2011-06-22 44 views
1

我使用教程从C2DM Tutorial,当我使用此代码在我的应用程序运行(我的应用程序有多个线程,并运行此C2DMessaging.register(getApplicationContext(),SENDERS_EMAIL_ID);在一个多线程提供ANR的C2DM广播意向。如何避免它?

。但是,即使我在单独的线程上运行此操作后,我也收到了下面的错误消息,并弹出了一个ANR,以为我看到在我的背景中,我的应用程序开始完美无缺了!!!!

我启动C2DM.register (...)是

  new Thread() { 
       public void run() { 
        try{ 
         C2DMessaging.register(getApplicationContext(), SENDERS_EMAIL_ID); 

        } catch (Exception e) { 
         Log.e(TAG, e.getMessage()); 
        } 
       } 
      }.start(); 

我这样做的错误日志是

E/ActivityManager( 162): ANR in com.example.myapp 
E/ActivityManager( 162): Reason: Broadcast of Intent { act=com.google.android.c2dm.intent.REGISTRATION cat=[com.example.myapp] flg=0x10 cmp=com.example.myapp/.c2dm.C2DMBroadcastReceiver (has extras) } 
E/ActivityManager( 162): Load: 0.63/0.24/0.32 
E/ActivityManager( 162): CPU usage from 5001ms to 0ms ago: 
E/ActivityManager( 162): 98% 29787/com.example.myapp: 98% user + 0.4% kernel/faults: 2 minor 
E/ActivityManager( 162): 1% 162/system_server: 0.4% user + 0.6% kernel/faults: 93 minor 
E/ActivityManager( 162): 0.8% 127/sdcard: 0% user + 0.8% kernel 
E/ActivityManager( 162): 0.6% 128/adbd: 0% user + 0.6% kernel/faults: 182 minor 
E/ActivityManager( 162): 0.6% 224/dhd_dpc: 0% user + 0.6% kernel 
E/ActivityManager( 162): 0.2% 240/com.android.phone: 0.2% user + 0% kernel 
E/ActivityManager( 162): 0.2% 29429/kworker/u:3: 0% user + 0.2% kernel 
E/ActivityManager( 162): 54% TOTAL: 49% user + 1.9% kernel + 2.1% iowait + 0.1% softirq 
E/ActivityManager( 162): CPU usage from 525ms to 1057ms later with 99% awake: 
E/ActivityManager( 162): 98% 29787/com.example.myapp: 96% user + 1.8% kernel 
E/ActivityManager( 162):  96% 29787/com.example.myapp: 96% user + 0% kernel 
E/ActivityManager( 162): 5.6% 162/system_server: 0% user + 5.6% kernel 
E/ActivityManager( 162):  5.6% 172/ActivityManager: 1.8% user + 3.7% kernel 
E/ActivityManager( 162):  1.8% 170/SensorService: 1.8% user + 0% kernel 
E/ActivityManager( 162): 2.7% 127/sdcard: 0% user + 2.7% kernel 
E/ActivityManager( 162): 2.7% 128/adbd: 0% user + 2.7% kernel/faults: 156 minor 
E/ActivityManager( 162):  2.7% 128/adbd: 0% user + 2.7% kernel 
E/ActivityManager( 162):  1.3% 11683/adbd: 0% user + 1.3% kernel 
E/ActivityManager( 162): 1.3% 224/dhd_dpc: 0% user + 1.3% kernel 

任何指针将非常感激!

谢谢。

为C2DMBroadcastReceiver的代码是

import android.app.Activity; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 

/** 
* Helper class to handle BroadcastReciver behavior. 
* - can only run for a limited amount of time - it must start a real service 
* for longer activity 
* - must get the power lock, must make sure it's released when all done. 
* 
*/ 
public class C2DMBroadcastReceiver extends BroadcastReceiver { 

    @Override 
    public final void onReceive(Context context, Intent intent) { 
     // To keep things in one place. 
     C2DMBaseReceiver.runIntentInService(context, intent); 
     setResult(Activity.RESULT_OK, null /* data */, null /* extra */);   
    } 
} 

的C2DMBaseReceiver是

import java.io.IOException; 

import android.app.AlarmManager; 
import android.app.IntentService; 
import android.app.PendingIntent; 
import android.content.Context; 
import android.content.Intent; 
import android.os.PowerManager; 
import android.util.Log; 

/** 
* Base class for C2D message receiver. Includes constants for the strings used 
* in the protocol. 
*/ 
public abstract class C2DMBaseReceiver extends IntentService { 
    private static final String C2DM_RETRY     = "com.google.android.c2dm.intent.RETRY"; 
    public static final String REGISTRATION_CALLBACK_INTENT = "com.google.android.c2dm.intent.REGISTRATION"; 
    private static final String C2DM_INTENT     = "com.google.android.c2dm.intent.RECEIVE"; 
    private static final String TAG       = "MyApp"; 
    // Extras in the registration callback intents. 
    public static final String EXTRA_UNREGISTERED   = "unregistered"; 
    public static final String EXTRA_ERROR     = "error"; 
    public static final String EXTRA_REGISTRATION_ID  = "registration_id"; 

    public static final String ERR_SERVICE_NOT_AVAILABLE = "SERVICE_NOT_AVAILABLE"; 
    public static final String ERR_ACCOUNT_MISSING   = "ACCOUNT_MISSING"; 
    public static final String ERR_AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED"; 
    public static final String ERR_TOO_MANY_REGISTRATIONS = "TOO_MANY_REGISTRATIONS"; 
    public static final String ERR_INVALID_PARAMETERS  = "INVALID_PARAMETERS"; 
    public static final String ERR_INVALID_SENDER   = "INVALID_SENDER"; 
    public static final String ERR_PHONE_REGISTRATION_ERROR = "PHONE_REGISTRATION_ERROR"; 

    private static final String WAKELOCK_KEY    = "MyApp"; 

    private static PowerManager.WakeLock mWakeLock; 
    private final String senderId; 

    /** 
    * The C2DMReceiver class must create a no-arg constructor and pass the 
    * sender id to be used for registration. 
    */ 
    public C2DMBaseReceiver(String senderId) { 
     // senderId is used as base name for threads, etc. 
     super(senderId); 
     this.senderId = senderId; 
    } 

    /** 
    * Called when a cloud message has been received. 
    */ 
    protected abstract void onMessage(Context context, Intent intent); 

    /** 
    * Called on registration error. Override to provide better error messages. 
    * 
    * This is called in the context of a Service - no dialog or UI. 
    */ 
    public abstract void onError(Context context, String errorId); 

    /** 
    * Called when a registration token has been received. 
    */ 
    public void onRegistered(Context context, String registrationId) 
      throws IOException { 
     // registrationId will also be saved 
    } 

    /** 
    * Called when the device has been unregistered. 
    */ 
    public void onUnregistered(Context context) { 
    } 

    @Override 
    public final void onHandleIntent(Intent intent) { 
     try { 
      Context context = getApplicationContext(); 
      if (intent.getAction().equals(REGISTRATION_CALLBACK_INTENT)) { 
       handleRegistration(context, intent); 
      } else if (intent.getAction().equals(C2DM_INTENT)) { 
       onMessage(context, intent); 
      } else if (intent.getAction().equals(C2DM_RETRY)) { 
       C2DMessaging.register(context, senderId); 
      } 
     } finally { 
      // Release the power lock, so phone can get back to sleep. 
      // The lock is reference counted by default, so multiple 
      // messages are ok. 

      // If the onMessage() needs to spawn a thread or do something else, 
      // it should use it's own lock. 
      mWakeLock.release(); 
     } 
    } 

    /** 
    * Called from the broadcast receiver. Will process the received intent, 
    * call handleMessage(), registered(), etc. in background threads, with a 
    * wake lock, while keeping the service alive. 
    */ 
    static void runIntentInService(Context context, Intent intent) { 
     if (mWakeLock == null) { 
      // This is called from BroadcastReceiver, there is no init. 
      PowerManager pm = (PowerManager) context 
        .getSystemService(Context.POWER_SERVICE); 
      mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 
        WAKELOCK_KEY); 
     } 
     mWakeLock.acquire(); 

     // Use a naming convention, similar with how permissions and intents are 
     // used. Alternatives are introspection or an ugly use of statics. 
     String receiver = context.getPackageName() + ".c2dm.MyC2dmReceiver"; 
     intent.setClassName(context, receiver); 

     context.startService(intent); 

    } 

    private void handleRegistration(final Context context, Intent intent) { 
     final String registrationId = intent.getStringExtra(EXTRA_REGISTRATION_ID); 
     String error = intent.getStringExtra(EXTRA_ERROR); 
     String removed = intent.getStringExtra(EXTRA_UNREGISTERED); 

     if (Log.isLoggable(TAG, Log.DEBUG)) { 
      Log.d(TAG, "dmControl: registrationId = " + registrationId 
        + ", error = " + error + ", removed = " + removed); 
     } 

     if (removed != null) { 
      // Remember we are unregistered 
      C2DMessaging.clearRegistrationId(context); 
      onUnregistered(context); 
      return; 
     } else if (error != null) { 
      // we are not registered, can try again 
      C2DMessaging.clearRegistrationId(context); 
      // Registration failed 
      Log.e(TAG, "Registration error " + error); 
      onError(context, error); 
      if ("SERVICE_NOT_AVAILABLE".equals(error)) { 
       long backoffTimeMs = C2DMessaging.getBackoff(context); 

       Log.d(TAG, "Scheduling registration retry, backoff = " 
         + backoffTimeMs); 
       Intent retryIntent = new Intent(C2DM_RETRY); 
       PendingIntent retryPIntent = PendingIntent 
         .getBroadcast(context, 0 /* requestCode */, retryIntent, 
           0 /* flags */); 

       AlarmManager am = (AlarmManager) context 
         .getSystemService(Context.ALARM_SERVICE); 
       am.set(AlarmManager.ELAPSED_REALTIME, backoffTimeMs, 
         retryPIntent); 

       // Next retry should wait longer. 
       backoffTimeMs *= 2; 
       C2DMessaging.setBackoff(context, backoffTimeMs); 
      } 
     } else { 
      try { 
       onRegistered(context, registrationId); 
       C2DMessaging.setRegistrationId(context, registrationId); 
      } catch (IOException ex) { 
       Log.e(TAG, "Registration error " + ex.getMessage()); 
      } 
     } 
    } 
} 

回答

0

我认为这是不发送注册信息,以谷歌,但在C2DMBroadcastReceiver从谷歌接收registration_id问题。 您是否在BroadcastReceiver中启动服务以进行注册处理? 请添加您的C2DMBroadcastReceiver的代码。

+0

确定。我添加了一些代码。能否请你帮忙。谢谢 – Sana

+0

另外我想指出,我确实收到id成功并将regId发布到服务器。 – Sana

+0

它的有趣,错误停止!唷! – Sana