背景:在Launcher中加载桌面布局的时候,显示默认的Widget布局
1.通过选择Widget的方式将Widget加载到界面中
以下是简单封装的一个工具类(选择Widget的工具类)和工具类的使用:
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_main);
hostViews1 = findViewById(R.id.main_host1);
selectWidget = new SelectWidget(this);
selectWidget.setResult(new HostViewResult() {
@Override
public void bindHostView(AppWidgetHostView view) {
hostViews1.addView(view);
}
});
findViewById(R.id.tv_select).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "VERSION: " + Build.VERSION.SDK_INT);
selectWidget.showWidgetPick();
}
});
}
package com.android.utillib;
import android.app.Activity;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.activity.ComponentActivity;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.ActivityResultRegistry;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityOptionsCompat;
public class SelectWidget {
//创建mAppWidgetHost的时候传入的ID,固定为1024
private final static int HOST_ID = 1024;
private static final String TAG = SelectWidget.class.getSimpleName();
//onActivityResult的用法
ActivityResultLauncher<Intent> launcherCreateWidget;
//onActivityResult的用法,调用选择Widget的请求
ActivityResultLauncher<Intent> launcherSelectWidget;
private Object mLock = new Object();
//接口回调,用于UI更新
private HostViewResult result;
private AppWidgetManager mAppWidgetManager;
private AppWidgetHost mAppWidgetHost;
private ComponentActivity mContext;
SelectWidget(ComponentActivity context) {
this.mContext = context;
mAppWidgetManager = AppWidgetManager.getInstance(context);
mAppWidgetHost = new AppWidgetHost(context, HOST_ID);
//启动Widget的监听,这样才能响应Widget的UI刷新和点击
mAppWidgetHost.startListening();
//注册ActivityResult
registerForActivityResult(context);
}
/**
* 设置UI刷新接口
* @param result
*/
public void setResult(HostViewResult result) {
this.result = result;
}
/**
* onActivityResult 方法已经被废弃,使用一下方式替代onActivityResult 方式
* 请求方式: launcher.launch(I);
* @param context
*/
private void registerForActivityResult(ComponentActivity context){
launcherSelectWidget = context.registerForActivityResult(new WidgetResultContract(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult data) {
if (data==null) return;
int resultCode =data.getResultCode();
Intent dataInten =data.getData();
Log.i(TAG, "onActivityResult: resultCode =" + resultCode);
addAppWidget(dataInten);
}
});
launcherCreateWidget = context.registerForActivityResult(new WidgetResultContract(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult data) {
if (data==null) return;
completeAddAppWidget(mContext,data.getData());
}
});
}
/**
* 显示Widget选择弹窗
*/
void showWidgetPick() {
int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
launcherSelectWidget.launch(pickIntent);
}
void addAppWidget(Intent data) {
// TODO: catch bad widget exception when sent
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
if (appWidget == null) {
return;
}
//widget 包含设置信息不为空,则启动widget的设置界面
if (appWidget.configure != null) {
// Launch over to configure widget, if needed
Intent intent = new Intent(
AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setComponent(appWidget.configure);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
launcherCreateWidget.launch(intent);
} else {
// widget 包含设置信息为空,直接添加widget到layout中
// Otherwise just add it
completeAddAppWidget(mContext,data);
}
}
/**
* 添加widget信息到layout中
*
* @param data 包含了widget的信息
*/
private void completeAddAppWidget(Context context, Intent data) {
Bundle extras = data.getExtras();
int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
Log.i(TAG, "dumping extras content=" + appWidgetInfo.provider.getPackageName());
// Perform actual inflation because we're live
synchronized (mLock) {
//获取显示widget的view
AppWidgetHostView mHostView = mAppWidgetHost.createView(context, appWidgetId,
appWidgetInfo);
mHostView.setAppWidget(appWidgetId, appWidgetInfo);
if (result != null) {
result.bindHostView(mHostView);
}
mHostView.requestLayout();
}
}
/**
* onActivityResult 输入输出处理类
*/
private class WidgetResultContract extends ActivityResultContract<Intent,ActivityResult>{
@NonNull
@Override
public Intent createIntent(@NonNull Context context, Intent intent) {
//ActivityResultLauncher.launcher(I) 对传入的数据进行处理,这里只是将传入的数据直接往下传输,并没有特殊处理
return intent;
}
@Override
public ActivityResult parseResult(int resultCode, @Nullable Intent intent) {
//对返回值的处理方法,返回的是resultCode和intent
//这里是将返回值封装到ActivityResult,然后返回,传入到结果回调监听ActivityResultCallback
return new ActivityResult(resultCode,intent);
}
}
}
2.获取所有的WidgetView
注意:因为不能获取到appWidgetId,所以这里需要提到一种方式,如下代码:
//通过allocateAppWidgetId获取到一个appWidgetHost 提供的 appWidgetId
int appWidgetId = appWidgetHost.allocateAppWidgetId();
//然后通过bindAppWidgetIdIfAllowed 将Id和provider关联一起
//需要是系统应用,不然一直返回fales,也就无法绑定成功
boolean success = widgetManager.bindAppWidgetIdIfAllowed(appWidgetId, appWidgetInfo.provider, null);
使用方式
final HostViewResult result = new HostViewResult() {
@Override
public void bindHostView(AppWidgetHostView view) {
hostViews1.addView(view);
}
};
createWidget = new CreateWidget(this);
createWidget.setResult(result);
findViewById(R.id.tv_load).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hostViews1.removeAllViews();
createWidget.bindWidgetVies();
}
});
工具类:
public class CreateWidget {
private static final String TAG = CreateWidget.class.getSimpleName();
private AppWidgetManager mAppWidgetManager;
private AppWidgetHost mAppWidgetHost;
private Context mContext;
private HostViewResult result;
private Object mLock = new Object();
public CreateWidget(Context mContext) {
this.mContext = mContext;
mAppWidgetManager = AppWidgetManager.getInstance(mContext);
mAppWidgetHost = new AppWidgetHost(mContext, 1024);
mAppWidgetHost.startListening();
}
public void bindWidgetVies() {
List<AppWidgetProviderInfo> providerInfos = getWidgetInfos();
for (AppWidgetProviderInfo providerInfo:providerInfos){
createWidgetView(providerInfo);
}
}
public void setResult(HostViewResult result) {
this.result = result;
}
private List<AppWidgetProviderInfo> getWidgetInfos() {
List<AppWidgetProviderInfo> providerInfos = mAppWidgetManager.getInstalledProviders();
//过滤一些不需要的东西
return providerInfos.stream().filter(info-> !info.provider.getPackageName().contains("com.android")).collect(Collectors.toList());
}
private void createWidgetView(AppWidgetProviderInfo appWidgetInfo) {
int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
Log.i(TAG, "getWidgetInfo packageName : " + appWidgetInfo.provider.getPackageName());
boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, appWidgetInfo.provider, null);
Log.i(TAG, "getWidgetInfo appWidgetId : " + success);
synchronized (mLock) {
//获取显示widget的view
AppWidgetHostView mHostView = mAppWidgetHost.createView(mContext, appWidgetId, appWidgetInfo);
mHostView.setAppWidget(appWidgetId, appWidgetInfo);
if (result != null) {
result.bindHostView(mHostView);
}
mHostView.requestLayout();
}
}
}
最后给个公共类
public interface HostViewResult {
void bindHostView(AppWidgetHostView view);
}
网友评论