明确的com.google.android.c2dm.intent.REGISTER意图

4

我很久以前从C2DM迁移到了GCM,因此我仍然通过创建com.google.android.c2dm.intent.REGISTER意图并将其传递给startService进行注册,正如GCM迁移文档中所指定的(该文档显然已过时):

Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app", PendingIntent.getBroadcast(context, 0, new Intent(), 0));
registrationIntent.putExtra("sender", "xxxxxx");
context.startService(registrationIntent);

从Android 5.0开始,意图必须是明确的:我该如何在这里做到这一点?我可以在意图上调用setComponent,但作为组件名称我应该使用什么?

2个回答

2
我使用一个函数来将 Implicit Intent 转换为 Explicit Intent:
Intent explicit = createExplicitFromImplicitIntent(mContext, registrationIntent);
startService(explicit);

public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
    // Retrieve all services that can match the given intent
    PackageManager pm = context.getPackageManager();
    List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
    if (resolveInfo == null ) {
        return null;
    }

    // Get component info and create ComponentName
    ResolveInfo serviceInfo = resolveInfo.get(0);
    String packageName = serviceInfo.serviceInfo.packageName;
    String className = serviceInfo.serviceInfo.name;
    ComponentName component = new ComponentName(packageName, className);

    // Create a new intent. Use the old one for extras and such reuse
    Intent explicitIntent = new Intent(implicitIntent);

    // Set the component to be explicit
    explicitIntent.setComponent(component);

    return explicitIntent;
}

1

您应该停止使用那个已经过时的意图。从2013年中期开始,推荐的注册GCM的方式是通过Google Play服务库,并且它只需要调用GoogleCloudMessaging类的一个register方法。

示例(摘自官方演示):

GoogleCloudMessaging gcm;
...

/**
 * Registers the application with GCM servers asynchronously.
 * <p>
 * Stores the registration ID and the app versionCode in the application's
 * shared preferences.
 */
private void registerInBackground() {
    new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            String msg = "";
            try {
                if (gcm == null) {
                    gcm = GoogleCloudMessaging.getInstance(context);
                }
                regid = gcm.register(SENDER_ID);
                msg = "Device registered, registration ID=" + regid;

                // You should send the registration ID to your server over HTTP, so it
                // can use GCM/HTTP or CCS to send messages to your app.
                sendRegistrationIdToBackend();

                // For this demo: we don't need to send it because the device will send
                // upstream messages to a server that echo back the message using the
                // 'from' address in the message.

                // Persist the regID - no need to register again.
                storeRegistrationId(context, regid);
            } catch (IOException ex) {
                msg = "Error :" + ex.getMessage();
                // If there is an error, don't just keep trying to register.
                // Require the user to click a button again, or perform
                // exponential back-off.
            }
            return msg;
        }

        @Override
        protected void onPostExecute(String msg) {
            mDisplay.append(msg + "\n");
        }
    }.execute(null, null, null);
}

请注意,注册是在后台完成的(通过一个AsyncTask),因为新的注册方法是阻塞的,所以不能在主线程上调用。

1
如果有一种简单的方法可以继续使用旧的方式(而且对最终用户没有任何影响),我宁愿不重写整个注册逻辑,你懂的? - Mohamed Hafez
@MohamedHafez 你可以继续使用已经过时的旧代码,希望它仍然能够正常工作。 - Eran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接