Android:加载三方应用的小部件到自己APP显示

两种方式:

1、自己加载小部件列表做选择要显示的小部件

2、调用系统的弹窗做选择要显示的小部件

直接贴代码:

java 复制代码
public class TempActivity extends FragmentActivity {
    private ActivityTempBinding viewBinding;
    private AppWidgetManager appWidgetManager;
    private AppWidgetHost appWidgetHost;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        viewBinding = ActivityTempBinding.inflate(getLayoutInflater());
        setContentView(viewBinding.getRoot());

        Context applicationContext = getApplicationContext();

        appWidgetManager = AppWidgetManager.getInstance(applicationContext);
        appWidgetHost = new AppWidgetHost(applicationContext, 0x200);
        appWidgetHost.startListening();
        FrameLayout frameLayout = viewBinding.framelayout;

        // 方式一:自己加载小部件列表做选择显示
        RecyclerView recyclerView = viewBinding.recycler;
        List<AppWidgetProviderInfo> installedProviders = appWidgetManager.getInstalledProviders();
        MyRecyclerAdapter adapter = new MyRecyclerAdapter(installedProviders);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        adapter.setListener(v -> {
            AppWidgetProviderInfo info = (AppWidgetProviderInfo) v.getTag();
            int widgetId = appWidgetHost.allocateAppWidgetId();
            AppWidgetHostView appWidgetHostView = appWidgetHost.createView(this, widgetId, info);
            int widgetWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
            int widgetHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widgetWidth, widgetHeight);
            frameLayout.removeAllViews();
            frameLayout.addView(appWidgetHostView, params);

            Bundle options = appWidgetManager.getAppWidgetOptions(widgetId);
            boolean success = appWidgetManager.bindAppWidgetIdIfAllowed(widgetId, info.provider, options);
            if (!success) {
                startBind(widgetId, info, options);
            }
        });


        // 方式二:使用系统自带的弹窗选择小部件
        viewBinding.btn.setOnClickListener(v -> {
            int widgetId = appWidgetHost.allocateAppWidgetId();
            Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
            pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
            startActivityForResult(pickIntent, 200);
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && data != null) {
            if (requestCode == 100) {
                createWidget(data);
            } else if (requestCode == 200) {
                addWidget(data);
            } else if (requestCode == 300) {
                addWidget(data);
            }
        }
    }

    private void createWidget(Intent data) {
        // 获取选择的widget的id
        int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,	-1);
        // 获取所选的Widget的AppWidgetProviderInfo信息
        AppWidgetProviderInfo appWidget = appWidgetManager.getAppWidgetInfo(appWidgetId);
        // 根据AppWidgetProviderInfo信息,创建HostView
        View hostView = appWidgetHost.createView(this, appWidgetId, appWidget);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        viewBinding.framelayout.removeAllViews();
        viewBinding.framelayout.addView(hostView, params);
        Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
        boolean success = appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, appWidget.provider, options);
        // 系统调起的总是return false
//        if (!success) {
//            startBind(appWidgetId, appWidget, options);
//        }
    }

    private void startBind(int appWidgetId, AppWidgetProviderInfo info, Bundle options) {
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.provider);
        // This is the options bundle described in the preceding section.
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
        startActivityForResult(intent, 300);
    }

    // 添加选择的widget。需要判断其是否含有配置,如果有,需要首先进入配置
    private void addWidget(Intent data) {
        int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                -1);
        AppWidgetProviderInfo appWidget = appWidgetManager.getAppWidgetInfo(appWidgetId);
        Log.d("AppWidget", "configure:" + appWidget.configure);
        if (appWidget.configure != null) {
            // 有配置,弹出配置
            Intent intent = new Intent(
                    AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
            intent.setComponent(appWidget.configure);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            startActivityForResult(intent, 200);
        } else {
            // 没有配置,直接添加
            onActivityResult(100, RESULT_OK, data);
        }
    }

}

注意,Activity一定不能继承AppCompatActivity,他会将小部件内部的控件都改写成了AppCompatXXXX,导致小部件不能显示。

相关推荐
移动开发者1号1 小时前
ReLinker优化So库加载指南
android·kotlin
山野万里__1 小时前
C++与Java内存共享技术:跨平台与跨语言实现指南
android·java·c++·笔记
Huckings1 小时前
Android 性能问题
android
移动开发者1号2 小时前
剖析 Systrace:定位 UI 线程阻塞的终极指南
android·kotlin
移动开发者1号2 小时前
深入解析内存抖动:定位与修复实战(Kotlin版)
android·kotlin
whysqwhw2 小时前
OkHttp深度架构缺陷分析与革命性演进方案
android
Digitally4 小时前
如何将文件从 iPhone 传输到 Android(新指南)
android·ios·iphone
whysqwhw5 小时前
OkHttp深度架构缺陷分析与演进规划
android
用户7093722538515 小时前
Android14 SystemUI NotificationShadeWindowView 加载显示过程
android
木叶丸5 小时前
跨平台方案该如何选择?
android·前端·ios