美文网首页
Widget 的获取和显示

Widget 的获取和显示

作者: 无良安生 | 来源:发表于2024-01-25 11:02 被阅读0次

背景:在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);
}

相关文章

网友评论

      本文标题:Widget 的获取和显示

      本文链接:https://www.haomeiwen.com/subject/djlmodtx.html