java.io.IOException: SERVICE_NOT_AVAILABLE в клиенте GCM
Я хочу внедрить клиента gcm в существующее приложение для Android. Итак, следуя этому уроку, я написал следующий код:
public class RegisterForGCMAsyncTask extends AbstractSecureOperationTask {
...
@Override
protected Boolean doInBackground(String... params) {
String token = authenticate();
getRegId();
if (TextUtils.isEmpty(registrationId)) {
return false;
}
//
try {
URL url = convertToURLEscapingIllegalCharacters(String.format(Constants.REGISTER_URL,
registrationId, userId, token));
URLConnection connection = url.openConnection();
InputStreamReader streamReader = new InputStreamReader(connection.getInputStream());
JSONParser parser = new JSONParser();
JSONObject rootObj = (JSONObject) parser.parse(streamReader);
String status = rootObj.get("status").toString();
if (status.equals("OK")) {
return true;
}
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private void getRegId() {
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
registrationId = gcm.register(PROJECT_ID);
} catch (IOException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
}
}
AndroidMainfest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.xxxxxxxx.xxxxxxxx"
android:versionCode="20140617"
android:versionName="2.0.0">
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="19"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<permission
android:name="de.xxxxxxxx.xxxxxxxx.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="de.xxxxxxxx.xxxxxxxx.permission.MAPS_RECEIVE"/>
<permission
android:name="de.xxxxxxxx.xxxxxxxx.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="de.xxxxxxxx.xxxxxxxx.permission.C2D_MESSAGE"/>
<!-- Maps API needs OpenGL ES 2.0. -->
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="de.retterapps.Handyalarm.views.activities.MainActivity"
android:configChanges="orientation|screenLayout|screenSize|layoutDirection"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver
android:name=".helper.gcm.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<category android:name="de.xxxxxxxx.xxxxxxxx"/>
</intent-filter>
</receiver>
<service android:name=".helper.gcm.GcmMessageHandler"/>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="xxxxxxxx"/>
</application>
Вчера все работало нормально, и я смог получить регистрационный идентификатор. Но теперь всегда есть IOException
поговорка SERVICE_NOT_AVAILABLE
,
Я тестировал его на своем Samsung Galaxy S5 и в эмуляторе Genymotion (Android 4.1.2), но я всегда получаю одинаковые результаты. Кто-нибудь знает, как решить проблему?
редактировать
Вот полная трассировка стека:
java.io.IOException: SERVICE_NOT_AVAILABLE
at com.google.android.gms.gcm.GoogleCloudMessaging.register(Unknown Source)
at de.retterapps.Handyalarm.helper.tasks.RegisterForGCMAsyncTask.getRegId(RegisterForGCMAsyncTask.java:72)
at de.retterapps.Handyalarm.helper.tasks.RegisterForGCMAsyncTask.doInBackground(RegisterForGCMAsyncTask.java:43)
at de.retterapps.Handyalarm.helper.tasks.RegisterForGCMAsyncTask.doInBackground(RegisterForGCMAsyncTask.java:24)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
9 ответов
Проверьте время вашего устройства. Google не может зарегистрировать ваше устройство с неправильным временем
Когда я столкнулся с этой проблемой, мне помогло открыть приложение Google Play.
Кажется, что он должен быть запущен хотя бы один раз после перезапуска устройства перед любой попыткой регистрации GCM.
Это странно. Я решил это, переместив код GCM в конец моего метода onCreate().
Я предполагаю, что контекст приложения не был полностью создан ко времени, когда я пытался зарегистрироваться для CGM. Требуется действительный контекст.
также может означать, что устройство отключено при выполнении задачи:
com.google.android.gms.tasks.RuntimeExecutionException
::java.util.concurrent.ExecutionException
:java.io.IOException
:SERVICE_NOT_AVAILABLE
в
com.google.android.gms.tasks.zzw.getResult
(com.google.android.gms: play-services-tasks@@17.2.1:3)
Так что это можно решить, не запрашивая, например. токен FCM, когда устройство отключено, например:
@Override
public void onNetworkAvailable() {
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {
Log.d(LOG_TAG, "FCM token: " + task.getResult());
});
}
NativeFirebaseError: [обмен сообщениями/неизвестно] java.io.IOException: java.util.concurrent.ExecutionException: java.io.IOException: SERVICE_NOT_AVAILABLE
Я знаю, это звучит странно, но эта ошибка возникает, когда на тестовом устройстве возникают проблемы с подключением к Интернету.
Если вы запускаете свое приложение в эмуляторе, вы должны установить Google Play Service.
Недавно я переключился на GenyMotion Emulator из нативного эмулятора Google и столкнулся с этой ошибкой. Позже я понял, что изображение GenyMotion не поставляется с сервисом Google Play. После установки проблема решена.
Вчера я решил проблему самостоятельно. Я следовал за демо-приложением и изменил AsyncTask в registerInBackground()- Метод на простой поток Java. Вот код:
private void registerInBackground() {
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
Toast.makeText(context, getString(R.string.txt_gcm_registered), Toast.LENGTH_LONG).show();
break;
case 1:
Toast.makeText(context, getString(R.string.error_register_gcm), Toast.LENGTH_LONG).show();
break;
}
super.handleMessage(msg);
}
};
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regId = gcm.register(Constants.SENDER_ID);
if (sendRegistrationIdToBackend(regId)) {
handler.sendEmptyMessage(0);
} else {
handler.sendEmptyMessage(1);
}
storeRegistrationId(context, regId);
} catch (IOException ex) {
handler.sendEmptyMessage(1);
Log.e(LOG_TAG, ex.getMessage(), ex);
}
}
};
new Thread(runnable).start();
}
Сейчас это работает, но я не знаю почему. Кто-нибудь может объяснить причину? Спасибо за вашу помощь!