【问题标题】:PARSE: Push Notifications "deviceToken" undefined解析:推送通知“deviceToken”未定义
【发布时间】:2015-04-11 13:17:51
【问题描述】:

这是我在 Parse Console 上的安装页面中的情况:

如您所见,有些设备有“deviceToken”,有些没有“deviceToken”。 这不好,因为每个设备都应该有 deviceToken 才能工作。

这怎么可能?这是一个严重的问题,因为没有 deviceToken 的人不会收到推送通知!

我已按照 Parse.com 上的所有说明执行所有操作,即使借助他们的空白项目和网络上的各种问题也是如此。但是没有什么能解决我的问题,现在我什么也做不了。

我唯一能想到的是,在我的应用程序(它已经在商店中)使用 Google Cloud Messaging 之前,我决定通过这个新的更新来更改系统并使用 Parse 完全删除 GCM 系统。这两个系统之间可能存在冲突吗?

我需要修复这个问题,你可以想象这是一个严重的错误,现在我 3/4 的用户没有收到推送通知。

如果您下载并安装应用程序:一切正常,deviceToken 没问题。如果您因为设备上已有 GCM 版本而更新应用:

  • 部分设备在 Parse 中注册良好,没有任何问题
  • 一些设备在 Parse 中注册但没有 deviceToken

对于没有 deviceToken 的设备,我尝试了很多方法:手动插入 deviceToken,卸载并重新安装应用程序,删除 Parse 上的特定行等。但没什么好...仍然面临这个问题。

我的代码

Application.java

public class Application extends android.app.Application {

public Application() {
}

@Override
public void onCreate() {
    super.onCreate();

    // Initialize the Parse SDK.
    Parse.initialize(this, "x", "x");

    // Specify an Activity to handle all pushes by default.
    PushService.setDefaultPushCallback(this, MainActivity.class);

}

}

MainActivity.java 在我的 mainActivity 中,我只是将 deviceToken(在我的情况下是 installationId)连接到我的 userAgent 中:这工作正常:我总是有 installationId 没有任何问题!这是我在 MainActivity 中唯一要做的事情(我还需要做其他事情吗?saveInBackground、回调等等?)

deviceToken = ParseInstallation.getCurrentInstallation().getInstallationId();
webSettings.setUserAgentString(userAgent + " ||" + deviceToken);

AndroidManifest.xml

<!-- Gestione del guasto-->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<!-- Utilizzo di internet  -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- Permesso di vibrare per le push notifications -->
<uses-permission android:name="android.permission.VIBRATE" />


<uses-permission android:name="android.permission.GET_ACCOUNTS" />

<!-- Mantiene attivo il processore così da poter ricevere in qualsiasi momento le notifiche -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- Consente di impostare l'allarme per l'aggiornamento automatico -->
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>


<permission android:name="com.hoxell.hoxellbrowser.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
<uses-permission android:name="com.hoxell.hoxellbrowser.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<application
    android:name="com.hoxell.hoxellbrowser.Application"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher_hoxell"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    >

    <!-- Richiesto per le applicazioni che usano Google Play Services -->
    <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize"
        android:launchMode="singleTask">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:name=".SettingsActivity"></activity>

    <receiver android:name=".AlarmReceiver"/>


    <service android:name="com.parse.PushService" />
    <receiver android:name="com.parse.ParseBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.USER_PRESENT" />
        </intent-filter>
    </receiver>
    <receiver android:name="com.hoxell.hoxellbrowser.Receiver"
        android:exported="false">
        <intent-filter>
            <action android:name="com.parse.push.intent.RECEIVE" />
            <action android:name="com.parse.push.intent.DELETE" />
            <action android:name="com.parse.push.intent.OPEN" />
        </intent-filter>
    </receiver>
    <receiver android:name="com.parse.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="com.hoxell.hoxellbrowser" />
        </intent-filter>
    </receiver>

</application>

