java.io.IOException: GCM客户端中的SERVICE_NOT_AVAILABLE

26

我想将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);
    }
}
}

Android清单文件:

<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>

昨天一切正常,我可以检索到注册ID。但是现在,总是出现“SERVICE_NOT_AVAILABLE”的IOException

我已在我的三星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)
8个回答

36

检查你的设备时间。如果时间不正确,Google将无法注册你的设备


2
时间似乎是正确的。奇怪的是,它昨天工作正常,但现在却不行了;无论是在真实设备上还是在Genymotion模拟器上都不行。 - Robin
是的,Google Play服务在测试设备(真实设备和模拟器)上都是最新版本。我使用的是Google Play服务4.4.52。 - Robin
嗯,你尝试过完全卸载应用程序,重新安装并再次测试吗? - Nickolai Astashonok
是的,我已经尝试过了。好吧,以下讨论说:“根据Google GCM文档,SERVICE_NOT_AVAILABLE表示Google服务器目前很忙,您应该稍后再试”。在这里查看更多信息:https://groups.google.com/forum/#!topic/android-gcm/Skhe3jG5DIg 这可能是问题吗? - Robin
如果没有互联网,您也会收到此异常。假设其他所有内容都正常工作。 - Hussain Mansoor
显示剩余5条评论

15

当我遇到这个问题时,对我有用的方法是打开Google Play应用程序。

似乎在设备重新启动之后,必须至少启动一次Google Play才能进行任何GCM注册尝试。


这很好。我尝试了两天,什么都没发生,但这个有效。太棒了。 - sachithkn

6

这是一个奇怪的问题。我通过将GCM代码移动到我的onCreate()方法的末尾来解决它。

我猜测在我尝试注册CGM时,应用程序上下文还没有完全创建。它需要一个有效的上下文。


我通过添加10秒的延迟(以完成应用程序加载),然后进行GCM请求来解决问题。 - Enakhi

3

SERVICE_NOT_AVAILABLE 可能意味着执行任务时设备离线:

com.google.android.gms.tasks.RuntimeExecutionException: java.io.IOException: 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());
    });
}

0

昨天我自己解决了这个问题。我遵循示例应用程序,并将registerInBackground()方法中的AsyncTask更改为普通的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();
}

现在它可以工作了,但我不知道为什么。有人能解释一下原因吗?感谢您的帮助!


0
如果您正在模拟器上运行应用程序,则必须安装Google Play服务。
我最近从Google原生模拟器切换到GenyMotion模拟器,并遇到了这个错误。后来我意识到GenyMotion镜像不带有Google Play服务。安装后,问题得到解决。

0

同时确保您的手机已连接互联网!


0

NativeFirebaseError: [messaging/unknown] java.io.IOException: java.util.concurrent.ExecutionException: java.io.IOException: SERVICE_NOT_AVAILABLE

我知道这听起来很奇怪,但当测试设备存在互联网连接问题时,就会出现此错误。


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