編輯:關於android開發
“Service”意思即“服務”的意思,像 Windows 上面的服務一樣,服務是在後台上運行,承擔著靜悄悄的不為人所注意的工作。Service運行在後台,它是不可見的、無界面的程序。Service可以在很多場合的應用中使用,比如播放多媒體的時候用戶啟動了其他Activity,這個時候程序要在後台繼續播放;比如檢測SD卡上文件的變化;再或者在後台記錄用戶的地理信息位置的改變;或者啟動一個服務來運行並一直監聽某種動作等等。
Local Service 用於應用程序內部。用於實現應用程序自己的一些耗時任務,比如查詢升級信息,並不占用應用程序比如Activity所屬線程,而是單開線程後台執行,這樣用戶體驗比較好。
啟動service有兩種方法:
1)、 Context.startService()
調用者與服務之間沒有關聯,即使調用者退出,服務仍可運行
2)、 Context.bindService()
調用者與服務綁定在一起,調用者一旦退出,服務也就終止
被啟動的服務是由其它組件調用startService()方法而啟動的,該方法會導致被啟動服務的生命周期方法onStartCommand()被回調。當服務是被啟動狀態後,其生命周期與啟動它的組件無關,即使啟動服務的組件(Activity,BroadcastReceiver)已經被銷毀,該服務還可以在後台無限期運行。除非調用stopSelf()或stopService()來停止該服務。
綁定服務是允許其它應用程序綁定並且與之交互的Service的實現類。為了提供綁定,必須實現onBind()回調方法。該方法返回IBinder對象,它定義了服務類與Activity交互的程序接口。
Activity通過bindService()方法綁定到服務類,同時Activity必須提供ServiceConnection接口的實現類,它監視Activity與服務類之間的連接。在重寫ServiceConnection接口的onServiceConnected()方法時,實現了將服務類順利賦值到了Activity中,實現了在Activity中使用該服務類並執行其中的方法。
onStartCommand()方法有三種返回值:
【備注:】
以上三種情況,可以理解為發生車禍後的人:
Remote Service 用於android系統內部的應用程序之間。可以定義接口並把接口暴露出來,以便其他應用進行操作。可被其他應用程序復用,比如天氣預報服務,其他應用程序不需要再寫這樣的服務,調用已有的即可。
【詳細說明:】
【詳細說明:】
【備注:】
public class MusicService extends Service {
private MediaPlayer mediaPlayer;
private boolean isStop = true;
@Nullable
@Override
public IBinderonBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
//當音樂播放完成時調用
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//播放完成之後發送廣播給Activity
Intent intent = new Intent("play_completion");
sendBroadcast(intent);
}
});
}
// AlertDialog.Builder b = newAlertDialog.Builder(this);
}
@Override
public int onStartCommand(Intent intent, intflags, int startId){
//獲得Activity傳遞過來的state
int state= intent.getIntExtra("state", 0);
switch (state){
//開始播放
case 0:
if (isStop) {
preparePlayMusic();
isStop = false;
} else if (mediaPlayer != null &&!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
break;
//暫停播放
case 1:
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
break;
//停止播放
case 2:
if (mediaPlayer != null) {
mediaPlayer.stop();
isStop = true;
}
break;
}
//START_STICKY,被系統回收之後,服務重啟,同時intent為null
//START_NOT_STICKY,被系統回收之後,服務不會重啟
//START_REDELIVER_INTENT,被系統回收之後,服務重啟,同時intent還為之前的intent
return this.START_NOT_STICKY;
}
private void preparePlayMusic() {
try {
//重置MediaPlayer
mediaPlayer.reset();
//設置播放數據源
mediaPlayer.setDataSource(Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +
"xiami" + File.separator + "audios" + File.separator + "被動.mp3"
);
//准備播放
mediaPlayer.prepare();
//開始播放
mediaPlayer.start();
//設置是否循環播放
mediaPlayer.setLooping(false);
} catch (IOExceptione) {
e.printStackTrace();
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
public class MainActivity extends AppCompatActivity {
private Intent intent;
private MyReceiver myReceiver;
private IntentFilter intentFilter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(this, MusicService.class);
myReceiver = new MyReceiver();
intentFilter = new IntentFilter();
intentFilter.addAction("play_completion");
}
public void start(View view) {
intent.putExtra("state", 0);
startService(intent);
}
public void pause(View view) {
intent.putExtra("state", 1);
startService(intent);
}
public void stop(View view) {
intent.putExtra("state", 2);
startService(intent);
}
@Override
protected void onStart() {
super.onStart();
registerReceiver(myReceiver,intentFilter);
}
@Override
protected void onStop() {
super.onStop();
unregisterReceiver(myReceiver);
}
}
不管是何種Service,它默認都是在應用程序的主線程(亦即UI線程)中運行的。所以,如果你的Service將要運行非常耗時或者可能被阻塞的操作時,你的應用程序將會被掛起,甚至會出現ANR錯誤。為了避免這一問題,你應該在Service中重新啟動一個新的線程來進行這些操作。現有兩種方法大家參考:
① 直接在Service的onStartCommand()方法中新建一個線程來執行;
② Android SDK 中為我們提供了一個現成的Service類來實現這個功能,它就是IntentService,它主要負責以下幾個方面:
IntentService使用隊列的方式將請求的Intent加入隊列,然後開啟一個worker thread(線程)來處理隊列中的Intent,對於異步的startService請求,IntentService會處理完成一個之後再處理第二個,每一個請求都會在一個單獨的workerthread中處理,不會阻塞應用程序的主線程。
這裡就給我們提供了一個思路,如果有耗時的操作可以在Service裡面開啟新線程,也可以使用IntentService來處理耗時操作。但你若是想在Service中讓多個線程並發的話,就得使用第一種方法,在Service內部起多個線程。
2.MusicService核心代碼:
public class MyService extends Service {
private MediaPlayer mediaPlayer;
private boolean isStop = true;
private File[] files;
private int currentPosition = 0;
//創建服務時調用
@Override
public void onCreate() {
super.onCreate();
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer();
// preparePlayMusicx();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
currentPosition++;
preparePlayMusicx();
isStop = false;
}
});
}
Log.d("lenve", "onCreate:");
}
private void preparePlayMusicx() {
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(files[currentPosition].getAbsolutePath());
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOExceptione) {
e.printStackTrace();
}
}
//創建時調用
@Nullable
@Override
public IBinderonBind(Intent intent) {
files =((MusicFiles) intent.getSerializableExtra("files")).getFiles();
Log.d("lenve", "onBind:");
return new MyBinder();
}
//解除綁定時調用
@Override
public boolean onUnbind(Intent intent) {
Log.d("lenve", "onUnbind:");
return super.onUnbind(intent);
}
//解除綁定時調用
@Override
public void onDestroy() {
super.onDestroy();
Log.d("lenve", "onDestroy:");
}
//自定義一個類繼承自Binder
class MyBinderextends Binder {
//在該類中定義一個方法,該方法返回當前Service的實例
public MyServicegetService() {
//返回當前Service的實例
return MyService.this;
}
}
public void play() {
if (isStop) {
preparePlayMusicx();
isStop = false;
} else if (mediaPlayer != null &&!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
public void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
public void stop() {
if (mediaPlayer != null) {
mediaPlayer.stop();
isStop = true;
}
}
}
3.Activity核心代碼:
public class MainActivity extends AppCompatActivity {
private Intent intent;
private ServiceConnection conn;
private MyService myService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//獲取音樂文件列表
File[] listFiles = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator + "xiami"+ File.separator + "audios").listFiles(new FileFilter(){
//過濾出所有的mp3文件
@Override
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".mp3")) {
return true;
}
return false;
}
});
intent = new Intent(this, MyService.class);
intent.putExtra("files", new MusicFiles(listFiles));
//當Activity和Service產生連接之後觸發該方法
//Activity和Service連接斷開後調用該方法
conn = new ServiceConnection() {
//當Activity和Service產生連接之後觸發該方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myService = ((MyService.MyBinder) service).getService();
Log.d("lenve", "onServiceConnected:");
}
//Activity和Service連接斷開後調用該方法
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("lenve", "onServiceDisconnected:");
}
};
//綁定服務,返回值表示綁定是否成功
boolean flag = bindService(intent, conn,Service.BIND_AUTO_CREATE);
}
public void bindService(View view) {
boolean flag = bindService(intent, conn,Service.BIND_AUTO_CREATE);
}
public void unbindService(View view) {
unbindService(conn);
}
public void play(View view) {
myService.play();
}
public void pause(View view) {
myService.pause();
}
public void stop(View view) {
myService.stop();
}
}
Android操作系統嘗試盡可能長時間保持應用的進程,但當可用內存很低時要移走一部分進程。哪些程序可以運行,哪些要被銷毀?答案是:重要級別低的進程可能被淘汰。
按照重要性排列,一共可以分成5級:
用戶此時需要處理和顯示的進程。符合下列條件任何一個,這個進程就被認為是前台運行進程。
銷毀前台運行進程是系統萬不得已的、最後的選擇——當內存不夠系統繼續運行下去時,殺掉一些前台進程來保證能夠響應用戶的需求。
一個可用進程沒有任何前台組件,但它仍然可以影響到用戶的界面。下面情況發生時,可以稱該進程為可用進程。
它是一個非前台的activity,但對用戶仍然可用(onPause()方法已經被調用)。例如:前台的activity是一個允許上一個activity可見的對話框。也就是說當前activity中是一個對話框,對話框之外的地方能看到前一個activity的界面。
服務進程是一個通過調用startService()方法啟動的服務,並且不屬於前兩種情況。盡管服務進程沒有直接被用戶看到,但他們確實是用戶所關心的,比如後台播放音樂或網絡下載數據,所以系統保證他們的運行。
一個後台進程就是非當前正在運行的activity(activity的onStop()方法已經被調用),他們不會對用戶體驗造成直接的影響,當沒有足夠內存來運行前台可見程序時,他們將會被終止。
通常,後台進程會有很多個在運行,LRU最近使用程序列表來保證經常運行的activity能最後一個被終止。
一個空線程沒有運行任何可用應用程序,保留他們的唯一原因是為了設立一個緩存機制,來加快組件啟動的時間。系統經常殺死這些內存來平衡系統的整個系統的資源,進程緩存和基本核心緩存之間的資源。、
1.Service是Android四大組件中與Activity最相似的組件,它們都代表可執行的程序
2.Service與Activity的區別:
>Service一直在後台運行,它沒有用戶界面,所以絕不會到前台來
>它完全具有自己的生命周期
3.應用場景:
>音樂播放器、後台下載等
4.Activity與Service的選擇標准
>如果在運行時需要向用戶呈現界面,或該程序需要與用戶交互,就需要使用Activity
>否則就應該考慮使用Service
5.Service分類
>本地服務(在應用內)
>遠程服務(在另一個應用內)
6.開發者開發Service的步驟與開發Activity的步驟很相似:
A.創建一個類,繼承Service
B.重寫Service類中的相關生命周期方法
C.別忘記在清單文件中進行注冊
7.Service與Activity的相似處:
>都是從Context派生出來,因此都可以調用Context裡定義的如getResources()、getContentResolver()等方法
8.服務的啟動方式:
>服務不能自己運行,需要通過調用Context.startService()或Context.bindService()方法啟動服務
>兩種啟動方式的區別:
startService()啟動服務,啟動者與服務之間沒有關聯,即使訪問者退出了,服務仍然運行
bindService()啟動服務,啟動者與服務之間綁定在了一起,啟動者退出,則服務也就終止--"不求同生,但求同死"
9.服務的結束方式:
>采用Context.startService()啟動的服務,只能調用Context.stopService()終止服務,
服務結束會調用onDestroy()方法啟動服務
>采用bindService()啟動的服務,隨著訪問者的退出而自動退出
10.注意:
>startService()啟動的服務,啟動者退出時,服務不會停止,除非調用stopService()
>bindService()啟動服務,啟動者退出時,服務也應該隨之終止
>service雖然在後台運行,也不要在其中執行耗時的任務(如網絡下載),請在相應的方法中開啟一個線程來處理
通過JAVA代碼獲取手機的一些基本信息(本機號碼,SDK版本,系統版本,手機型號),javasdk代碼如下: package com.zzw.getPhoneInfos
Android開發學習之路-Android中使用RxJava,-androidrxjavaRxJava的核心內容很簡單,就是進行異步操作。類似於Handler和Async
個人應用開發詳記. (一),個人應用開發 心血來潮. 突然想開發一個視頻分享社區類的APP. 於是想了就開始做~ 博客就來記錄開發過程
Android 扒開美女衣服,android扒開美女本文主要實現一個小的扒開美女衣服的游戲項目 效果如下: 項目布局設計: <FrameLayout xmlns