Build.gradle

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// You must install or update the Support Repository through the SDK manager to use this dependency.
compile 'com.android.support:support-v4:20.+' //support
compile "com.google.android.gms:play-services:5.0.+" //play services
compile 'com.parse.bolts:bolts-android:1.+'
compile fileTree(dir: 'libs', include: 'Parse-*.jar')

}

我真的不知道还能做什么,这就是为什么我希望有人可以帮助我。

谢谢。

【问题讨论】:

  • 仅供参考,注册id存储在deviceToken列中,而不是installationId中。

标签: android parse-platform push-notification google-cloud-messaging devicetoken


【解决方案1】:

您是否在平板电脑上同时使用 2 个用户配置文件?因为我遇到了完全相同的问题,并且根据我的经验,配置文件之间存在冲突。事实上,在我的情况下,一台设备将 2 行注册到 Parse 数据库中。一个带有 deviceToken,一个带有“未定义”的 deviceToken。

不幸的是我从来没有解决过这个问题,我猜这是 Parse 的一个错误。

【讨论】:

  • 该死,你是对的。就是这个。我在平板电脑中确实有 2 个配置文件,我刚刚对其进行了测试:正常配置文件确实收到了 deviceToken,但受限制的配置文件(我需要的那个!)没有收到它。该死!现在?我可以做点什么吗?!?
  • 正如我所说,我没有解决这个问题。因此,我只为 1 台平板电脑使用了 1 个配置文件
  • 你在说哪种类型的个人资料,因为我面临同样的问题。
  • 有人能解决这个问题吗?我也被困在同一个地方。
  • 您可以在解析安装表中添加一个名为“isActiveUser”的新列。一台设备不能在同一时刻与不同的用户进行 2 个会话。
【解决方案2】:

将解析日志设置为详细有助于进一步调试:

Parse.setLogLevel(Parse.LOG_LEVEL_VERBOSE);

我注意到我在清单中使用了错误的“sender_id”:

<meta-data android:name="com.parse.push.gcm_sender_id"
    android:value="id:123456789"/>

这可能不是确切的解决方案,但 LOG_LEVEL_VERBOSE 可能有助于调试。

