当前位置: 首页 > 知识库问答 >
问题:

Google GCM客户端在以编程方式注销/注册BroadcastReceiver后不发送消息

白彦
2023-03-14

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

广播接收者是否有责任不发送消息?还是必须在清单文件中注册BroadcastReceiver??

如有任何建议,我将不胜感激。

更新:

有趣的是,如果我以编程方式注册BroadcastReceiver,那么当在GCM服务器上注册设备本身时,GCM服务器始终会提供一个新的regId,当BroadcastReceiver在清单中注册时,GCM服务器会提供相同的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次后,为同一部手机注册:

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

薛弘壮
2023-03-14

如果动态注册接收者,则在应用程序未运行时收到消息没有帮助。见此帖:

使用registerReceiver的C2DM接收机动态寄存器

如果要在应用不活动时忽略消息,可以设置标志。但似乎动态注册不是一个好计划。

 类似资料:
  • 在开始协议前,客户端在授权服务器注册。客户端在授权服务器上注册所通过的方式超出了本规范,但典型的涉及到最终用户与HTML注册表单的交互。 客户端注册不要求客户端与授权服务器之间的直接交互。在授权服务器支持时,注册可以依靠其他方式来建立信任关系并获取客户端的属性(如重定向URI、客户端类型)。例如,注册可以使用自发行或第三方发行声明或通过授权服务器使用信任通道执行客户端发现完成。 当注册客户端时,客

  • 本文向大家介绍Android BroadcastReceiver广播注册方式总结,包括了Android BroadcastReceiver广播注册方式总结的使用技巧和注意事项,需要的朋友参考一下 Android:BroadcastReceiver注册的方式分为两种: 静态注册 动态注册 1. 静态注册 在AndroidManifest.xml里通过标签声明 属性说明: 注册示例 当此App首次启动

  • 本规范不排除使用未注册的客户端。然而,使用这样的客户端超出了本规范的范围,并需要额外的安全性分析并审查其互操作性影响。

  • AWS Java 开发工具包是否提供与胶合模式注册表进行交互的任何方法?我正在寻找诸如注册架构,更新已注册架构的版本,删除架构等方法。我知道aws提供了这里提到的Python库方法 我正在寻找与注册表交互的Java方式。类似于Spring云模式注册表 AWS Glues还提供endpoint,但我不确定它们是否允许我与胶水模式注册表进行交互。 这个SO问题建议遵循aws提供的示例,但我正在专门寻找

  • Twilio布道者们好, 我们使用Twilio模块,可编程聊天,并使用Javascript客户端和Twilio.api,C#服务器API。 我们希望用户看到特定信道的信道和消息,但需要有条件地阻止他们发送消息。 我们可以禁用UI元素,但智能用户仍然能够访问Twilio客户端,并发送消息。

  • 有没有办法在不使用REST操作的情况下从Eureka服务器中删除注册实例?哪个是包含所有应用程序的数据结构? (很明显,我想删除他们在Eureka服务器中编写代码)。