Android學(xué)習(xí)之---------服務(wù)(案例:音樂播放器)

我們手機中很多app在運行的過程中都能在后臺運行摔敛,例如邊聽歌邊打游戲,這一功能得益于服務(wù)全封,后臺功能屬于Android四大組件之一马昙。
下面通過音樂播放器的案列走進服務(wù):
服務(wù)(Service)是Android中的四大組件之一,它能夠長期在后臺運行切不提供用戶界面刹悴,即使用戶切換到另一應(yīng)用程序行楞,服務(wù)仍可在后臺運行敢伸。它的創(chuàng)建過程與創(chuàng)建Activity相似,只需繼承Service類即可恒削。

下面我們先來創(chuàng)建一個服務(wù):創(chuàng)建一個項目池颈,在項目中新建一個MyService類繼承自Service,然后會自動實現(xiàn)onBind()方法:

  public class MyService extends Service {
    @Nullable
    @Override
   public IBinder onBind(Intent intent) {
     return null;
 }
}

本服務(wù)目前沒有實現(xiàn)任何功能钓丰。需要注意的是琢歇,在MyService中有一個onBi()方法,該方法是Service類中唯一的抽象方法梦鉴,所以必須要在子類中實現(xiàn)李茫。
接下來我們需要在清單文件中配置,這是因為服務(wù)屬于Android四大組件之一肥橙,所以要在AndroidManifest.xml清單文件中進行注冊魄宏。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lxz.android0804">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <!--在此注冊服務(wù)信息-->
    <service android:name=".MyService"/>
</application>
</manifest>

至此服務(wù)便創(chuàng)建成功了,需要注意到是不要忘記在清單文件中注冊存筏,否則服務(wù)不會生效宠互。

服務(wù)與其他組件不同的是:Service不能自己主動執(zhí)行味榛,需要調(diào)用相應(yīng)的方法來啟動。啟動服務(wù)的方法有兩個予跌,分別是Context.startService()和Context.bindService()搏色。使用不同方式開啟服務(wù),服務(wù)的生命周期也會不同券册。
1频轿、startService方式開啟服務(wù)的生命周期:
onCreate()(第一次創(chuàng)建服務(wù)時執(zhí)行)→onStartCommend()(啟動服務(wù)調(diào)用的方法)→onDestroy(服務(wù)被銷毀時執(zhí)行的方法)
2、bindService方式開啟服務(wù)的生命周期:
onCreate()(第一次創(chuàng)建服務(wù)時執(zhí)行)→onBind(啟動服務(wù)調(diào)用的方法)→onUnbind(斷開服務(wù)綁定時執(zhí)行的方法)→onDestroy(服務(wù)被銷毀時執(zhí)行的方法)
兩種方式都可以顯現(xiàn)編寫播放器的功能烁焙,但為了全面起見略吨,我們采用混合開啟服務(wù)的方式來寫,而且這樣也有很大的優(yōu)點考阱。
讓服務(wù)在后臺長期運行,又調(diào)用服務(wù)里的方法流程:
1鞠苟、先調(diào)用startService 開啟一個服務(wù)
2乞榨、然后調(diào)用BindService方法,獲取中間人(運行服務(wù)中的方法)
3当娱、unBindService方法
4吃既、調(diào)用StopService方法

接下來就正式進入音樂播放器的編寫:
首先在來寫我們的布局頁面:

<LinearLayout       xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context="com.lxz.android0804.MainActivity">

<SeekBar
    android:id="@+id/seekbar"
    android:layout_width="300dp"
    android:layout_height="wrap_content"
    android:layout_marginBottom="0dp"
    android:layout_marginTop="20dp"
    />

<ImageButton
    android:id="@+id/btn_play"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:scaleType="fitXY" //scaleType等比例縮放屬性
    android:background="@null"
    android:onClick="startmusic"
    android:src="@drawable/start" />
</LinearLayout>

這里設(shè)置了一個進度條,和一個圖片按鈕跨细,同時給ImageButton設(shè)置了點擊事件鹦倚,采用線性布局,水平放置冀惭。這里在處理圖片按鈕時用到了一個圖片等比例縮放的屬性震叙,即:scaleType屬性。界面如圖顯示(主要用于功能的實現(xiàn)散休,所以沒有優(yōu)化界面的美觀度):


image.png

然后在MainActivity中來實現(xiàn)我們設(shè)置的點擊事件,同時開啟我們的服務(wù):

public class MainActivity extends AppCompatActivity {
 MyConn conn;//聲明
 MyService.MyBinder myBinder;
 private ImageButton imageButton;
 private SeekBar seekBar;  
 @Override
protected void onCreate(Bundle savedInstanceState) {     
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageButton=findViewById(R.id.btn_play);
    seekBar=findViewById(R.id.seekbar);
    Intent intent = new Intent(this, MyService.class);
    startService(intent);  //開啟服務(wù)
    conn=new MyConn(); //
    bindService(intent,conn,BIND_AUTO_CREATE);
}

class MyConn implements ServiceConnection{//自己定義一個MyConn類實現(xiàn)接口

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder service) {
      myBinder=(MyService.MyBinder) service;//得到傳過來的中間人,因為放音樂也需要用中間人媒楼,所以把中間人設(shè)置為全局變量
     }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {

    }
}
//播放音樂
public void startmusic(View view){
           }

  }
}

