Parse Push Notification Exception: “unauthorized:

2019-02-15 14:44发布

问题:

I want to send push Notification using Parse API and GCM. I have done successfully configuration on server and test via sending push notification form Parse terminal and receive at android device.

But when i'm sending push programmatically then got an Exception: "unauthorized: master key is required".

I using following code:

ParseQuery query = ParseInstallation.getQuery();
    query.whereEqualTo("channels", "testing");

    // Notification for Android users
    query.whereEqualTo("deviceType", "android");
    ParsePush androidPush = new ParsePush();
    androidPush.setMessage("Your suitcase has been filled with tiny robots!");
    androidPush.setQuery(query);
    androidPush.sendInBackground(new SendCallback() {
        @Override
        public void done(ParseException e) {
            if ( e == null ) {
                Log.d("GARG","Parse Notification Done. : ");
            } else {
                Log.d("GARG","Notification failed.: "+e.getMessage());
                e.printStackTrace();
            }
        }
    });

android manifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.demo">

<permission
    android:name="com.demo.permission.MAPS_RECEIVE"
    android:protectionLevel="signature" />

<uses-permission android:name="com.demo.permission.MAPS_RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<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.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<permission
    android:name="com.demo.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name="com.demo.permission.C2D_MESSAGE" />

<application
    android:name=".AppInitializer"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true">

<service android:name="com.parse.PushService" />
    <meta-data
        android:name="com.parse.push.notification_icon"
        android:resource="@drawable/ic_cast_light" />

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

    <meta-data
        android:name="com.parse.APPLICATION_ID"
        android:value="@string/parse_app_id" />
    <meta-data
        android:name="com.parse.CLIENT_KEY"
        android:value="@string/parse_client_key" />

    <meta-data
        android:name="com.parse.X-Parse-Master-Key"
        android:value="@string/parse_master_key" />

<receiver android:name="com.parse.ParsePushBroadcastReceiver"
        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.demo" />
        </intent-filter>
    </receiver>

</application>

Initialize Parse SDK in android

public class AppInitializer extends Application {

public static JSONObject errorDataProvider;

@Override
public void onCreate() {

    super.onCreate();
    Parse.enableLocalDatastore(getApplicationContext());
    Parse.initialize(new Parse.Configuration.Builder(getApplicationContext())
            .applicationId(Utility.ApplicationId)
            .clientKey(Utility.ClientKey)
            .server(Utility.Server_URL)
            .build()
    );

    ParseInstallation.getCurrentInstallation().saveInBackground();

    ParsePush.subscribeInBackground(Utility.PARSE_CHANNEL, new SaveCallback() {
        @Override
        public void done(ParseException e) {
            Log.e("GARG", "Successfully subscribed to Parse!");
        }
    });
    }
 }

回答1:

UPDATED ANSWER

Hi, i investigate it a bit and found that currently the only to send Push is by using the masterKey and that's exactly the reason why you are getting this error

In order to send push with master key the best approach will be to create a cloud code function and trigger this function from the client side. so you need to do the following:

  1. Inside your cloud code main.js file create a new function

Parse.Cloud.afterSave("SendPush", function(request) {


  var query = new Parse.Query(Parse.Installation);
  query.exists("deviceToken");

  // here you can add other conditions e.g. to send a push to sepcific users or channel etc.

  var payload = {
    alert: "YOUR_MESSAGE"
      // you can add other stuff here...
  };


  Parse.Push.send({
      data: payload,
      where: query
    }, {
      useMasterKey: true
    })
    .then(function() {
      response.success("Push Sent!");
    }, function(error) {
      response.error("Error while trying to send push " + error.message);
    });
});

After you created the cloud code function restart your server

  1. Trigger this cloud code function from your android app in the following way:

    HashMap<String,String> map = new HashMap<String, String>();
    map.put("PARAM1KEY","PARAM1VALUE");
    // here you can send parameters to your cloud code functions
    // such parameters can be the channel name, array of users to send a push to and more...
    
    ParseCloud.callFunctionInBackground("SendPush",map, new FunctionCallback<Object>() {
    
        @Override
        public void done(Object object, ParseException e) {
            // handle callback 
        }
    });
    

This will trigger a call to the cloud code function that you created above and inside the cloud code the useMasterKey is true so it should work.

update: spelling