android中的service總結和小例子

什麼是service?

service是被“後臺服務”,它的運行不依賴ui界面,我個人還喜歡把它看着一種消息服務,因爲你可以在任何有 Context 的地方調用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,來控制它,你也可以在 Service 裏註冊 BroadcastReceiver。

service分類
a、按運行地點分類
本地服務(Local) 該服務依附在主進程上
遠程服務(Remote)該服務是獨立進程的(少見的,並且一般都是系統服務)
b、按運行類型分類
前臺服務 會在通知一欄顯示 ONGOING 的 Notificatio
後臺服務 默認的服務即爲後臺服務,即不會在通知一欄顯示 ONGOING 的 Notification
c、按使用方式分類(重要¥¥¥¥¥¥¥)
startService 啓動的服務 主要用於啓動一個服務執行後臺任務,不進行通信。停止服務使用stopService

bindService 啓動的服務 該方法啓動的服務要進行通信(即外部可以調用service內部的方法)。停止服務使用unbindService

startService 同時也 bindService 啓動的服務 停止服務應同時使用stepService與unbindService(這是混合服務)


三種開啓服務的生命週期的區別
startService方式開啓的服務,服務會長期在後臺運行,直到用戶手動停止服務或者調用stopService方法,其中onCreate方法只會執行一次,onstart()可能執行多次(對應調用startService的次數),並且系統只會創建Service的一個實例(因此你應該知道只需要一次stopService調用

bindService方式開啓服務會執行服務的onCreate方法 和 onBind()方法 onstart方法不會執行當連接建立後,服務會一直存在,直到調用它的Context對象銷燬(比如activity銷燬)或者調用了Context.unbindService()方法,系統將會自動停止Service,對應onDestroy將被調用。

如果一個Service是混合方式啓動,則該Service將會一直在後臺運行。並且不管如何調用,onCreate始終只會調用一次,對應startService調用多少次,Service的onStart便會調用多少次。調用unbindService將不會停止Service,而必須調用 stopService 或 Service的 stopSelf 來停止服務。這樣可以實現長期後臺運行和實現通信的


Thread線程和Service的區別

Thread:Thread 是程序執行的最小單元,它是分配CPU的基本單位。可以用 Thread 來執行一些異步的操作

Service:Service 是android的一種機制,當它運行的時候如果是Local Service,那麼對應的 Service 是運行在主進程的 main 線程上的。如:onCreate,onStart 這些函數在被系統調用的時候都是在主進程的 main 線程上運行的。如果是Remote Service,那麼對應的 Service 則是運行在獨立進程的 main 線程上。因此請不要把 Service 理解成線程。

startService方式開啓服務(電話竊聽器)

重要:四大組件都需要配置,因此在創建服務後需要在xml文件中配置

AndroidManifest.xml文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.alleged.phoneListener"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
    </uses-permission>
    <!-- 對外部文件的寫入和刪除權限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >
    </uses-permission>
    <!-- 音頻刻錄權限 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" >
    </uses-permission>
    <!-- 接收手機完全開啓狀態權限 -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" >
    </uses-permission>
    <!-- 讀取電話狀態權限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" >
    </uses-permission>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".phonelistener"></service>
        <receiver android:name=".BootBrodcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"></action>
            </intent-filter>
        </receiver>
    </application>

</manifest>

BootBrodcastReceiver設置開機啓動服務的廣播接受者

package com.alleged.phoneListener;

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

public class BootBrodcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // 接受到相應的廣播後,調用onReceive()方法
        //這裏調用要開啓的服務
        //創建出相應的意圖的對象 第一個參數是上下文 第二參數你要開啓的類
        System.out.println("廣播開啓");
        Intent listenerIntent = new Intent(context,phonelistener.class);

        context.startService(listenerIntent);

    }

}

service phoneListenerService.java

package com.alleged.phoneListener;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

public class phonelistener extends Service {
    private String TAG = "PhoneListenerService";// 這裏設置一個Log標誌,方便於調試

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    /* 複寫onCreate()方法,當這個服務被創建的時候就實現監聽 */
    @Override
    public void onStart(Intent intent, int startId) {

    };

    @Override
    public void onCreate() {
        System.out.println("oncreate is working");
        /* 取得本機的電話服務 //創建電話管理者 */
        TelephonyManager telmanager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        // 註冊一個電話監聽器 通過管理類的listen方法監聽 這裏要實現一個phoneStateListener對象,監聽狀態改變
        // 實現PhoneStateListener對象
        PhoneStateListener calllistener = new PhoneStateListener() {
            private String callNum;// 定義一個監聽電話號碼
            private boolean isRecord = false;// 定義一個當前是否正在複製的標誌
            private MediaRecorder recorder;// 媒體複製類

            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                // 判斷一下電話屬於什麼狀態
                switch (state) {
                // 無任何狀態
                case TelephonyManager.CALL_STATE_IDLE:
                    // 把來電號碼設置爲空
                    callNum = null;
                    // 判斷錄音是否爲空和錄音開關的狀態
                    if (recorder != null && isRecord) {
                        Log.i(TAG, "錄音完成");// 設定一個錄音完成的標誌,方便調試
                        recorder.stop();// 錄音完成,
                        recorder.reset();// 通過reset()方法回到Initialized狀態
                        recorder.release();// 釋放所有和MediaRecorder對象綁定的資源
                        isRecord = false;// 錄音完成,改變狀態標誌
                    }
                    break;
                // 代表響鈴狀態
                case TelephonyManager.CALL_STATE_RINGING:
                    // 獲取來電的電話號碼
                    this.callNum = incomingNumber;
                    break;
                // 代表接起電話
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    // 判斷來電號碼,是否是要監聽的電話號碼
                    if (callNum.equals("1234567")) {
                        Log.i(TAG, "開始錄音");
                        // 是要監聽的電話,就開始錄音
                        recorder = new MediaRecorder();
                        // 設置資源
                        // 定義聲音來自於麥克風
                        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                        // 設置輸出格式爲3gp格式
                        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                        // 定我編碼
                        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                        // 此處定義一個format類,方便對錄音文件進行命名
                        SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");
                        String fileName = this.callNum + "_" + format.format(new Date());
                        System.out.println(
                                "/mnt/sdcard/luyin.3gp");
                        recorder.setOutputFile("/mnt/sdcard/luyin.3gp");
                        // 準備資源
                        try {
                            recorder.prepare();
                        } catch (IllegalStateException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        recorder.start(); // 開始刻錄
                        isRecord = true;// 標誌錄音成功
                        System.out.println("開始錄製");
                    } else {
                        System.out.println("不是想要錄音的電話號碼");
                        Log.e(TAG, "不是想要錄音的電話號碼");
                    }

                }
                super.onCallStateChanged(state, incomingNumber);

            }


        };
        // 正式監聽
        telmanager.listen(calllistener, PhoneStateListener.LISTEN_CALL_STATE);
        super.onCreate();
    }

}

