一旦收到广播意图CONNECTIVITY_CHANGE,如何更新小部件

时间:2012-06-24 22:33:30

标签: android android-intent android-widget intentfilter

每当网络数据包数据连接发生变化时,我想更新小部件文本及其颜色。即使这个小部件也可以启用/禁用网络数据包数据。 android.net.conn.CONNECTIVITY_CHANGE的广播接收器已在Android清单文件中注册,而onReceive()已在AppWidgetProvider类中重写。

每当我启用/禁用连接onReceive()被触发两次时,我注意到一种非常奇怪的行为。在第一个实例中,我收到NetworkInfo个对象,但在第二个实例中,我没有收到信息实例。   但是当我通过系统设置启用/禁用连接时,onReceive()会被触发一次并且NetworkInfo对象为空。

这是我的清单文件。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.rakesh.simplewidget"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />
    <!-- Permissions -->
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >

        <!-- Widget Broadcast receiver -->
        <receiver
            android:name=".ExampleAppWidgetProvider"
            android:label="Widget ErrorBuster" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>

            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widget1_info" />
        </receiver>
        <service android:name=".UpdateWidgetService"></service>
    </application>
</manifest>

我的AppWidgetProvider类如下。

public class ExampleAppWidgetProvider extends AppWidgetProvider {

 int[] mAppWidgetIds;

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

  final int N = appWidgetIds.length;
  this.mAppWidgetIds = appWidgetIds;


  // Get all ids
  ComponentName thisWidget = new ComponentName(context,
   ExampleAppWidgetProvider.class);
  int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

  // Build the intent to call the service
  Intent intent = new Intent(context.getApplicationContext(),
   UpdateWidgetService.class);
  intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);

  // Update the widgets via the service
  context.startService(intent);
 }

 @Override
 public void onReceive(Context context, Intent intent) {
  super.onReceive(context, intent);
  NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);

  StringBuilder str = new StringBuilder();
  if (info != null) {
   str.append(" info is NULL");
  }
  if (checkConnectivityState(context)) {
   str.append("; data is enable");
  } else {
   str.append("; data is disable");
  }
  Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
 }

 public static void updateAppWidget(Context context,
  int[] appWidgetIds, boolean enable) {
  if (appWidgetIds == null) {
   return;
  }
  if (appWidgetIds.length > 0) {

   AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
   RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.widget1);
   if (enable) {
    updateViews.setTextColor(R.id.BtEnableDisable, Color.GREEN);
    updateViews.setTextViewText(R.id.BtEnableDisable, "Enabled");

   } else {
    updateViews.setTextColor(R.id.BtEnableDisable, Color.GRAY);
    updateViews.setTextViewText(R.id.BtEnableDisable, "Disabled");
   }
   appWidgetManager.updateAppWidget(appWidgetIds, updateViews);
   Toast.makeText(context, "updateAppWidget() ", Toast.LENGTH_SHORT).show();

  }
 }

 private boolean checkConnectivityState(Context context) {
  final TelephonyManager telephonyManager = (TelephonyManager) context
   .getSystemService(Context.TELEPHONY_SERVICE);
  return telephonyManager.getDataState() == TelephonyManager.DATA_CONNECTED;

 }
}

启用/禁用网络数据包数据连接的服务类。

public class UpdateWidgetService extends Service {
    private static final String LOG = "de.vogella.android.widget.example";

    @Override
    public void onStart(Intent intent, int startId) {
        Log.i(LOG, "Called");
        // Create some random data

        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this
                .getApplicationContext());

        int[] allWidgetIds = intent
                .getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);

        ComponentName thisWidget = new ComponentName(getApplicationContext(),
                ExampleAppWidgetProvider.class);
        int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
        Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
        Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));

        for (int widgetId : allWidgetIds) {
            // Create some random data
            int number = (new Random().nextInt(100));

            RemoteViews remoteViews = new RemoteViews(this
                    .getApplicationContext().getPackageName(),
                    R.layout.widget1);
            Log.w("WidgetExample", String.valueOf(number));
            EnableDisableConnectivity edConn = new EnableDisableConnectivity(this.getApplicationContext());
            edConn.enableDisableDataPacketConnection(!checkConnectivityState(this.getApplicationContext()));

            // Register an onClickListener
            Intent clickIntent = new Intent(this.getApplicationContext(),
                    ExampleAppWidgetProvider.class);

            clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
            clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,
                    allWidgetIds);

            PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.BtEnableDisable, pendingIntent);
            appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }
        stopSelf();

        super.onStart(intent, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private boolean checkConnectivityState(Context context){
        final TelephonyManager telephonyManager = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        return telephonyManager.getDataState() == TelephonyManager.DATA_CONNECTED;

    }
}

我还尝试使用Broadcast Receiver类,只要连接发生变化,我就会收到NetworkInfo。但我不知道如何从广播接收器更新小部件文本/颜色。

有没有其他方法可以在收到CONNECTIVITY_CHANGE意图后更新窗口小部件文本/颜色?

编辑:

我无法弄清楚为什么我在AppWidgetProvider中获得两个CONNECTIVITY_CHANGE意图,但我学会了如何从广播接收器更新小部件,下面是代码。

public class ConnectivityReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        NetworkInfo info = (NetworkInfo)intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);

        if(info.getType() == ConnectivityManager.TYPE_MOBILE){

            RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                    R.layout.widget1);

            if(info.isConnectedOrConnecting()){
                Toast.makeText(context, "Data packet enabled", Toast.LENGTH_SHORT).show();
                Log.d("RK","Mobile data is enabled");
                remoteViews.setTextColor(R.id.BtEnableDisable, Color.GREEN);
                remoteViews.setTextViewText(R.id.BtEnableDisable, "Enabled");
            }else{
                Toast.makeText(context, "Data packet disabled", Toast.LENGTH_SHORT).show();
                Log.e("RK","Mobile data is disconnected");
                remoteViews.setTextColor(R.id.BtEnableDisable, Color.BLACK);
                remoteViews.setTextViewText(R.id.BtEnableDisable,"Disabled");
            }

            ComponentName thiswidget = new ComponentName(context, ExampleAppWidgetProvider.class);
            AppWidgetManager manager = AppWidgetManager.getInstance(context);
            manager.updateAppWidget(thiswidget, remoteViews);

        }
    }

}

如果有人知道我为什么会收到两个CONNECTIVITY_CHANGE意图,请在此处分享您的想法。你会在这里得到帮助。

1 个答案:

答案 0 :(得分:4)

现在我已经发现,当单击按钮启用/禁用网络时,为什么onReceive()被调用两次。 1.第一次在APPWIDGET_UPDATE意图广播时调用它。 2.第二次在CONNECTIVITY_CHANGE意图广播时调用它。

无论如何我能够从Broadcast接收器更新小部件,源代码已经发布在上面的帖子中。