Push android with Amazon SNS

Asked

Viewed 486 times

11

I’m trying to push an android app, but I’m not getting the push in my app.

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.google.android.c2dm.permission.REGISTER" />
<uses-permission android:name="br.com.bencao.permission.C2D_MESSAGE" />

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

<application
    android:name=".core.RootApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <activity
        android:name=".activity.MainActivity"
        android:label="@string/app_name"
        android:noHistory="true"
        android:screenOrientation="portrait" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    <!-- [START gcm_receiver] -->
    <receiver
        android:name=".gcm.GcmBroadcastReceiver"
        android:exported="true"
        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="br.com.bencao" />
        </intent-filter>
    </receiver>
    <!-- [END gcm_receiver] -->

    <!-- [START gcm_listener] -->
    <service
        android:name="br.com.bencao.gcm.MyGcmListenerService"
        android:exported="false" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </service>
    <!-- [END gcm_listener] -->

    <!-- [START instanceId_listener] -->
    <service
        android:name="br.com.bencao.gcm.MyInstanceIDListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID"/>
        </intent-filter>
    </service>
    <!-- [END instanceId_listener] -->

    <service
        android:name="br.com.bencao.gcm.RegistrationIntentService"
        android:exported="false">
    </service>

    <activity
        android:name=".activity.BencaoDiaActivity"
        android:excludeFromRecents="true"
        android:label="@string/title_activity_bencao_dia"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name=".activity.SobreActivity"
        android:label="@string/title_activity_sobre"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name=".activity.DicasActivity"
        android:label="@string/title_activity_dicas"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name=".activity.DicaExibirActivity"
        android:label="@string/title_activity_dica_exibir"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name=".activity.MensagensActivity"
        android:label="@string/title_activity_mensagens"
        android:screenOrientation="portrait" >
    </activity>
    <activity
        android:name=".activity.MensagensExibirActivity"
        android:label="@string/title_activity_mensagens_exibir"
        android:screenOrientation="portrait" >
    </activity>
</application>

Quickstartpreferences.java

package br.com.bencao.gcm;

public class QuickstartPreferences {

    public static final String SENT_TOKEN_TO_SERVER = "SENT_TOKEN_TO_SERVER";
    public static final String REGISTRATION_COMPLETE = "REGISTRATION_COMPLETE";

}

Mygcmlistenerservice . java

package br.com.bencao.gcm;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.android.gms.gcm.GcmListenerService;

import br.com.bencao.R;
import br.com.bencao.activity.MainActivity;

public class MyGcmListenerService extends GcmListenerService {

    private static final String TAG = "MyGcmListenerService";

    /**
     * Called when message is received.
     *
     * @param from SenderID of the sender.
     * @param data Data bundle containing message data as key/value pairs.
     *             For Set of keys use data.keySet().
     */
    // [START receive_message]
    @Override
    public void onMessageReceived(String from, Bundle data) {
        String message = data.getString("message");
        Log.d(TAG, "From: " + from);
        Log.d(TAG, "Message: " + message);

        if (from.startsWith("/topics/")) {
            // message received from some topic.
        } else {
            // normal downstream message.
        }

        // [START_EXCLUDE]
        /**
         * Production applications would usually process the message here.
         * Eg: - Syncing with server.
         *     - Store message in local database.
         *     - Update UI.
         */

        /**
         * In some cases it may be useful to show a notification indicating to the user
         * that a message was received.
         */
        sendNotification(message);
        // [END_EXCLUDE]
    }
    // [END receive_message]

    /**
     * Create and show a simple notification containing the received GCM message.
     *
     * @param message GCM message received.
     */
    private void sendNotification(String message) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("GCM Message")
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }
}

Myinstanceidlistenerservice.java

package br.com.bencao.gcm;

import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

import com.google.android.gms.iid.InstanceID;
import com.google.android.gms.iid.InstanceIDListenerService;

public class MyInstanceIDListenerService extends InstanceIDListenerService {

    private static final String TAG = "MyInstanceIDLS";

    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. This call is initiated by the
     * InstanceID provider.
     */
     // [START refresh_token]
     @Override
    public void onTokenRefresh() {
        // Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
    // [END refresh_token]
}

Gcmbroadcastreceiver.java

package br.com.bencao.gcm;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Explicitly specify that GcmIntentService will handle the intent.
        ComponentName comp = new ComponentName(context.getPackageName(),
                MyGcmListenerService.class.getName());
        Log.i("gcm", "receive");
        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
}

Registrationintentservice.java

package br.com.bencao.gcm;

import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.google.android.gms.gcm.GcmPubSub;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;

import java.io.IOException;

import br.com.bencao.R;

public class RegistrationIntentService extends IntentService {

    private static final String TAG = "RegIntentService";
    private static final String[] TOPICS = {"global"};

    public RegistrationIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

