GCM SERVICE_NOT_AVAILABE только в сотовой сети
Я и мой друг разрабатываем приложение для Android и внедрили все необходимое для GCM. На моем устройстве (Nexus 4) регистрация и получение сообщений работают нормально по WiFi и сотовой сети. Но если мой друг пытается зарегистрировать свое устройство (Xperia Z), оно выходит из строя по сотовой сети, и он получает ошибку SERVICE_NOT_AVAILABLE. Через Wi-Fi регистрация и получение сообщений работает нормально с его устройством тоже. Если он регистрирует свое устройство по WiFi, а затем переключается обратно на сотовые данные, он не получает никакого сообщения!
У нас недостаточно устройств для проверки, если это проблема с его устройством или проблема в нашем приложении, поэтому мы надеемся, что вы можете помочь нам. Вот некоторые файлы нашего проекта, если вам нужно больше деталей, я добавлю их позже.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.mypackage.vorlesungsplan.app"
android:versionCode="0010201"
android:versionName="1.2.1 (Raw Potato)" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="android.permission.GET_TASKS"/>
<permission android:name="de.mypackage.vorlesungsplan.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="de.mypackage.vorlesungsplan.app.C2D_MESSAGE" />
<supports-screens android:normalScreens="true" android:xlargeScreens="true" android:largeScreens="true" android:smallScreens="false"/>
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:allowBackup="false" >
<activity
android:name="MainActivity"
android:label="@string/title_activity_startup" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="SettingsActivity" android:label="Einstellungen" android:screenOrientation="portrait"></activity>
<activity android:name="InfoHelpActivity" android:screenOrientation="portrait"></activity>
<activity android:name="LunchActivity" android:screenOrientation="portrait"></activity>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<receiver
android:name=".io.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="de.mypackage.vorlesungsplan.app" />
</intent-filter>
</receiver>
<service android:name=".io.GCMIntentService" />
</application>
</manifest>
Метод register() выполняется в фоновом процессе, как это делает документация. Поэтому мы использовали обычный поток вместо AsyncTask, но я не думаю, что это может вызвать проблему. Следующий класс расширяет класс Thread:
RegisterServerOperation.java
public void run() {
...
if(checkPlayServices()) {
Logbook.d("Device is GCM capable");
// Hole die regId des Geräts oder erzeuge eine neue
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(activity);
String regId = Settings.getInstance(activity).getSetting("regId");
if (regId == null || regId.isEmpty()) {
regId = gcm.register(SENDER_ID);
Settings.getInstance(activity).setSetting("regId", regId);
}
Logbook.d("Registration id for this device is: "+regId);
} else {
throw new Exception("REGISTRATION_FAILED");
}
...
}
Метод checkPlayServices() скопирован из примера Google и также должен быть корректным, поскольку в logcat появляется строка "Устройство поддерживает GCM". Класс "Настройки" - это наша собственная реализация для хранения настроек, а класс "Журнал" - только класс-оболочка для android.util.Log. Мой друг также сделал перехват своего сетевого трафика с помощью DDMS:
Первый пик был вызван обычным http-запросом, который наше приложение отправляет в начале. Это доказывает, что его подключение к сотовой сети было жизнеспособным в данный момент. После этого должен быть еще один пик, вызванный методом gcm.register (...), но ничего нет.
Мы создали приложение со следующей версией проекта google_play_services_lib:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="google_play_services_version">4132500</integer>
</resources>
Сервисы Google Play, установленные на его устройстве, обновлены (версия 4.1.32). Его версия для Android - 4.3, и это стандартное ПО Sony. Мой Nexus 4 работает с ночной сборкой CM 11 (так что это Android 4.4.2).
Пожалуйста, помните, что одно и то же приложение работает правильно по Wi-Fi, но не по сотовой сети. Это просто сбивает нас с толку, и мы пробовали много подходов к решению проблем, но ни один из них не улучшил нашу ситуацию.
Я надеюсь, что кто-то может помочь нам, спасибо