Android-Widget:从Appwidgetprovider的onUpdate调用BroadcastReceiver onReceive

时间:2014-05-08 04:38:38

标签: android

我正在制作一个手电筒小部件,它将打开/关闭手电筒,我也试图在点击小部件按钮时切换小部件按钮的图标,为此我有了Appwidgetprovider,其onUpdate将使用RemoteViews并调用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);

    }
}

BroadcastReceiver类:

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>

在清单中,我包装了小部件服务的<action>标记  <intent-filter>因为它显示警告说&#34;导出的接收器不需要许可&#34;。

2 个答案:

答案 0 :(得分:5)

onReceive function is not being called and no action happening with the widget

您的意图component class应该是Broadcast Receiver class,而不是WidgetProvider

更改此

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

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

当您使用PendingIntent.getBroadcast时,它会指向Intent to be broadcast。因此,当您点击widget中的按钮时,系统会调用Broadcast Receiver onResume

您不需要在Action设置任何receiver

但是如果您想使用自定义Intent,那么您可以像这样设置Intent action

 Intent receiver = new Intent("COM_FLASHLIGHT");

并且manifest中的接收者应该注册intent-filter来处理自定义操作。

 <receiver android:name=".services.WidgetService">
     <intent-filter>
        <action android:name="COM_FLASHLIGHT"></action>
     </intent-filter>
 </receiver>

因此,当调用BroadCast Receiver onReceive时,您可以检查此类具体操作

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.
    }
}

自定义Actions通常是在RemoteView中有多个操作时定义的。

答案 1 :(得分:0)

enter image description here 如果您阅读该文档,则在触发 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);
}