Google GCM客户端在以编程方式取消注册/注册广播接收器后不发送消息

时间:2014-08-10 21:09:10

标签: android broadcastreceiver google-cloud-messaging onresume registering

我想注册/取消注册我用来接收来自GCM的消息的BroadcastReceiver。我已经在我的onResume()中声明并初始化了BroadcastReceiver.class,但是在我下次启动onPause()之后取消注册它时它不再发送消息,只有当我再次发送regId并注册GCM服务器时

BroadcastReceiver可以负责不发送消息吗? 或者在Manifest文件中注册BroadcastReceiver是否必不可少?

我真的很感激任何建议。

更新:

有趣的是,如果我以编程方式注册BroadcastReceiver,GCM服务器在GCM服务器上注册设备本身时会一直提供新的regId,当在Manifest中注册BroadcastReceiver时,GCM服务器提供相同的regId 。 WHY ??

注册/取消注册的方法:

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

完整的主要活动:

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



}

在GCM服务器上注册4次后,注册同一部手机:

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 个答案:

答案 0 :(得分:0)

如果您动态注册接收器,如果您在应用未运行时收到消息,则无效。看这篇文章:

Dynamic register of C2DM receiver using registerReceiver

如果您想在应用未处于活动状态时忽略消息,可以设置标记。但似乎动态注册不是一个好的计划。