        try {
            // [START register_for_gcm]
            // Initially this call goes out to the network to retrieve the token, subsequent calls
            // are local.
            // [START get_token]
            InstanceID instanceID = InstanceID.getInstance(this);
            String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
                    GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
            // [END get_token]
            Log.i(TAG, "GCM Registration Token: " + token);

            // TODO: Implement this method to send any registration to your app's servers.
            sendRegistrationToServer(token);

            // Subscribe to topic channels
            subscribeTopics(token);

            // You should store a boolean that indicates whether the generated token has been
            // sent to your server. If the boolean is false, send the token to your server,
            // otherwise your server should have already received the token.
            sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, true).apply();
            // [END register_for_gcm]
        } catch (Exception e) {
            Log.d(TAG, "Failed to complete token refresh", e);
            // If an exception happens while fetching the new token or updating our registration data
            // on a third-party server, this ensures that we'll attempt the update at a later time.
            sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false).apply();
        }
        // Notify UI that registration has completed, so the progress indicator can be hidden.
        Intent registrationComplete = new Intent(QuickstartPreferences.REGISTRATION_COMPLETE);
        LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
    }

    /**
     * Persist registration to third-party servers.
     *
     * Modify this method to associate the user's GCM registration token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
    }

    /**
     * Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
     *
     * @param token GCM token
     * @throws IOException if unable to reach the GCM PubSub service
     */
    // [START subscribe_topics]
    private void subscribeTopics(String token) throws IOException {
        GcmPubSub pubSub = GcmPubSub.getInstance(this);
        for (String topic : TOPICS) {
            pubSub.subscribe(token, "/topics/" + topic, null);
        }
    }
    // [END subscribe_topics]

}

Mainactivity.java

package br.com.bencao.activity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;

import br.com.bencao.R;
import br.com.bencao.animacoes.FadeInOut;
import br.com.bencao.core.RootActivity;
import br.com.bencao.core.RootApplication;
import br.com.bencao.gcm.QuickstartPreferences;
import br.com.bencao.gcm.RegistrationIntentService;
import br.com.bencao.ws.BencaoDados;


public class MainActivity extends RootActivity {

    private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
    private static final String TAG = "MainActivity";

    private BroadcastReceiver mRegistrationBroadcastReceiver;
    RootApplication rootApplication;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rootApplication = (RootApplication)getApplicationContext();

        Typeface tfb = Typeface.createFromAsset(getAssets(),
                "fonts/Lato-Regular.ttf");
        TextView carregando_txt = (TextView) findViewById(R.id.carregando_dados);
        carregando_txt.setTypeface(tfb);

        FadeInOut anim = new FadeInOut();
        anim.setAnim(carregando_txt);

        new BencaoDados(MainActivity.this).execute();

        Log.e("token", rootApplication.getAndroid_token());

        mRegistrationBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                SharedPreferences sharedPreferences =
                        PreferenceManager.getDefaultSharedPreferences(context);
                boolean sentToken = sharedPreferences
                        .getBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false);
                if (sentToken) {
                    Log.e("gcm", "a");
                } else {
                    Log.e("gcm", "b");
                }
            }
        };

        if (checkPlayServices()) {
            // Start IntentService to register this application with GCM.
            Intent intent = new Intent(this, RegistrationIntentService.class);
            startService(intent);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(QuickstartPreferences.REGISTRATION_COMPLETE));
    }

    @Override
    protected void onPause() {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
        super.onPause();
    }

    /**
     * Check the device to make sure it has the Google Play Services APK. If
     * it doesn't, display a dialog that allows users to download the APK from
     * the Google Play Store or enable it in the device's system settings.
     */
    private boolean checkPlayServices() {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (apiAvailability.isUserResolvableError(resultCode)) {
                apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
                        .show();
            } else {
                Log.i(TAG, "This device is not supported.");
                finish();
            }
            return false;
        }
        return true;
    }
}

I’m using SNS to push, someone can identify some error or something missing in the code?

  • Returns an error in Logcat?

  • No, it works normal, but when I push the SNS does not receive

  • follow step by step... something else on your web part must be wrong.

  • http://docs.aws.amazon.com/sns/latest/dg/mobile-push-gcm.html https://aws.amazon.com/pt/blogs/aws/push-notifications-to-mobile-devices-using-amazon-sns/

  • Put a breakpoint on String message = data.getString("message"); is probably coming from something other than message on your date. It happened to me.

1 answer

2

According to Amazon SNS and GCM documentation for android, you need to complete 3 basic requirements:

  • The application must be registered with the GCM: you must have a Google Cloud Messaging API enabled in the Google Developers Console.
  • Have a GCM API authentication key (Sender auth token), this token is used in the header of the GCM-directed message. If incorrect or missing, the Google server returns an authentication error and does not send the message. The same is obtained by registering the app in the Google Developers Console.
  • You need to have a Registration ID. It is necessary for sending messages as it is the unique identifier of each instance of your application. The class responsible for obtaining it is the RegistrationIntentService, using the method instanceID.getToken(). Note that you have not implemented the method sendRegistrationToServer, who is responsible for registering the token generated by Google Play Services on your server. Without it, it is not possible to direct messages to a specific device.

I created an example application with these features. The source code and a small tutorial are available on Github: Android client and PHP server.

Unfortunately I could not supplement the response with links to the documentation due to Stackoverflow’s reputation restrictions.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.