Android四大組件之服務 – Android移動開發技術文章_手機開發 Android移動開發教學課程

 

很多情況下,一些與用戶很少需要產生交互的應用程序,我們一般讓它們在後臺運行就行瞭,而且在它們運行期間我們仍然能運行其他的應用。

為瞭處理這種後臺進程,Android引入瞭Service的概念。Service在Android中是一種長生命周期的組件,它不實現任何用戶界面。

基本概念

Ÿ   Service是一種在後臺運行,沒有界面的組件,由其他組件調用開始。

 

Ÿ   創建Service,定義類繼承Service,AndroidManifest.xml中定義<service>

 

Ÿ   開啟Service,在其他組件中調用startService方法

 

Ÿ   停止Service,調用stopService方法

 

1.在activity中調用service

 

 

/* 

 * 開啟服務 

 */ 

public void start(View view) { 

    Intent intent = new Intent(this, MyService.class); 

    startService(intent); 

/* 

 * 結束服務 

 */ 

public void stop(View view) { 

    Intent intent = new Intent(this, MyService.class); 

    stopService(intent); 

2.定義Service:

 

 

public class MyService extends Service { 

 

    /*

     * 綁定時調用

     */ 

    public IBinder onBind(Intent intent) { 

        return null; 

    } 

 

    /*

     * 開啟服務時調用

     */ 

    public void onCreate() { 

        super.onCreate(); 

        System.out.println("onCreate"); 

    } 

 

    /*

     * 結束服務時調用

     */ 

    public void onDestroy() { 

        super.onDestroy(); 

        System.out.println("onDestroy"); 

    } 

 

3.在清單文件中進行定義服務:<service android:name=".PMyService" />

 

電話錄音

 

電話錄音是使用服務來實現的,在後臺運行,使用監聽器來監聽電話的狀態,當來電話時,監聽器獲取到來電話的電話號碼,當用戶接聽後,就開始錄音,當監聽到電話的狀態掛斷後,停止錄音,並將錄音保存到sdcard中。

 

java代碼:

 

 

@Override 

public void onCreate() { 

    //拿到電話服務 

    TelephonyManager manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 

     

    //電話的狀態監聽器 

    manager.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE); 

 

private final class MyListener extends PhoneStateListener { 

    private String num; 

    private MediaRecorder recorder;   //錄音 

    private File file; 

    public void onCallStateChanged(int state, String incomingNumber) { 

        switch (state) { 

            //響鈴狀態 

            case TelephonyManager.CALL_STATE_RINGING: 

                //保存電話號 

                num = incomingNumber; 

                break; 

            //接通電話狀態 

            case TelephonyManager.CALL_STATE_OFFHOOK: 

                try { 

                    //設置文件保存位置 

                    file = new File(Environment.getExternalStorageDirectory(), num + "_" + System.currentTimeMillis() + ".3gp"); 

                     

                    //創建錄音器 

                    recorder = new MediaRecorder(); 

                     

                    //設置音頻的來源(麥克風) 

                    recorder.setAudioSource(AudioSource.MIC); 

                     

                    //采取3gp格式保存 

                    recorder.setOutputFormat(OutputFormat.THREE_GPP); 

                     

                    //設置編碼器 

                    recorder.setAudioEncoder(AudioEncoder.AMR_NB); 

                     

                    //輸出文件路徑 

                    recorder.setOutputFile(file.getAbsolutePath()); 

                     

                    //準備 

                    recorder.prepare(); 

                     

                    //錄音 

                    recorder.start(); 

                } catch (Exception e) { 

                    e.printStackTrace(); 

                } 

                break; 

                 

            //電話空閑狀態 

            case TelephonyManager.CALL_STATE_IDLE: 

                //電話掛斷後停止錄音 

                if (recorder != null) { 

                    recorder.stop(); 

                    recorder.release(); 

                } 

                break; 

        } 

    } 

 

權限:

 

 

   <!– 讀電話的狀態權限–> 

   <uses-permission android:name="android.permission.READ_PHONE_STATE" />  

   <!– 錄音權限–> 

<uses-permission android:name="android.permission.RECORD_AUDIO" />  

<!– sdCard讀的權限–> 

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  

<!– sdCard寫的權限–> 

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  

<!– 打開網絡權限–> 

<uses-permission android:name="android.permission.INTERNET" />  

 

 

綁定本地服務

綁定本地服務實際上就是activity和服務進行綁定,activity一般是和用戶進行交互,而服務一般是進行後臺的工作,如果activity中需要訪問服務中的一些方法,進行交互,這就需要進行綁定。

 

Ÿ   使用bindService綁定服務,傳入一個自定義的ServiceConnection用來接收IBinder

 

Ÿ   定義一個業務接口,其中定義需要的使用的方法

 

Ÿ   服務中自定義一個IBinder繼承Binder並實現業務接口,在onBind方法中返回

 

Ÿ   調用端將IBinder轉為接口類型,調用接口中的方法即可調用到服務中的方法

 

Activity和Service進行綁定示例:

 

Activity:

 

 

public class MainActivity extends Activity { 

    private QueryService qs; 

    private EditText editText; 

 

    public void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState); 

        setContentView(R.layout.main); 

        editText = (EditText) findViewById(R.id.id); 

         

        // 綁定服務, 傳入ServiceConnection用來接收IBinder 

        bindService(new Intent(this, PersonService.class), new MyConn(), BIND_AUTO_CREATE); 

    } 

 

    /*

     * 自定義的ServiceConnection用來接收IBinder

     */ 

    private final class MyConn implements ServiceConnection { 

        public void onServiceConnected(ComponentName name, IBinder service) { 

            qs = (QueryService) service; 

        } 

        public void onServiceDisconnected(ComponentName name) { 

        } 

    }                                                            

 

    /*

     * 根據Id獲取聯系人

     */ 

    public void queryName(View view) { 

        String id = editText.getText().toString(); 

        String name = qs.query(Integer.parseInt(id)); 

        Toast.makeText(this, name, 0).show(); 

    } 

Service:

 

 

public class PersonService extends Service { 

 

    private String[] data = { "zxx", "lhm", "flx" }; 

 

    /* www.aiwalls.com

     * 當綁定時調用此方法, 返回一個IBinder, 用來調用當前服務中的方法

     */ 

    public IBinder onBind(Intent intent) { 

        return new MyBinder(); 

    } 

 

    /*

     * 查詢方法

     */ 

    public String query(int id) { 

        return data[id]; 

    } 

 

    /*

     * 自定義IBinder, 實現QueryService業務接口, 提供給調用者訪問當前服務的方法

     */ 

    private final class MyBinder extends Binder implements QueryService { 

        public String query(int id) { 

            return PersonService.this.query(id); 

        } 

    } 

 

 

 

 

綁定遠程服務

Ÿ   遠程綁定服務時無法通過同一個接口來調用方法,這時就需要使用AIDL技術

 

Ÿ   將接口擴展名改為“.aidl”

 

Ÿ   去掉權限修飾符

 

Ÿ   gen文件夾下會生成同名接口

 

Ÿ   將服務中自定義的IBinder類改為繼承接口中的Stub

 

Ÿ   ServiceConnection中返回的IBinder是代理對象,不能使用強轉,改用Stub.asInterface()摘自:傅榮康專欄

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *