代码之家  ›  专栏  ›  技术社区  ›  Edmond Tamas

通过程序注销/注册BroadcastReceiver后,Google GCM客户端不发送消息

  •  0
  • Edmond Tamas  · 技术社区  · 12 年前

    我想注册/注销我用于从GCM接收消息的BroadcastReceiver。我已经在我的onResume()中声明并初始化了BroadcastReceiver.class,但在我下次启动应用程序时在onPause()中注销后,它将不再发送消息,除非我再次发送regId并在GCM服务器上注册。

    BroadcastReceiver是否可以负责不发送消息? 还是必须在Manifest文件中注册BroadcastReceiver??

    我非常感谢你的任何建议。

    更新:

    有趣的是,如果我以编程方式注册BroadcastReceiver,则在GCM服务器上注册设备时,GCM服务器始终会提供一个新的regId,当BroadcastReceive在Manifest中注册时,GCC服务器会提供相同的regId。为什么?

    注册/注销方法:

    @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次后,同一电话的RegIds:

    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 回复  |  直到 12 年前
        1
  •  0
  •   Community Mohan Dere    9 年前

    如果你动态注册接收者,如果你在应用程序未运行时收到一条消息,那就没用了。请参阅此帖子:

    Dynamic register of C2DM receiver using registerReceiver

    如果您想在应用程序未激活时忽略消息,可以设置标志。但无论怎样,动态注册似乎都不是一个好计划。