(android的4.0後這個種服務安裝啓動的時候需要一個界面,爲了安全)
package com.alleged.phoneListener;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    System.out.println("ma de zhi zhang");
    //監聽器的實現步驟
    //第一步:註冊一個廣播接受者
    //設置爲開機啓動的廣播
    //開啓服務
    //在onstart 定一個電話監聽類
    //在監聽類中設置管理者
    //註冊一個監聽類
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

}

混合開啓服務的小例子
mainActivity.java

package com.alleged.hybrid;

import android.support.v7.app.ActionBarActivity;

import com.alleged.musicService.Ibinder;
import com.alleged.musicService.music_Service;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;

public class MainActivity extends ActionBarActivity {
    private Context context;
    private Ibinder binder;
    private MyConn conn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        //在頁面啓動就開啓服務
        Intent intent = new Intent(context, music_Service.class);
        context.startService(intent);
    }

    public void startService(View v) {
        //開啓服務
    }

    public void bindService(View v) {
        System.out.println("bindservice");
        Intent intent = new Intent(context, music_Service.class);
        conn = new MyConn();
        if(conn!=null){
            bindService(intent, conn, BIND_AUTO_CREATE);
        }

    }

    public void unbindService(View v) {
        conn = new MyConn();
        context.unbindService(conn);

    }

    public void stopService(View v) {
        Intent intent = new Intent(context, music_Service.class);
        context.stopService(intent);

    }
    public void play_music(View v){
        binder.playMusic();
    }
    public void stop_music(View v){
        binder.sleepmusic();
    }
    public void nextmusic(View v){
        binder.nextOne();
    }
    public void prevmusic(View v){
        binder.prev();
    }
/*  public class myconn implements ServiceConnection{
        //連接成功
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            System.out.println("連接成功 ");
            binder = (Ibinder) service;
            System.out.println("連接成功 ");
        }

        //連接失敗
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }

    }*/
    private class MyConn implements ServiceConnection {

        // 當連接成功時候調用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 獲取我們定義的中間人對象

            binder = (Ibinder) service;

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }

    }
}

music_service.java

package com.alleged.musicService;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;

public class music_Service extends Service {

    //IBinder類返回,提供接口調用方法內部的方法
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return new myIBinder();
    }
    public void play_Music(){
        System.out.println("音樂播放");
    }
    public void sleep_music(){
        System.out.println("音樂暫停");
    }
    public void next_One(){
        System.out.println("下一首");
    }
    public void prev_one(){
        System.out.println("上一首");
    }
    public class myIBinder extends Binder implements Ibinder{

        @Override
        public void playMusic() {
            play_Music();

        }

        @Override
        public void sleepmusic() {
            sleep_music();
        }

        @Override
        public void nextOne() {
            next_One();

        }

        @Override
        public void prev() {
            prev_one();

        }

    }


}

佈局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.alleged.hybrid.MainActivity" >

    <Button
        android:id="@+id/button1"
        android:text="startService"
        android:onClick="startService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" />

    <Button
        android:id="@+id/button2"
        android:onClick="bindService"
        android:text="bindService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/button3"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="58dp" />

    <Button
        android:id="@+id/button3"
        android:onClick="unbindService"
        android:text="unbindService"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button2"
        android:layout_below="@+id/button1"
        android:layout_marginTop="151dp" />

    <Button
        android:id="@+id/buttton4"
        android:onClick="stopService"
        android:text="stopService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button2"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="30dp" />

    <Button
        android:id="@+id/stop_music"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/next"
        android:layout_below="@+id/next"
        android:onClick="stop_music"
        android:text="暫停" />

    <Button
        android:id="@+id/prev"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/buttton4"
        android:layout_below="@+id/button2"
        android:layout_marginTop="42dp"
        android:onClick="prevmusic"
        android:text="上一首" />

    <Button
        android:id="@+id/next"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/prev"
        android:layout_alignBottom="@+id/prev"
        android:layout_marginLeft="31dp"
        android:layout_toRightOf="@+id/prev"
        android:onClick="nextmusic"
        android:text="下一首" />

    <Button
        android:id="@+id/play_music"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/stop_music"
        android:layout_alignBottom="@+id/stop_music"
        android:layout_toLeftOf="@+id/next"
        android:onClick="play_music"
        android:text="播放" />

</RelativeLayout>

配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.alleged.hybrid"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="com.alleged.musicService.music_Service">
         </service>
    </application>

</manifest>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章