同時在MainActivity中得到我們設(shè)置imageButton跟seekBar。
因為在執(zhí)行Bindservice時我們需要實例化ServiceConnection接口的實現(xiàn)類戚丸,所以自己定義了一個MyConn類實現(xiàn)接口划址,重寫onServiceConnected()和onServiceDisconnected()方法。

那么接下來我們就要在MyService類里面完成我們想要實現(xiàn)的創(chuàng)建限府、播放夺颤、暫停最基本的功能:

      public class MyService extends Service {
private static final String TAG = "MyService";
String path="mnt/sdcard/2.mp3";
MediaPlayer mediaPlayer;//全局變量
@Nullable
@Override
public IBinder onBind(Intent intent) {
    return new MyBinder();
}

@Override
public void onCreate() {
    Log.i(TAG, "onCreate: 準備播放");
    super.onCreate();
    //準備音樂播放器流程
    mediaPlayer=new MediaPlayer();//局部變量,本方法有效
    try {
        mediaPlayer.setDataSource(path);
        mediaPlayer.prepare();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//播放音樂
public void play(){
    Log.i(TAG, "play: 開始播放");
    mediaPlayer.start();
}
//暫停
public void pause(){
    mediaPlayer.pause();
}
    }

在這里為了簡單我們直接聲明了音樂文件的路徑胁勺,然后實現(xiàn)各個功能世澜,在過程中我們使用了MediaPlayer來實現(xiàn)播放音樂的功能。在Android中播放音頻文件一般都是使用MediaPlayer類來實現(xiàn)署穗。
下面對MediaPlayer進行簡單的介紹下其中常用的方法:
setAudioStreamType:指定音頻文件類型必須在prepare()方法之前調(diào)用宜狐。
setDateSource():設(shè)置要播放的音頻文件的位置势告。
prepare():在開始播放之前調(diào)用這個方法來完成準備工作。
start():開始或繼續(xù)音頻播放抚恒。
pause():暫停播放音頻咱台。
reset():將MediaPlayer重置到剛剛創(chuàng)建的狀態(tài)。
seekTo():從指定的位置開始播放音頻俭驮。
stop():停止播放音頻回溺,調(diào)用該方法后MediaPlayer對象無法再播放音頻。
release():釋放掉與MediaPlayer對象相關(guān)的資源混萝。
isplaying():判斷當(dāng)前MediaPlayer是否正在播放遗遵。
getDuration():獲取載入音頻文件時長。
getCurrentPosition():獲取當(dāng)前播放音頻文件的位置逸嘀。
以上就是最常用的幾個方法了车要。

因為我們要播放音樂所以我們肯定也需要獲取音樂的播放時長,進度崭倘,當(dāng)前狀態(tài)等功能翼岁,所以就用到上面的方法:我們將其加入到我們的服務(wù)類中。

 //獲取歌曲時長(毫秒數(shù))
public int getDuration(){
    return mediaPlayer.getDuration();
}
//查看當(dāng)前播放進度(毫秒數(shù))
public int getCurrentPosition(){
    return mediaPlayer.getCurrentPosition();
}
//查看播放狀態(tài)
public boolean playstate(){
   return mediaPlayer.isPlaying();
}
//定位音樂播放器
public void setPosition(int newPosition){
    mediaPlayer.seekTo(newPosition);
}

因為Activity與服務(wù)時兩個不同的組件司光,所以當(dāng)我們在Activity中不能直接調(diào)用的服務(wù)中的方法琅坡,所以我們準備了一個中間人MyBinder來連接服務(wù)于Activity之間的關(guān)系,講各個方法放入進去残家。

class MyBinder extends  Binder{ //定義內(nèi)部類榆俺,中間人
    public void callMusic(){
        play();
    }
    public void stopMusic(){
        pause();
    }
    public boolean callPlayState(){
        return playstate();
    }
    public int callDuration(){
        return getDuration();
    }
    public int callCurrentPosition(){
        return getCurrentPosition();
    }
    public void callSetPosition(int x){
        setPosition(x);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坞淮,隨后出現(xiàn)的幾起案子茴晋,更是在濱河造成了極大的恐慌,老刑警劉巖回窘,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晃跺,死亡現(xiàn)場離奇詭異,居然都是意外死亡毫玖,警方通過查閱死者的電腦和手機掀虎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來付枫,“玉大人烹玉,你說我怎么就攤上這事〔玻” “怎么了二打?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掂榔。 經(jīng)常有香客問我继效,道長症杏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任瑞信,我火速辦了婚禮厉颤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凡简。我一直安慰自己逼友,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布秤涩。 她就那樣靜靜地躺著帜乞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪筐眷。 梳的紋絲不亂的頭發(fā)上黎烈,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音匀谣,去河邊找鬼照棋。 笑死,一個胖子當(dāng)著我的面吹牛振定,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肉拓,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼后频,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了暖途?” 一聲冷哼從身側(cè)響起卑惜,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驻售,沒想到半個月后露久,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡欺栗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年毫痕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迟几。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡消请,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出类腮,到底是詐尸還是另有隱情臊泰,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布蚜枢,位于F島的核電站缸逃,受9級特大地震影響针饥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜需频,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一丁眼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贺辰,春花似錦户盯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吃靠,卻和暖如春硫眨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巢块。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工礁阁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人族奢。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓姥闭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親越走。 傳聞我的和親對象是個殘疾皇子棚品,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容