【问题标题】:java.io.IOException: SERVICE_NOT_AVAILABLE in GCM Clientjava.io.IOException:GCM 客户端中的 SERVICE_NOT_AVAILABLE
【发布时间】:2014-08-07 10:57:18
【问题描述】:

我想在现有的安卓应用中实现一个 gcm 客户端。因此,按照this 教程,我编写了以下代码:

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>

昨天一切正常,我可以检索注册 ID。但是现在,总是有一个IOExceptionSERVICE_NOT_AVAILABLE

我在三星 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)

【问题讨论】:

    标签: android firebase-cloud-messaging google-cloud-messaging ioexception service-not-available


    【解决方案1】:

    检查您设备的时间。 Google 无法在错误的时间注册您的设备

    【讨论】:

    • 时间似乎是正确的。奇怪的是,它昨天工作了 - 但现在,它不工作了;(无论是在真实设备上,还是在 genymotion 模拟器上。
    • 您是指在测试设备上还是在其他设备上?在测试设备上,是的。
    • 是的,google play servis 在两个测试设备(真实设备和模拟器)上都是最新的。我使用谷歌播放服务 4.4.52。
    • 嗯,您是否尝试过完全删除应用程序,重新安装并再次测试?
    • 是的,我已经尝试过了。好吧,以下讨论说“根据 Google GCM 文档,SERVICE_NOT_AVAILABLE 表示 Google 服务器目前正忙,您应该稍后再试”。在此处查看更多信息:groups.google.com/forum/#!topic/android-gcm/Skhe3jG5DIg 这可能是问题所在吗?
    【解决方案2】:

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

    在任何 GCM 注册尝试之前,它似乎必须在设备重新启动后至少启动一次。

    【讨论】:

    • 那很好。我试了两天没有任何反应,但这很管用。太棒了。
    • 这对我也有用!谢谢。
    【解决方案3】:

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

    我的猜测是,当我尝试注册 CGM 时,应用上下文尚未完全创建。它需要一个有效的上下文。

    【讨论】:

    • 我通过添加 10 秒延迟(用于完整的应用程序加载)解决了问题,然后发出 GCM 请求。
    【解决方案4】:

    昨天我自己解决了这个问题。我按照演示应用程序并将 registerInBackground()-Method 中的 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();
    }
    

    现在,它正在工作,但我不知道为什么。任何人都可以解释原因吗?感谢您的帮助!

    【讨论】:

      【解决方案5】:

      如果您在模拟器中运行应用,则必须安装 Google Play Service。

      我最近从 Google 原生模拟器切换到 GenyMotion 模拟器并遇到了这个错误。后来我意识到 GenyMotion 图像不附带 Google Play 服务。安装后问题解决。

      【讨论】:

        【解决方案6】:

        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());
            });
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-02-15
          • 1970-01-01
          • 2019-04-08
          • 2014-07-12
          • 1970-01-01
          • 1970-01-01
          • 2011-05-15
          相关资源
          最近更新 更多