Google GCM client not sending messages after unreg

2019-08-30 02:03发布

问题:

I would like to register/unregister the BroadcastReceiver which I am using to receive messages from GCM. I have declared and initialised the BroadcastReceiver.class in my onResume(), but after I unregister inside onPause() next time my app launches it wont send messages any more, only if I send the regId again and register with the GCM server as well.

Can the BroadcastReceiver be responsible for not sending the messages? Or is it essential to have the BroadcastReceiver registered in the Manifest file??

I would be really grateful for any suggestion.

UPDATE:

Interestingly if I register the BroadcastReceiver programatically, the GCM server gives a new regId all the time when registering the device itself on the GCM server, when the BroadcastReceiver is registered in the Manifest, the GCM server gives the same regId. WHY??

Methods for registering/unregistering:

@Override    
protected void onResume() {         
            super.onResume();   

            IntentFilter filter = new IntentFilter();
            receiver = new GcmBroadcastReceiver();  

            filter.addAction("com.google.android.c2dm.intent.RECEIVE");
            filter.addAction("com.google.android.c2dm.intent.REGISTRATION");
            filter.addCategory("com.taxidirectdriver");

            registerReceiver(receiver, filter, "com.google.android.c2dm.permission.SEND", null);


        }

    @Override
        protected void onPause() {      
            super.onPause();

            unregisterReceiver(receiver);
        }

Full MainActivity:

