从 Activity 手动更改小部件状态

Posted

技术标签:

【中文标题】从 Activity 手动更改小部件状态【英文标题】:Manually change widget state from Activity 【发布时间】:2012-07-18 13:14:36 【问题描述】:

我的应用有一个小部件,当我们点击它时它会点亮 LED 闪光灯,当我们再次点击它时它会关闭它。

这是代码(感谢来自 post 的 Kartik):

WidgetProvider.java

public class WidgetProvider extends AppWidgetProvider 

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) 

        Intent receiver = new Intent(context, WidgetReceiver.class);
        receiver.setAction("COM_FLASHLIGHT");
        receiver.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                receiver, 0);

        RemoteViews views = new RemoteViews(context.getPackageName(),
                R.layout.widget);

        views.setOnClickPendingIntent(R.id.imageButtonWidget, pendingIntent);

        appWidgetManager.updateAppWidget(appWidgetIds, views);

    

WidgetReceiver.java

public class WidgetReceiver extends BroadcastReceiver 
    public static boolean isLightOn = false;
    public static Camera camera;

    @Override
    public void onReceive(Context context, Intent intent) 
        RemoteViews views = new RemoteViews(context.getPackageName(),
                R.layout.widget);

        if (isLightOn) 
            views.setImageViewResource(R.id.imageButtonWidget,
                    R.drawable.widget_lamp_button_default);
         else 
            views.setImageViewResource(R.id.imageButtonWidget,
                    R.drawable.widget_lamp_button_checked);
        


        AppWidgetManager appWidgetManager = AppWidgetManager
                .getInstance(context);
        appWidgetManager.updateAppWidget(new ComponentName(context,
                WidgetProvider.class), views);


        if (isLightOn) 
            if (camera != null) 
                camera.stopPreview();
                camera.release();
                camera = null;
            
            isLightOn = false;


         else 
            // Open the default i.e. the first rear facing camera.
            camera = Camera.open();
            if (camera == null) 
                Toast.makeText(context, "R.string.no_camera",
                        Toast.LENGTH_SHORT).show();

             else 
                // Set the torch flash mode
                Parameters param = camera.getParameters();
                param.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                try 
                    camera.setParameters(param);
                    camera.startPreview();
                    isLightOn = true;
                 catch (Exception e) 
                    Toast.makeText(context, "R.string.no_flash",
                            Toast.LENGTH_SHORT).show();
                
            
        
    

现在我想从我的应用程序中关闭小部件。在我的应用程序的主要活动中使用此代码,我可以释放小部件拍摄的相机:

MainActivity.java

//Stop widget camera
        if (WidgetReceiver.isLightOn)
        Camera a = WidgetReceiver.camera;
        a.stopPreview();
        a.release();
        a = null;
        WidgetReceiver.isLightOn=false;

但问题是小部件仍设置为选中的可绘制对象 (R.drawable.widget_lamp_button_checked)。所以 FlashLight 已经很好地关闭了,但我仍然需要强制小部件将其可绘制设置为未选中的 (R.drawable.widget_lamp_button_default)。

我该怎么做?

编辑:问题已解决

WidgetProvider.java

   public class WidgetProvider extends AppWidgetProvider 

        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                int[] appWidgetIds) 

             // Set widget's drawable to unchecked

            RemoteViews views2 = new RemoteViews(context.getPackageName(),
                    R.layout.widget);
            AppWidgetManager mManager = AppWidgetManager.getInstance(MainActivity
                    .getContext());
            ComponentName cn = new ComponentName(MainActivity.getContext(),
                    WidgetProvider.class);
            views2.setImageViewResource(R.id.imageButtonWidget,
                    R.drawable.widget_lamp_button_default);
            mManager.updateAppWidget(cn, views2);


            // Widget OnClick Behavior

            Intent receiver = new Intent(context, WidgetReceiver.class);
            receiver.setAction("COM_FLASHLIGHT");
            receiver.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
                    receiver, 0);

            RemoteViews views = new RemoteViews(context.getPackageName(),
                    R.layout.widget);

            views.setOnClickPendingIntent(R.id.imageButtonWidget, pendingIntent);

            appWidgetManager.updateAppWidget(appWidgetIds, views);

        
    

WidgetReceiver.java -> 保持不变

MainActivity.java

    public class MainActivity extends Activity 
        private static Context mContext;

        public static Context getContext() 
            return mContext;
        


       @Override
        public void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);

            mContext = this;


                   //Stop widget camera

                    if (WidgetReceiver.isLightOn)
                    Camera a = WidgetReceiver.camera;
                    a.stopPreview();
                    a.release();
                    a = null;
                    WidgetReceiver.isLightOn=false;


        // Fire Widget's update with Intent 

        Intent intent = new Intent(this, WidgetProvider.class);
                intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
                // Use an array and EXTRA_APPWIDGET_IDS instead of
                // AppWidgetManager.EXTRA_APPWIDGET_ID,
                // since it seems the onUpdate() is only fired on that:
                int[] ids =  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ;
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
                sendBroadcast(intent);


【问题讨论】:

【参考方案1】:

在 AppWidgetProvider 的 onReceive() 方法中,使用 AppWidgetManager 类的 updateAppWidget 方法向您的 AppWidgetProvider 发送广播并更新您的小部件:

@Override
public void onReceive(Context context, Intent intent) 


    ...
    views = new RemoteViews(context.getPackageName(),
    R.layout.yourwidgetlayout);
    AppWidgetManager mManager = AppWidgetManager.getInstance(App
    .getContext());
    ComponentName cn = new ComponentName(App.getContext(),
    YourAppWidgetProvider.class);
    //change your views,here I change text of text view witch it's id is "widgettextview" 
    views.setTextViewText(R.id.widgettextview, "lastWord");
    mManager.updateAppWidget(cn, views);
    ...
     

这里是应用定义:

public class App extends Application implements OnInitListener 

    private static Context mContext;

    public void onCreate() 
        super.onCreate();
        mContext = this;
        
    public static Context getContext() 
        return mContext;
    

【讨论】:

抱歉,我不明白App 类的用法。为什么要使用与TextToSpeech api 相关的OnInitListener 好的,感谢您的回答,我已经解决了我的问题,但我没有使用您的 App 课程,但我从 MainActivity 课程中获得了上下文(这可能是您的意思和我不明白?)。无论如何,问题已解决(见帖子),感谢您的回答:)。

以上是关于从 Activity 手动更改小部件状态的主要内容,如果未能解决你的问题,请参考以下文章

从 Activity 更新 Android 小部件

Flutter - 无法从父小部件更改子状态

当 Android 中的 Activity 内容更改时,小部件不更新

Flutter 从相关的小部件类更改状态

从另一个小部件更改一个小部件中的状态

如何从另一个小部件设置状态?