Android小部件:从Appwidgetprovider的onUpdate调用BroadcastReceiver onReceive

Android小部件:从Appwidgetprovider的onUpdate调用BroadcastReceiver onReceive,android,Android,我正在制作一个手电筒小部件,它将打开/关闭手电筒,并且我尝试在单击小部件按钮时切换小部件按钮的图标,为此,我有一个Appwidgetprovider,它的onUpdate将使用RemoteView并调用BroadcastReceiver 在BroadcastReceiver中,onReceive功能将为小部件执行闪光灯切换和图标切换。 我面临的问题是onReceive函数没有被调用,小部件也没有发生任何操作 代码如下: AppWidgetProvider类: public class Widge

我正在制作一个手电筒小部件,它将打开/关闭手电筒,并且我尝试在单击小部件按钮时切换小部件按钮的图标,为此,我有一个Appwidgetprovider,它的onUpdate将使用RemoteView并调用BroadcastReceiver

在BroadcastReceiver中,onReceive功能将为小部件执行闪光灯切换和图标切换。 我面临的问题是onReceive函数没有被调用,小部件也没有发生任何操作

代码如下:

AppWidgetProvider类:

public class WidgetActivity extends AppWidgetProvider {
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Intent receiver = new Intent(context, WidgetActivity.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_flash_layout);
        views.setOnClickPendingIntent(R.id.imageButton1, pendingIntent);

        appWidgetManager.updateAppWidget(appWidgetIds, views);

    }
}
广播接收器类别:

public class WidgetService extends BroadcastReceiver {
    private static boolean isLightOn = false;
    private static Camera camera;

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub

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

        if (isLightOn) {
            views.setImageViewResource(R.id.imageButton1,
                    R.drawable.light_off_widget);
        } else {
            views.setImageViewResource(R.id.imageButton1,
                    R.drawable.light_on_widget);
        }

        AppWidgetManager appWidgetManager = AppWidgetManager
                .getInstance(context);
        appWidgetManager.updateAppWidget(new ComponentName(context,
                WidgetActivity.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, "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, "no flash", Toast.LENGTH_SHORT)
                            .show();
                }
            }
        }
    }
}
舱单:

<receiver android:name="com.widget.WidgetActivity">
    <intent-filter>
              <action
                 android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
              android:name="android.appwidget.provider"
              android:resource="@xml/flash_widget" />
</receiver>

<receiver android:name="com.widget.WidgetService">

    <action android:name="COM_FLASHLIGHT"></action>

</receiver>

在清单中,我将小部件服务的
标记用
,因为它显示了一条警告:“导出的接收器不需要许可”

您的意图
组件类
应该是
广播接收器类
,而不是
WidgetProvider

改变这个

 Intent receiver = new Intent(context, WidgetActivity.class);

当您使用
pendingent.getBroadcast
时,它期望
意图被广播
。因此,当您单击
小部件中的按钮时,将调用
广播接收器
onResume

您实际上不需要在此处为
接收器设置任何
操作

但是如果您想使用自定义的
意图
,那么您可以像这样设置
意图操作

 Intent receiver = new Intent("COM_FLASHLIGHT");
public class WidgetService extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    if(intent.getAction().equalsIgnoreCase("COM_FLASHLIGHT")){
          // do your stuff for this action.
    }
}
manifest
中的接收者应向
intent filter
注册以处理自定义操作

 <receiver android:name=".services.WidgetService">
     <intent-filter>
        <action android:name="COM_FLASHLIGHT"></action>
     </intent-filter>
 </receiver>
自定义
操作
通常是在
远程视图中有多个操作时定义的

您的意图
组件类
应该是
广播接收器类
,而不是
WidgetProvider

改变这个

 Intent receiver = new Intent(context, WidgetActivity.class);

当您使用
pendingent.getBroadcast
时,它期望
意图被广播
。因此,当您单击
小部件中的按钮时,将调用
广播接收器
onResume

您实际上不需要在此处为
接收器设置任何
操作

但是如果您想使用自定义的
意图
,那么您可以像这样设置
意图操作

 Intent receiver = new Intent("COM_FLASHLIGHT");
public class WidgetService extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    if(intent.getAction().equalsIgnoreCase("COM_FLASHLIGHT")){
          // do your stuff for this action.
    }
}
manifest
中的接收者应向
intent filter
注册以处理自定义操作

 <receiver android:name=".services.WidgetService">
     <intent-filter>
        <action android:name="COM_FLASHLIGHT"></action>
     </intent-filter>
 </receiver>
自定义
操作
通常是在
远程视图中有多个操作时定义的
如果您阅读了文档,则在触发notifyDataSetChanged()时,将调用RemoteViewsService中的onDataSetChanged

因此,如果您想从onReceive()方法更新WidgetService,可以调用 来自AppWidgetManager的notifyAppWidgetViewDataChanged()方法

@Override
public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);

    int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
    AppWidgetManager.getInstance(context)
            .notifyAppWidgetViewDataChanged(ids, R.id.stack_view_movies);
}
如果您阅读了文档,则在触发notifyDataSetChanged()时,将调用RemoteViewsService中的onDataSetChanged

因此,如果您想从onReceive()方法更新WidgetService,可以调用 来自AppWidgetManager的notifyAppWidgetViewDataChanged()方法

@Override
public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);

    int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
    AppWidgetManager.getInstance(context)
            .notifyAppWidgetViewDataChanged(ids, R.id.stack_view_movies);
}

我的小部件中有一个刷新按钮。我想执行
onUpdate()
并尝试使用
按钮1.setonClickPendingContent()
函数,但它不起作用。有什么想法吗?我的小部件中有一个刷新按钮。我想执行
onUpdate()
并尝试使用
按钮1.setonClickPendingContent()
函数,但它不起作用。有什么想法吗?