С тех пор, как я пытался обновить мое Android-приложение из Eclipse до Android Studio (преобразование в простой проект), у меня возникали проблемы.Я думаю, что я сгладил большинство из них, но я не могу получать уведомления от GCM (что является важной частью приложения).
Вот сообщение, которое я с телефона Android получаю сообщение GCM(эти сообщения отправляются с сервера мультикастинга на несколько устройств Android):
--------- beginning of main
2018-10-26 15:46:36.222 2921-2921/com.ddv.android.gcm.support.app V/GCMBroadcastReceiver: onReceive: com.google.android.c2dm.intent.RECEIVE
2018-10-26 15:46:36.222 2921-2921/com.ddv.android.gcm.support.app V/GCMBroadcastReceiver: GCM IntentService class: com.ddv.android.gcm.support.app.GCMIntentService
2018-10-26 15:46:36.225 2921-2921/com.ddv.android.gcm.support.app V/GCMBaseIntentService: Acquiring wakelock
2018-10-26 15:46:36.226 1686-3213/? W/ActivityManager: Unable to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x10 pkg=com.ddv.android.gcm.support.app cmp=com.ddv.android.gcm.support.app/com.activate.gcm.GCMIntentService (has extras) } U=0: not found
Вот мой AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ddv.android.gcm.support.app"
android:versionCode="1"
android:versionName="1.0" >
...
<permission
android:name="com.ddv.android.gcm.support.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.ddv.android.gcm.support.app.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.ddv.android.gcm.support.app.permission.RECEIVE" />
...
<application
android:icon="@drawable/ddv_launcher"
android:label="@string/app_name"
android:theme="@style/PulseAppTheme"
android:allowBackup="false"
android:name=".GlobalVariables" >
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:enabled="true"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.ddv.android.gcm.support.app" />
</intent-filter>
</receiver>
<service android:name="com.ddv.android.gcm.support.app.GCMIntentService"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
...
Я также попытался изменить <service android:name="com.ddv.android.gcm.support.app.GCMIntentService"
на <service android:name=".GCMIntentService"
с теми же результатами.
По сути, я могу сказать, что устройство Android получает сообщение GCM.И он знает, что GXM IntentService - это мой пользовательский com.ddv.android.gcm.support.app.GCMIntentService, но он ничего с этим не делает ... И он на самом деле не выдает никакой ошибки.Сообщение, которое я вижу в logcat, выглядит как предупреждение, если что-нибудь.
Я убедился, что мой GCMIntentService находится в основном пакете приложения.И что у меня есть все правильные разрешения, поэтому я не уверен, что мне не хватает или почему я не могу заставить это работать.
При обновлении приложения мне пришлось изменить способ регистрации моего GCM.и возможно у меня все еще есть это неправильно.Но следующий код не выдает никаких ошибок, и когда я отправляю сообщение GCM с сервера, все мои устройства Android получают сообщение сверху (создается впечатление, что они зарегистрированы правильно и что-то получают от Google).
Регистрационный код GCM:
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(RegisterActivity.this);
}
regId = gcm.register(SENDER_ID);
Log.d(TAG, "########################################");
Log.d(TAG, "Current Device's Registration ID is: " + regId);
SharedPreferences prefs = RegisterActivity.this.getSharedPreferences("com.google.android.gcm", 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("regId", regId);
editor.apply();
Log.d(TAG, "prefs.getString(\"regId\", \"\"): " + prefs.getString("regId", ""));
Log.d(TAG, "GCMRegistrar.getRegistrationId: " + GCMRegistrar.getRegistrationId(RegisterActivity.this));
ServerUtilities.registerToGCMServer(RegisterActivity.this, regId);
Код ServerUtilities:
static boolean registerToGCMServer(final Context context, final String regId) {
Log.i(TAG, "registering device on GCM Server (regId = " + regId + ")");
String baseUrl = getHost(context) + context.getString(R.string.GCM_PATH) + context.getString(R.string.GCM_REGISTER_PATH);
Map<String, String> params = new HashMap<String, String>();
params.put("regId", regId);
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
// Once GCM returns a registration id, we need to register it in the
// demo server. As the server might be down, we will retry it a couple
// times.
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
Log.d(TAG, "Attempt #" + i + " to register");
try {
displayMessage(context, context.getString(R.string.server_registering, i, MAX_ATTEMPTS));
post(baseUrl, params);
GCMRegistrar.setRegisteredOnServer(context, true);
String message = context.getString(R.string.server_registered);
CommonUtilities.displayMessage(context, message);
return true;
} catch (IOException e) {
// Here we are simplifying and retrying on any error; in a real
// application, it should retry only on unrecoverable errors
// (like HTTP error code 503).
Log.e(TAG, "Failed to register on attempt " + i, e);
if (i == MAX_ATTEMPTS) {
break;
}
try {
Log.d(TAG, "Sleeping for " + backoff + " ms before retry");
Thread.sleep(backoff);
} catch (InterruptedException e1) {
// Activity finished before we complete - exit.
Log.d(TAG, "Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
return false;
}
// increase backoff exponentially
backoff *= 2;
}
}
String message = context.getString(R.string.server_register_error, MAX_ATTEMPTS);
CommonUtilities.displayMessage(context, message);
return false;
}
Да, правая последняя часть информации.Вот что я ожидаю от своего приложения: в моем GCMIntentService.java
я ожидаю вызова перезаписанной функции onMessage()
, которая отображает предупреждение на основе полученного сообщения GCM.
public class GCMIntentService extends GCMBaseIntentService {
...
@Override
public void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
String alertText = intent.getExtras().getString("text");
String ackID = intent.getExtras().getString("id");
String detailID = intent.getExtras().getString("detail_id");
// Sets the class to be called when the notification is selected
intent.setClass(context, AlertFragmentActivity.class);
intent.putExtra("alert", (Parcelable) (new Alert(ackID, detailID, alertText)));
// I think this only goes through if the app is already running?
displayAlert(context, intent);
// notifies user
generateNotification(context, intent);
}
}
Я знаю, что в конечном итоге мне придется обновиться до FCM, но это все равно должно работать в это время (до апреля 2019 года, когда GCM будет полностью удален).