public class MainActivity extends FragmentActivity implements 
    GooglePlayServicesClient.ConnectionCallbacks,
    GooglePlayServicesClient.OnConnectionFailedListener, LocationListener { 

    private static final String PROPERTY_APP_VERSION = "appVersion";

    GoogleCloudMessaging gcm;
    String regid;
    Context context;
    AtomicInteger msgId = new AtomicInteger();

    private static final int GPS_ERRORDIALOG_REQUEST = 9001;
    GoogleMap mMap; 

    public SharedPreferences pref;
    public static String DNAME = "dname";
    public static final String REGID="regid";   
    String driverName;

    private static final float DEFAULTZOOM = 15;
    private static final String TAG = null;

    private static long locRefresh = 300000;
    private static long fastestRefresh = 120000;

    LocationClient mLocationClient;
    Marker marker;

    Geocoder geocoder;
    List<Address> addresses;

    ArrayList<Double> drivers = new ArrayList<Double>();
    Map<String,Double> nameAndDistance = new HashMap<String, Double>();
    String address;

    OrdersDBHelper dbHelper;

    private GcmBroadcastReceiver receiver;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); 

        if(isOnline()){         

        pref = getSharedPreferences("SETTINGS_PREF", MODE_PRIVATE);     
        driverName = pref.getString(DNAME, "none");
        if(driverName == null || driverName == "none") {
            Intent i = new Intent(this, Registration.class);
            startActivity(i);
        } else {

        // GCM startup
        gcm = GoogleCloudMessaging.getInstance(this);
        context = getApplicationContext();
        regid = getRegistrationId(context);

        pref = getSharedPreferences("SETTINGS_PREF", MODE_PRIVATE);     
        regid = pref.getString(REGID, "");
        if (regid == null || regid.equals("")){
        registerInBackground();
        }           

        } // end of else statement

        // Initiate Map if services exists
        if (servicesOK() && isOnline() && isLocationOn()) {
            setContentView(R.layout.map_activity);

            if (initMap()) {
                //Toast.makeText(this, "Ready To map!", Toast.LENGTH_SHORT).show();
                mLocationClient = new LocationClient(this, this, this);
                mLocationClient.connect();              
            }   

            else {
            Toast.makeText(this, "Map Not Available!", Toast.LENGTH_SHORT).show();  
            }
        }
        else {
            Intent conInt = new Intent(this, ConnDependencies.class);  
            conInt.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(conInt);              
        }   

        } else {
            Intent conInt = new Intent(this, ConnDependencies.class);  
            conInt.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(conInt);      
        }   //end is online

    }

    @Override
    protected void onResume() {         
        super.onResume();   
        locRefresh = 300000;
        fastestRefresh = 120000;
        Log.i(TAG, "Resfresh interval set to "+ locRefresh + " millis");    

        /*
        //experimental receiver registration                    
        IntentFilter filter = new IntentFilter();
        receiver = new GcmBroadcastReceiver();  

        filter.addAction("com.google.android.c2dm.intent.RECEIVE");
        filter.addAction("com.google.android.c2dm.intent.REGISTRATION");
        filter.addCategory("com.taxidirectdriver");

        registerReceiver(receiver, filter, "com.google.android.c2dm.permission.SEND", null);
        */

        if(isOnline() && isLocationOn()){
            Log.i(TAG, "Location and internet ok!");                
        } else {
            Intent conInt = new Intent(this, ConnDependencies.class);  
            conInt.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(conInt);  
        }
    }

    @Override
    protected void onPause() {      
        super.onPause();
        locRefresh = 21600000;
        fastestRefresh = 21600000;
        Log.i(TAG, "Resfresh interval set to "+ locRefresh + "(6 hours) millis");   
        //unregisterReceiver(receiver);
    }

    public void exitApp (){             

        Intent inn = new Intent(this, DialogAlert.class);
        startActivity(inn);

        //unregisterReceiver(receiver);
        Log.i(TAG, "Receiver unregistered!");
        finish();
    }


    public boolean isLocationOn(){
         LocationManager locman = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
         if(locman.isProviderEnabled(LocationManager.GPS_PROVIDER)) {       
            return true;
         }
        return false;       
    }   

    public boolean isOnline() {
        ConnectivityManager cm =
            (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected()) {             
            return true;
        } 
        return false;
    }

    public void showOrders(View view) {         
        Intent intent = new Intent(this, ClientDetails.class);          
        startActivity(intent);
    }


    // Check for Play Services
    public boolean servicesOK() {
        int isAvailable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

        if (isAvailable == ConnectionResult.SUCCESS) {
            return true;
        }
        else if (GooglePlayServicesUtil.isUserRecoverableError(isAvailable)) {
            Dialog dialog = GooglePlayServicesUtil.getErrorDialog(isAvailable, this, GPS_ERRORDIALOG_REQUEST);
            dialog.show();
        }
        else {
             Toast.makeText(this, "Cant Connect to Google Play services", Toast.LENGTH_SHORT).show();
        }
        return false;
    }

    // Initializing map
    private boolean initMap(){
        if (mMap == null){
            SupportMapFragment mapFrag = 
                    (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
            mMap = mapFrag.getMap();
        }
        return (mMap != null);
    }


    // My Location
    @Override
    public void onConnectionFailed(ConnectionResult arg0) {
        // TODO Auto-generated method stub      
    }

    @Override
    public void onConnected(Bundle arg0) {
        //Toast.makeText(this, "Connected to current location service", Toast.LENGTH_SHORT).show();     
        LocationRequest request = LocationRequest.create();
        request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        request.setInterval(locRefresh);
        request.setFastestInterval(fastestRefresh);
        mLocationClient.requestLocationUpdates(request, this);      


        //Marking users location
        Location currentLocation = mLocationClient.getLastLocation();
        LatLng ll = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(ll, DEFAULTZOOM);
        mMap.animateCamera(update);

        if  (marker != null){
            marker.remove();
        }

        MarkerOptions options = new MarkerOptions()
        .title(driverName)
        .position(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()))
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.driver_marker));          
        marker = mMap.addMarker(options);

    }   

    @Override
    public void onDisconnected() {
        // TODO Auto-generated method stub      
    }


    @Override
    public void onLocationChanged(Location location) {


        LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());
        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(ll, DEFAULTZOOM);
        mMap.animateCamera(update);

        if  (marker != null){
            marker.remove();
        }

        MarkerOptions options = new MarkerOptions()
        .title(driverName)
        .position(new LatLng(location.getLatitude(), location.getLongitude()))
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.driver_marker));
        //.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
        marker = mMap.addMarker(options);


        final int DEFAULT_TIMEOUT = 20 * 1000;
        AsyncHttpClient client = new AsyncHttpClient();
        client.setTimeout(DEFAULT_TIMEOUT); 


         if (location.getLatitude() != 0) {

         RequestParams params = new RequestParams();        
         params.put("NAME", driverName);
         params.put("REGID", regid);
         params.put("LAT", String.valueOf(location.getLatitude()));
         params.put("LNG", String.valueOf(location.getLongitude()));

         client.post("http://edmondvarga.com/android_dev/taxidirect/update_coor.php", params, new AsyncHttpResponseHandler() {

            @Override
            public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                    Throwable arg3) {
                //Toast.makeText(getApplicationContext(), "ERROR UPDATING POSITION!", Toast.LENGTH_LONG).show();                
            }

            @Override
            public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
                Log.d("HTTP", "onSuccess, coordinates sent!");              
            }                           
            });      
         }          
    }   

            /**
             * Registers the application with GCM servers asynchronously.
             * <p>
             * Stores the registration ID and the app versionCode in the application's
             * shared preferences.
             */
            private void registerInBackground()
            {
            new AsyncTask<Void, Void, String>()
            {
            @Override
            protected String doInBackground(Void... params)
            {
            String msg = "";
            try
            {
                if (gcm == null)
                {
                gcm = GoogleCloudMessaging.getInstance(context);
                }
                regid = gcm.register(Globals.GCM_SENDER_ID);
                msg = "Device registered, registration ID=" + regid;

                // You should send the registration ID to your server over
                // HTTP, so it can use GCM/HTTP or CCS to send messages to your app.
                sendRegistrationIdToBackend();

                // For this demo: we use upstream GCM messages to send the
                // registration ID to the 3rd party server

                // Persist the regID - no need to register again.
                storeRegistrationId(context, regid);
            }
            catch (IOException ex)
            {
                msg = "Error :" + ex.getMessage();
                // If there is an error, don't just keep trying to register.
                // Require the user to click a button again, or perform
                // exponential back-off.
            }
            return msg;
            }


            @Override
            protected void onPostExecute(String msg)
            {

                //Toast.makeText(getApplicationContext(), "regId is: " + regid, Toast.LENGTH_SHORT).show();
            }
        }.execute(null, null, null);
        }


        /**
         * Store regid and the app version in SETTINGS_PREF
         *     
         */

        private void storeRegistrationId(Context context, String regid) {
            int appVersion = getAppVersion(context);        
            pref = getSharedPreferences("SETTINGS_PREF", MODE_PRIVATE);
            SharedPreferences.Editor editor = pref.edit();
            editor.putString(REGID,regid);
            editor.putInt(PROPERTY_APP_VERSION, appVersion);
            editor.commit();

        }

        /**
         * Sends the registration ID to the 3rd party server via an upstream 
         * GCM message. Ideally this would be done via HTTP to guarantee success or failure 
         * immediately, but it would require an HTTP endpoint.
         */
        private void sendRegistrationIdToBackend()
        {

        String name = driverName;
        Log.d(Globals.TAG, "Driver name is: " + driverName + " " + "REGISTER USERID: " + regid);

        new AsyncTask<String, Void, String>()
        {
            @Override
            protected String doInBackground(String... params)
            {
            String msg = "";
            try
            {
                Bundle data = new Bundle();
                data.putString("name", params[0]);
                data.putString("action", "com.taxidirect.gcmdemo.REGISTER");
                String id = Integer.toString(msgId.incrementAndGet());
                gcm.send(Globals.GCM_SENDER_ID + "@gcm.googleapis.com", id, Globals.GCM_TIME_TO_LIVE, data);
                msg = "Sent registration";
            }
            catch (IOException ex)
            {
                msg = "Error :" + ex.getMessage();
            }
            return msg;
            }

            @Override
            protected void onPostExecute(String msg)
            {
            //Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
            }
        }.execute(name);
        }

        /**
         * Gets the current registration ID for application on GCM service, if there
         * is one.
         * <p>
         * If result is empty, the app needs to register.
         * 
         * @return registration ID, or empty string if there is no existing
         *         registration ID.
         */
        private String getRegistrationId(Context context)
        {
        pref = getSharedPreferences("SETTINGS_PREF", MODE_PRIVATE);
        String registrationId = pref.getString(REGID, "");
        if (registrationId == null || registrationId.equals(""))
        {
            Log.i(TAG, "Registration not found.");
            return "";
        }
        // Check if app was updated; if so, it must clear the registration ID
        // since the existing regID is not guaranteed to work with the new
        // app version.
        int registeredVersion = pref.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
        int currentVersion = getAppVersion(context);
        if (registeredVersion != currentVersion)
        {
            Log.i(Globals.TAG, "App version changed.");
            return "";
        }
        return registrationId;
        }

        /**
         * @return Application's version code from the {@code PackageManager}.
         */
        private static int getAppVersion(Context context)
        {
        try
        {
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
        }
        catch (NameNotFoundException e)
        {
            // should never happen
            throw new RuntimeException("Could not get package name: " + e);
        }
        }    


        @Override
          public boolean onCreateOptionsMenu(Menu menu) {
              // Inflate the menu items for use in the action bar
              MenuInflater inflater = getMenuInflater();
              inflater.inflate(R.menu.main, menu);
              return super.onCreateOptionsMenu(menu);
          }

          @Override
          public boolean onOptionsItemSelected(MenuItem item) {
              switch (item.getItemId()) {
              case R.id.exitApp:    
                  exitApp();
                  return true;
              }
              return super.onOptionsItemSelected(item);
          }



}