【讨论】:

    【解决方案3】:

    某些安装确实在其deviceToken 列中设置了 GCM 注册 ID,这很好地表明您的设置是正确的。安装肯定有可能缺少 GCM 注册 ID:

    • 设备可能无法访问 Google 服务框架(例如 Amazon Kindle Fire)。如果您设置了非 GCM ParsePush 接收器,则推送到这些设备应该仍会被传递。
    • 该应用程序已从设备中删除,因此已从 GCM 中注销。在这种情况下,我们不会自动删除安装,因为这可能会导致意外的数据丢失,因为您可以在安装类中存储任意数据。
    • 当设备尝试自行注册时,Google 服务框架可能不可用。

    在前两种情况下,这是按预期工作的,一般不用担心。

    【讨论】:

    • 设备可以访问谷歌服务框架(galaxy tab 3)..这不是不可用的问题......我对没有deviceToken的设备所做的是手动删除并重新安装应用程序并且已经进行了新的注册:但仍然没有 deviceToken。我试过清除应用程序缓存/数据,但结果相同。我不知道还能做什么……我们不想离开 Parse 框架:我们认为它很棒。但真的..我们还能做些什么来解决我们的问题?请帮助..你是唯一可以真正帮助我们的人.. :)
    • 我已经添加了我的 Build.gradle 代码:gms 版本编译是否有问题..?
    • 我不明白这个答案,你说这是一个合理的行为,但我不明白为什么,我有这个问题,没有 deviceToken 也没有类型,这意味着我的用户无法接收推送,如何这可以纠正吗?
    • 如果用户通过删除您的应用选择退出推送通知,则没有可推送的应用。因此,这是合理的行为:)
    • 同样,只有可以访问 Google 服务的设备才支持 GCM。 Kindle 设备将无法获取注册令牌。
    【解决方案4】:

    我已经为这个问题苦苦挣扎了很长时间,直到我最近才意识到发生了什么。不仅包名需要匹配,还需要在声明中包含构建风格。

    如果您遵循解析教程并将 com.parse.starter 替换为您的包名称,如果您没有构建风格,那么您就完成了,但如果您需要确保将其包含在内:

    com.packagename.build_flavor{调试、发布等}

    【讨论】:

      【解决方案5】:

      您可以创建一个类并扩展Application 来初始化您的应用程序。这样初始化ParsePushupdateParseInstallation

      示例代码:

      public class YourappApplication extends Application {
      
          @Override
          public void onCreate() {
              super.onCreate();
              Parse.initialize(this,YOU_PARSE_applicationId, YOU_PARSE_clientKey);
      
              ParseInstallation.getCurrentInstallation().saveInBackground();
      
              ParsePush.subscribeInBackground("", new SaveCallback() {
                  @Override
                  public void done(ParseException e) {
                      if (e == null) {
                          Log.d("com.parse.push", "successfully subscribed to the broadcast channel.");
                      } else {
                          Log.e("com.parse.push", "failed to subscribe for push", e);
                      }
                  }
              });
          }
      
          public static void updateParseInstallation(ParseUser user) {
              ParseInstallation installation = ParseInstallation.getCurrentInstallation();
              installation.put("userId", user.getObjectId());
              installation.saveInBackground();
          }
      }
      

      然后在你的 LoginActivity 中:updateParseInstallation

      ParseUser.logInInBackground(username, password, new LogInCallback() {
                              @Override
                              public void done(ParseUser parseUser, ParseException e) {
                                  setProgressBarIndeterminateVisibility(false);
                                  if(e == null){
                                      YourappApplication.updateParseInstallation(parseUser);
                                      Intent intent = new Intent(LoginActivity.this,
                                              MainActivity.class);
                                      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                      intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                                      startActivity(intent);
                                  }
                             }
                });
      

      【讨论】:

      • 这不是我问的
      【解决方案6】:

      那些是模拟器用户吗?根据我的经验,如果您在模拟器上运行安装,它不会自动设置设备令牌。

      【讨论】:

        【解决方案7】:

        重命名模块后我遇到了类似的问题。

        尝试“清理项目”,然后尝试“重建项目”

        【讨论】:

          【解决方案8】:

          我遇到了这个问题,但是在使用 phonegap-parse-plugin 的 cordova 应用程序中。我不得不编辑插件中的android java代码来修复,所以效果一样。

          尝试在 Initialize 和 setDefaultPushCallback 之间添加此保存:

          ParseInstallation.getCurrentInstallation().save();
          

          必须在他们之间才能工作。

          【讨论】:

            【解决方案9】:

            我的问题是我在清单中缺少此权限:

            &lt;uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /&gt;

            我还必须在之前添加元数据 &lt;service android:name="com.parse.PushService" /&gt;:

            <meta-data
            android:name="com.parse.APPLICATION_ID"
            android:value="YourParseApplicationID" />
            
            <meta-data
            android:name="com.parse.CLIENT_KEY"
            android:value="YourParseClientKey" />
            

            现在检查您是否可以获得 deviceToken。如果一切正常,还要在 Parse 中检查您的应用仪表板。

            【讨论】:

              【解决方案10】:

              我不知道 tghis 是否对任何人有帮助,但在从包含解析集成的应用程序类中删除此行后,我能够正确获取设备令牌和通知。这是代码。注释行(已删除的行)使一切正常。谁能解释一下为什么会这样?

              package com.test.android.push;
              
              import android.app.Application;
              
              import com.parse.Parse;
              import com.parse.ParseInstallation;
              import com.parse.ParsePush;
              
              public class FarrApplication extends Application {
              @Override
              public void onCreate() {
                  super.onCreate();
                  Parse.initialize(this, "xxxx", "xxxx");
                  ParseInstallation.getCurrentInstallation().saveInBackground();
                  ParsePush.subscribeInBackground("---"); // REMOVED AND WORKS
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-02-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多