2010-02-06 35 views
13

我們希望通過代碼啓用或禁用小部件。當我們說 「禁用」時,我們表示在應用 中註冊的小部件在 嘗試向其主屏幕添加小部件時不應顯示在用戶可用的小部件列表中。 這個問題已經被問到,很遺憾,很多次沒有 答案。動態啓用或禁用小部件不起作用

有一個響應由戴安娜Hackborn到這表明,有可能使用 軟件包管理器禁用部件單獨 小部件問題:

PackageManager pm = context.getPackageManager(); 
pm.setComponentEnabledSetting(new ComponentName("com.example.android.apis", ".appwidget.ExampleBroadcastReceiver"), 
    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, // or DISABLED 
    PackageManager.DONT_KILL_APP); 

然而,這是行不通的。小部件組件在小部件列表中仍將出現 。可能是AppWidgetService(位於Android源代碼的\ src \ base \ services \ java \ com \ android \ server上的Base.git中的 )加載了可用小部件列表,並緩存了可用小部件的此列表 。如果是這種情況,那麼上述 代碼啓用或禁用小部件組件將在 設備重置後工作,因爲不會有緩存;它不是。

我也嘗試尋找重寫某些方法的 AppWidgetProvider,如篩選出任何事件。我不認爲 這會去任何地方,因爲填充 列表的AppWidgetService使用軟件包管理器來查找在啓動時捕獲 ACTION_APPWIDGET_UPDATE操作的所有組件,並且在添加軟件包時添加了 (即新應用程序是安裝)。從此列表中刪除提供商的唯一時間是 在ACTION_PACKAGE_REMOVED廣播上。 因此,無論組件的啓用/禁用狀態如何,我都會查看實際的 列表活動,當用戶長按 單擊桌面並添加時,將顯示從Launcher應用程序中顯示的實際 列表活動一個widget:AppWidgetPickActivity Settings.GIT com.android.settings。這不幸的是,從AppWidgetService填充列表 直接,而無需爲 組件的啓用狀態的任何過濾: 無效putInstalledAppWidgets(列表項){安裝 清單= mAppWidgetManager.getInstalledProviders();putAppWidgetItems(installed,null,items); }

我很想看看有沒有人克服了這個障礙。也許我是 去錯誤的方式。我想要的只是能夠從用戶可用的小部件列表中刪除 小部件,當他們嘗試 將小部件添加到其主屏幕時。

+1

3年後,這個問題的任何更新? – 2014-03-29 21:12:15

回答

3

這可能是AppWidgetService (位於Android的源的 Base.git在 的\ src \基地\服務\ java中的\ com \ Android的 \服務器),它加載的 可用小部件列表,緩存這個可用小部件的列表 。

它確實如我所知。它將該列表存儲在mInstalledProviders;此列表將通過readStateFromFileLocked()添加到該列表中,該列表似乎是從系統啓動邏輯中調用的。

如果是這樣的情況下,雖然,然後 上面的代碼,其啓用或禁用 的插件組件將設備復位,因爲 就沒有高速緩存之後 工作;它不是。

您假設一個RAM緩存。緩存是一個XML文件。

這不幸的是,直接填充 列表從 AppWidgetService,沒有任何 濾波組件的enabled 狀態

這似乎是在Android的一個bug。更一般地說,我認爲整個緩存是bug - 如果緩存不同步,我無法恢復。

我建議你在public Android issue tracker上發佈你的文章作爲問題,如果你還沒有這樣做。

1

特徵

pm.setComponentEnabledSetting() 

作品ICS。當小部件被禁用時,它將從可用小部件列表中刪除。目前小小的安慰,但它至少已被糾正。

2

它爲我工作!我不得不使用DONT_KILL_APP,否則它會立即殺死我的應用程序。另外,我必須評論條件,以檢查它是否已經處於相同的狀態。

這是我創建的helper方法:

public void setMyCustomWidgetEnabled(boolean bEnable) 
    { 
     Log.d(LOG_TAG_NAME, "Entering setMyCustomWidgetEnabled(" + bEnable + ")..."); 

     PackageManager rPackageManager = getPackageManager(); 
     if(rPackageManager != null) 
     { 
      ComponentName rComponentName = new ComponentName(getBaseContext(), MyCustomWidget.class); 

      int nComponentEnabledState = rPackageManager.getComponentEnabledSetting(rComponentName); 

      if(bEnable) 
      { 
       //if(nComponentEnabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) 
       { 
        // Change the State to Enabled 
        rPackageManager.setComponentEnabledSetting(rComponentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); 

        Log.d(LOG_TAG_NAME, "-> Changed My Custom Widget' to ENABLED!"); 
       } 
      } 
      else 
      { 
       //if(nComponentEnabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) 
       { 
        // Change the State to Disabled 
        rPackageManager.setComponentEnabledSetting(rComponentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); 

        Log.d(LOG_TAG_NAME, "-> Changed 'My Custom Widget' to DISABLED!"); 
       } 
      } 
     } 

     Log.d(LOG_TAG_NAME, "Leaving setMyCustomWidgetEnabled(" + bEnable + ")..."); 
} 
+3

它看起來像啓用/禁用僅在清單中的接收器最初啓用時才起作用。如果它被清單禁用,則編程啓用/禁用不起作用。請你確認這一行爲? – 2014-03-29 21:26:06

+0

@ peter.bartos是的,它只在清單中最初啓用時纔有效。同樣爲了禁用小部件的應用程序,用戶需要強制退出應用程序才能'更新'小部件列表,如果它不以編程方式終止它的話。 – Cheruby 2018-02-21 16:06:47