RegIds for the same phone after 4 registering attempts on the GCM Server:

Records are: D1 : APA91bEYZYdKgdngfbxYIjyvhtWm-1ncGOBz1OUER8lM_BfnAwU8IwFAOkawMCgyETGTnHgTOUETKcfYUXUeRvDbEOEoSLexKNh6T9vo4FnBLD7ZajJ0FjahrTNTLrMIafzz0VPw3E5ApK4uCoUM6ibwETQrkDo2RQ
Records are: D2 : APA91bETu7NDrbBGhx4iSUB3YbYq3SG4ZitS_MFFL94CSk13hY_WhOf7HEwyshSnlb2iEmHja3T_qPq1PKfTPre1UGKHkGCpg3xW02HTwBhgp18kQoqUp-MEChN-BJqlDtnDh8A-dHXhGdCRYdd0ou_HYY-MQvOkxA
Records are: 3 : APA91bF2BM3UIg9eLk8Jkj3PwFTsvRD5-1p3CQ3QkFKkhfUm8rfbuchdfwITdErx4p8_L2XWu5f1dU6ZSn9L1uyjqNY6ZMvHsn4kXS2J6Csf1sdjGct444xZZl8P56bIqUaX5Deotm-4eUCD-RBEIHhBK24RTBvtuQ
Records are: 6 : APA91bFYWdORwtUP8b02RZjnL7UBrdBTk3_RRn818F1RV2kMF9T7eQvrGfjmg7qy61drJTlnFqORDmcxKnLiIGC13Gve9qYmO1xd2ZhJX72Llskpm_AWE8bSth7D_9iS6m-BSXcTe25vG4AMxOOmryfSbwR2VmwA-Q

回答1:

If you dynamically register the receiver, it isn't helpful if you receive a message when the app is not running. See this post:

Dynamic register of C2DM receiver using registerReceiver

If you want to ignore messages when the app is not active, you can set flags. But it seems like dynamic registration is not a good plan either way.