1. 程式人生 > >Android Activity接收Service傳送的廣播

Android Activity接收Service傳送的廣播

最近接觸Android,有很多不明白的地方,也走了很多彎路,現在將我今天走的彎路貼上來,也為了避免初學者也走這種彎路。

  Android中Activity接收廣播的方式是建一個內部類,該內部類繼承BroadcastReceiver類,而Service端在完成一個耗時操作後,可以傳送廣播用來通知別的元件完成任務了,這樣就實現了Service與Activity的通訊,Service的程式碼比較簡單,如下所示

複製程式碼
public class PassengerService extends Service {
    private ThreadGroup myThreads = new ThreadGroup("ServiceWorker");//
用ThreadGroup類而不是Thread類,因為Service中可能有多個耗時的子執行緒 @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); new Thread(myThreads, new DownLoadAd(), "background").start();//Service已啟動,就開始子執行緒 } @Override public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub return null; } //Service中要實現的執行緒,以休眠5秒錶示一個耗時操作 class DownLoadAd implements Runnable { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block
e.printStackTrace(); } Intent intent = new Intent(); intent.setAction("polly.liu.Image");//用隱式意圖來啟動廣播 intent.putExtra("msg", "圖片下載好了"); sendBroadcast(intent); } } }
複製程式碼

這一步比較簡單,基本上不會有什麼疑問。我自己在做Activity端的接收程式時,遇到了幾點問題,下面一一呈現:

  我最初的程式碼如下:

  Activity:

複製程式碼
public class LoginActivity extends Activity{
    BroadcastMain receiver;
    //內部類,實現BroadcastReceiver
    public class BroadcastMain extends BroadcastReceiver{
        //必須要過載的方法,用來監聽是否有廣播發送
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(LoginActivity.this, intent.getStringExtra("msg"), 1).show();        
        }
    }    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.login);
        receiver = new BroadcastMain();
    }
}
複製程式碼

  然後AndroidManifest中添加了

<receiver android:name="polly.liu.LoginActivity.BroadcastMain">
            <intent-filter>
                <action android:name="polly.liu.Image"/>
            </intent-filter>
</receiver>

  程式執行,出錯,報錯原因大概是不能例項化polly.liu.LoginActivity.BroadcastMain這個類,於是我好像明白了在AndroidManifest不能新增內部類,於是尋找在程式碼中註冊BroadcastMain這個廣播接收類的方法,於是程式碼改變如下:

複製程式碼
public class LoginActivity extends Activity{
    BroadcastMain receiver;
    //內部類,實現BroadcastReceiver
    public class BroadcastMain extends BroadcastReceiver{
        //必須要過載的方法,用來監聽是否有廣播發送
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(LoginActivity.this, intent.getStringExtra("msg"), 1).show();        
        }
    }    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.login);
        receiver = new BroadcastMain();
        //新添程式碼,在程式碼中註冊廣播接收程式
        IntentFilter filter = new IntentFilter();
        filter.addAction("polly.liu.Image");
        registerReceiver(receiver, filter);
    }
}
複製程式碼

  一執行,沒報錯,並且程式執行5秒以後,彈出了Toast,“圖片下載成功”,有點沾沾自喜,但是關閉程式,第二次再啟動程式以後,並未彈出“圖片下載成功”,翻來覆去找原因,未果,但是,一個手賤,用騰訊手機助手將所有無關程序關閉以後,再重新執行程式,又彈出“圖片下載成功”的提示了,於是覺得是Service生命週期的原因,果斷修改程式碼:

複製程式碼
public class LoginActivity extends Activity{
    BroadcastMain receiver;
    //內部類,實現BroadcastReceiver
    public class BroadcastMain extends BroadcastReceiver{
        //必須要過載的方法,用來監聽是否有廣播發送
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(LoginActivity.this, intent.getStringExtra("msg"), 1).show();    
        }
    }    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.login);
        receiver = new BroadcastMain();
        //新添程式碼,在程式碼中註冊廣播接收程式
        IntentFilter filter = new IntentFilter();
        filter.addAction("polly.liu.Image");
        registerReceiver(receiver, filter);
    }
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Intent intent = new Intent();
        intent.setClass(this, PassengerService.class);
        stopService(intent);
    }
}
複製程式碼