【问题标题】:Android - adding AppWidgets to an ActivityAndroid - 将 AppWidgets 添加到 Activity
【发布时间】:2012-04-03 18:56:26
【问题描述】:

我最初的目标是将 Google 搜索小部件添加到活动的线性布局中。我需要包含它,就像它在启动器中显示和工作一样(这就是我需要能够添加小部件的原因)。


我想在我的活动中添加小部件,而不必启动小部件选择器活动。我试过了:

1。直接指定一个整数 id(我总是得到 inflate 错误)

2。得到这样的 id:

  ComponentName cn = new ComponentName(getBaseContext(), "com.android.quicksearchbox.SearchWidgetProvider");
  int[] ids = AppWidgetManager.getInstance(getApplicationContext()).getAppWidgetIds (cn);

(数组始终为空)

这些都不起作用。

在此之后,我有了这段代码,以使用 ID(如果我从小部件选择器活动中获取 ID,它就可以工作):

    AppWidgetProviderInfo withWidgetInfo = AppWidgetManager.getInstance(getApplicationContext()).getAppWidgetInfo(appWidgetId);
    AppWidgetHostView hostView = myWidgetHost.createView(getBaseContext(), appWidgetId, withWidgetInfo);
    hostView.setAppWidget(appWidgetId, withWidgetInfo);
    LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
    ll.addView(hostView);

我该怎么做?谢谢!

【问题讨论】:

    标签: android widget


    【解决方案1】:

    试试这个:

    // APPWIDGET_HOST_ID is any number you like
    appWidgetManager = AppWidgetManager.getInstance(this);
    appWidgetHost = new AppWidgetHost(this, APPWIDGET_HOST_ID);
    AppWidgetProviderInfo newAppWidgetProviderInfo = new AppWidgetProviderInfo();
    
    // Get an id
    int appWidgetId = appWidgetHost.allocateAppWidgetId();
    
    // Get the list of installed widgets
    List<AppWidgetProviderInfo> appWidgetInfos = new ArrayList<AppWidgetProviderInfo>();
    appWidgetInfos = appWidgetManager.getInstalledProviders();
    
    for(int j = 0; j < appWidgetInfos.size(); j++)
    {
        if (appWidgetInfos.get(j).provider.getPackageName().equals("com.android.quicksearchbox") && appWidgetInfos.get(j).provider.getClassName().equals("com.android.quicksearchbox.SearchWidgetProvider"))
        {
            // Get the full info of the required widget
            newAppWidgetProviderInfo = appWidgetInfos.get(j);
            break;
        }
     }
    
    // Create Widget
    AppWidgetHostView hostView = appWidgetHost.createView(this, appWidgetId, newAppWidgetProviderInfo);
    hostView.setAppWidget(appWidgetId, newAppWidgetProviderInfo);
    
    // Add it to your layout
    LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
    ll.addView(hostView);
    

    编辑

    要绑定小部件 ID,即更新小部件并响应用户交互,请参阅此处的解决方案:Widgets don't respond when re-added through code

    【讨论】:

    • 谢谢!这非常有用! :)
    • 上面的代码只是展示了小部件,但是没有appWidgetManager.bindAppWidgetId();
    • 但是appWidgetManager.bindAppWidgetId();只能由系统应用执行,对吧?即使我正在寻找解决方法,你能帮忙吗?
    • 你给了 LinearLayout 并说“将它添加到你的布局中”,但我想将它添加到手机的主屏幕上,我该怎么做
    • @KamranAhmed 如果我这样做(我正在尝试将日历添加到我的屏幕)我只能看到该小部件的容器,其中没有任何数据。它也是不可点击的,实际上它不会打开应用程序。任何想法为什么?谢谢
    【解决方案2】:

    好吧,我设法使代码可以工作(除了它应该而且不能那么容易工作 - 详细信息在下面提供)。

    应该工作的代码是:

            //create ComponentName for accesing the widget provider
            ComponentName cn = new ComponentName("com.android.quicksearchbox", "com.android.quicksearchbox.SearchWidgetProvider");
            //ComponentName cn = new ComponentName("com.android.music", "com.android.music.MediaAppWidgetProvider");
    
            //get appWidgetManager instance
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getBaseContext());
            //get list of the providers - .getAppWidgetIds (cn) does seem to be unrelated to widget hosting and more related to widget development
            final List<AppWidgetProviderInfo> infos = appWidgetManager.getInstalledProviders();
    
            //get AppWidgetProviderInfo
            AppWidgetProviderInfo appWidgetInfo = null;
            //just in case you want to see all package and class names of installed widget providers, this code is useful
            for (final AppWidgetProviderInfo info : infos) {
                Log.v("AD3", info.provider.getPackageName() + " / "
                        + info.provider.getClassName());
            }
            //iterate through all infos, trying to find the desired one
            for (final AppWidgetProviderInfo info : infos) {
                if (info.provider.getClassName().equals(cn.getClassName()) && info.provider.getPackageName().equals(cn.getPackageName())) {
                    //we found it
                    appWidgetInfo = info;
                    break;
                }
            }
            if (appWidgetInfo == null)
                return; //stop here
    
            //allocate the hosted widget id
            int appWidgetId = myWidgetHost.allocateAppWidgetId();
    
            //bind the id and the componentname - here's the problem!!!
            appWidgetManager.bindAppWidgetId(appWidgetId, cn); 
    
            //creat the host view
            AppWidgetHostView hostView = myWidgetHost.createView(getBaseContext(), appWidgetId, appWidgetInfo);
            //set the desired widget
            hostView.setAppWidget(appWidgetId, appWidgetInfo);
    
            //add the new host view to your activity's GUI
            LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
            ll.addView(hostView);
    

    好吧,问题是“appWidgetManager.bindAppWidgetId(appWidgetId, cn);” - 这需要清单中的 BIND_APPWIDGET 权限。 - 即使我们放了,它仍然不起作用。我读到它可能是为系统应用程序保留的

    但是,即使添加了权限并将apk放在system/app文件夹中,它仍然不起作用(它不会使其成为系统应用)。

    关于这个问题我找到了这个答案here:

    这是故意不提供给应用程序。如果你想 添加一个小部件,您需要启动选择器 UI 供用户选择 然后将负责绑定的小部件。小部件可以暴露 大量所有类型的私有数据,因此允许 应用程序在没有用户隐式的情况下任意绑定到它们 批准(通过选择 UI)。

    Dianne ... Android 框架工程师

    但是,我不确定,但是,也许这意味着如果我们可以使用图像开发人员的密钥对 apk 进行签名,我们可以实现所需的功能?但是,这不在问题的主题范围内。 但是,如果您碰巧能够向我解释如何有效地托管 AppWidgets,请执行并让我接受您的答案(市场上的启动器应用程序可以做到,所以它必须是可能的)。

    【讨论】:

      猜你喜欢
      • 2011-05-14
      • 2021-09-13
      • 1970-01-01
      • 2016-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-28
      • 1970-01-01
      相关资源
      最近更新 更多