版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
Android主要開發(fā)組件目標學員:學習目標:
課程時長:Android中級開發(fā)者ActivityIntentContentProviderServiceBroadcastReceiver6學時,270分鐘1Activity2Intent4Service3ContentProvider課程目錄4BroadcastReceiver5理解Android應用中四大重要組件及BroadcastReceiver熟練使用Android四大組件及BroadcastReceiver進行項目開發(fā)Activity生命周期Intent的傳輸機制ContentProvider的存儲機制Service的使用AIDL服務1Activity2Intent4Service3ContentProvider課程目錄4BroadcastReceiver5Activity對開發(fā)者而言,Activity是Android應用程序的入口。在Activity類中定義了一系列的生命周期方法,比如onCreate()、onResume()、onStart()、onPause()、onStop()和onDestroy(),Android系統(tǒng)會在適當?shù)臅r候調用對應的生命周期方法。
Activity的狀態(tài)運行
當Activity位于堆棧的頂部時,它就處于運行狀態(tài)(active)。暫停
當Activity失去了焦點,但是依然可見時,Activity就處于暫停狀態(tài)(paused),維持著成員信息和所有狀態(tài)。停止
當Activity完全被其他的Activity覆蓋時,它就處于停止狀態(tài)(stopped),處于停止狀態(tài)的Activity依然維持著成員信息和所有狀態(tài),只是變得不可見了。銷毀
當Activity處于停止或者暫停狀態(tài)時,系統(tǒng)可能要求它結束生命周期,或者直接把它所在的進程殺死,進而從內存中刪除它,此時的Activity就被銷毀了。Activity的生命周期圖publicclassActivityextendsApplicationContext{protectedvoidonCreate(){}protectedvoidonStart(){}protectedvoidonRestart(){}protectedvoidonResume(){}protectedvoidonPause(){}protectedvoidonStop(){}protectedvoidonDestroy(){}}創(chuàng)建Activitypackagecom.chinasofti.etc;importandroid.app.Activity;importandroid.os.Bundle;publicclassHelloActivityextendsActivity{@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);}}注冊Activity<xmlversion="1.0"encoding="utf-8"><manifestxmlns:android="/apk/res/android"package="com.chinasofti.etc"android:versionCode="1"android:versionName="1.0"><applicationandroid:icon="@drawable/icon"android:label="@string/app_name"><activityandroid:name=".HelloActivity"android:label="@string/app_name"><intent-filter><actionandroid:name="ent.action.MAIN"/><categoryandroid:name="ent.category.LAUNCHER"/></intent-filter></activity></application><uses-sdkandroid:minSdkVersion="7"/></manifest>啟動ActivitystartActivity(Intent)方法用于啟動一個新的Activity
當Activity位于堆棧的頂部時,它就處于運行狀態(tài)(active)。startActivityForResult(Intent,int)可以用于啟動Activity并返回結果
其中參數(shù)int代表本次調用 onActivityResult(int,int,Intent)方法返回數(shù)據
ActivityAintentActivityBActivity之間傳遞數(shù)據protectedvoidonListItemClick(ListViewl,Viewv,intposition,longid){ super.onListItemClick(l,v,position,id); Intentintent=newIntent(this,DetailActivity.class); intent.putExtra("name",peoples[position]); startActivity(intent);} protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //獲得Intent并從中讀取附帶的數(shù)據
Intentintent=getIntent(); Stringname=intent.getStringExtra("name"); TextViewview=newTextView(this); view.setText("您選擇了"+name); setContentView(view); }演示Activity生命周期演示Activity的生命周期本節(jié)的例子代碼是demo\activity運行此案例,ContactsActivity和DetailActivity界面分別如下圖所示,我們可以在Eclipse開發(fā)工具中切換到DDMS頁面查看ContactsActivity及DetailActivity的生命周期情況。演示Activity生命周期處理配置變化Activity是與用戶交互最主要的機制,當設備的配置(屏幕方向、語言)等發(fā)生變化時,系統(tǒng)應該采取必要的措施處理此狀況。在AndroidManifest.xml中通過定義android:configChanges屬性來指明監(jiān)聽的配置變化,當配置發(fā)生變化時,Activity的onConfigurationChanged()方法會被調用,開發(fā)者可以在這里處理。如果未做任何處理,由于設備的配置變化往往需要應用重新裝載資源,因此系統(tǒng)會銷毀Activity并重新啟動。Configuration類簡介Configuration類專門用于描述手機設備上的配置信息,這些配置信息既包括用戶特定配置項,也包括系統(tǒng)的動態(tài)設備配置.
獲取Configuration對象的方法:getResources().getConfiguration();
該類的一些描述系統(tǒng)信息的屬性:floatfontScale:字體縮放因子intkeyBoard:鍵盤類型.KEYBOARD_NOKEYS,KEYBOARD_QWERTY,KEYBOARD_12KEYintkeyboardHidden:當前鍵盤是否可用.Localelocale:intmcc:移動信號國家碼intmnc:移動信號網絡碼intnavigation:方向導航設備的類型.NAVIGATION_NONAV,NAVIGATION_DPADNAGIVATION_TRACKBALL,VAGIVATION_WHEELintorientation:ORIENTATION_LANDSCAPE(橫向),ORIENTATION_PORTRAIT(豎向),ORIENTATION_SQUARE(方形)inttouchscreen:TOUCHSCREEN_NOTOUCH,TOUCHSCREEN_STYLUSTOUCHSCREEN_FINGER案例1:獲取系統(tǒng)設備狀態(tài)Configurationc=MainActivity.this.getResources().getConfiguration();Stringscreen=c.orientation==Configuration.ORIENTATION_LANDSCAPE"橫向屏幕":"豎向屏幕";StringmncCode=c.mcc+"";StringnaviName=c.orientation==c.NAVIGATION_NONAV"沒有方向控制":c.orientation==c.NAVIGATION_WHEEL"滾輪控制方向":c.orientation==c.NAVIGATION_TRACKBALL"軌跡球控制方向":c.orientation==c.NAVIGATION_DPAD"dpad控制方向盤":"未指定";Stringtouchname=c.touchscreen==c.TOUCHSCREEN_FINGER"指控":c.touchscreen==c.TOUCHSCREEN_STYLUS"手寫筆":"無觸摸屏";
參見案例:test_configuration1案例2:重寫onConfigurationChanged響應系統(tǒng)設置更改需求說明:調用Activity中的setRequestedOrientation(int)方向來修改屏幕的方向,在onConfigurationChanged()中監(jiān)聽這個變化。
步驟:1.配置:
<!--授予程序修改系統(tǒng)設置的權限--><uses-permissionandroid:name="android.permission.CHANGE_CONFIGURATION"/>
<activityandroid:name=".MainActivity"android:label="@string/app_name"
android:configChanges="orientation"
>2.使用一個按鈕來改變屏幕方向
publicvoidonClick(Viewv){ Configurationc=MainActivity.this.getResources().getConfiguration(); if(c.orientation==Configuration.ORIENTATION_LANDSCAPE){ MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } if(c.orientation==Configuration.ORIENTATION_PORTRAIT){ MainActivity.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } }
案例2:重寫onConfigurationChanged響應系統(tǒng)設置更改步驟三:重寫onConfigurationChanged方法.@Override//重寫onConfigurationChanged方法用于監(jiān)聽publicvoidonConfigurationChanged(ConfigurationnewConfig){super.onConfigurationChanged(newConfig);Stringscreen=newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE"橫向":"豎向";Toast.makeText(MainActivity.this,screen,Toast.LENGTH_LONG).show();}常見面試問題1.橫豎屏切換時候activity的生命周期
1、不設置Activity的android:configChanges時,切屏會重新調用各個生命周期
2、設置Activity的android:configChanges="orientation"時,不會重走生命周期.
案例:test_configuration3如何將一個Activity設置成窗口的樣式。
在AndroidManifest.xml中定義Activity的地加方一句話android:theme="@android:style/Theme.Dialog"常見面試問題如果后臺的Activity由于某原因被系統(tǒng)回收了,如何在被系統(tǒng)回收之前保存當前狀態(tài)
onSaveInstanceState()
當你的程序中某一個ActivityA在運行時,主動或被動地運行另一個新的ActivityB,這個時候A會執(zhí)行onSaveInstanceState()。B完成以后又會來找A,這個時候就有兩種情況:一是A被回收,二是A沒有被回收,被回收的A就要重新調用onCreate()方法,不同于直接啟動的是這回onCreate()里是帶上了參數(shù)savedInstanceState;而沒被收回的就直接執(zhí)行onResume(),跳過onCreate()了。Handler消息傳遞機制Android平臺不允許Activity新啟動的線程訪問該Activity里的界面組件,會導致新啟動的線程無法動態(tài)改變界面組件的屬性值。這時就要采用Handler的消息傳遞機制來實現(xiàn)了.Handler的作用:1.在新啟動的線程中發(fā)送消息2.在主線程中獲取,處理消息.
開發(fā)者只要重寫Handler類中處理消息的方法,當新啟動的線程發(fā)送消息(調用handler對象的sendMessage()方法)時,Handler類中處理消息的方法會被自動回調.Handler類的常用方法:voidhandleMessage(Messagemsg);finalbooleanhasMessage(intwhat):finalbooleanhasMessages(intwhat,Objectobject):MessageobtainMessage():sendEmptyMessage(intwhat):finalbooleansendEmptyMessageDelayed(intwhat,longdelayMillis):finalbooleansendMessage(Messagemsg):Handler案例案例要求:通過一個線程來周期性地修改ImageView所顯示的圖片.參考源代碼:test_handler1finalImageViewimageview=(ImageView)this.findViewById(R.id.imageview);finalHandlerhandler=newHandler(){
publicvoidhandleMessage(Messagemsg){ if(msg.what==1){ imageview.setImageResource(imageids[currentid++]); if(currentid>=4){ currentid=0; } } } };newTimer().schedule(newTimerTask(){ publicvoidrun(){
Messagem=newMessage(); m.what=1; handler.sendMessage(m); }
},0,800);1Activity2Intent與IntentFilter4Service3ContentProvider課程目錄4BroadcastReceiver5Intent簡介問題:假如甲Activity要啟動另一個Activity,為何不直接使用一個形如startActivity(ClassactivityClass)的方法,這樣比較直接
實際上android使用Intent來封裝程序的調用意圖,不管程序想啟動一個Activity,Service,還是broadcastReceiver,android使用統(tǒng)一的Intent對象來封裝這種”意圖”,提供了一致的編程模型.
另外采用意圖也實現(xiàn)解耦.使用Intent啟動系統(tǒng)組件類型啟動方法ActivitystartActivity(Intent)startActivityForResult(Intent,int)serviceComponentNamestartService(Intent)BooleanbindService(Intent,ServiceConnection,int)broadcastreceiversendBroadcast(Intent)sendBroadcast(Intent,String)sendOrderedBroadcast(Intent,String,BraodcastREceiver,Handler,int,String,Bundle)sendStickyBroadcast(Intent)sendStickyOrderedBroadcast(Intent,BroadcastReceiver,Handler,int,String,Bundle);IntentIntent可以看做是Activity之間的橋梁
Action:ACTION_VIEW,ACTION_EDIT,ACTION_MAIN Data:封裝的數(shù)據,以Uri格式表示 Category:標志動作執(zhí)行的分類,例如CATEGORY_LAUNCHER Type:MIME Component:標明Intent指向的組件class Extras:用于在Intent中攜帶一些數(shù)據信息
Intent的成員-ComponentNameIntent中的Component屬性需要接受一個ComponentName對象,該對象的構造方法如下:ComponentName(Stringpkg,Stringcls):ComponentName(Contextpkg,Stringcls):ComponentName(Contextpkg,Class<>cls):ComponentName是處理此Intent的組件的名字,例如 com.chinasofti.etc.HelloActivity。 ComponentName是可選的,如果被設定,那么系統(tǒng)將直接將其
值作為處理Intent的組件。
可以通過Intent.setClass(),Intent.setComponent()等方法設置 ComponentName。
如果沒有設置ComponentName,那么系統(tǒng)根據Intent_Filter的定義去匹配處理Intent組件onConfigurationChanged響應系統(tǒng)設置更改地么那么案例1-示范Component1.事件綁定open.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){ComponentNamecn=newComponentName(MainActivity.this,SecondActivity.class);Intentintent=newIntent();intent.setComponent(cn);//為Intent設置ComponentName屬性startActivity(intent);}});配置<activityandroid:name=".SecondActivity"android:label="第二個窗口"/>3.第二個窗口
TextViewresult=(TextView)this.findViewById(R.id.result);ComponentNamecn=this.getIntent().getComponent();result.setText("包名:"+cn.getPackageName()+"\n類名:"+cn.getClassName());Intent之ActionAction本質上就是一個字符串常量,代表intent要完成的一個抽象”動作”.這個動作具體由哪個組件(Activity或是BoardcastReceiver)來完成,action并不管.如Android提供的標準動作:
Intent.ACCTION_VIEW,它只表示一個抽象的查看操作,但具體看什么,啟動哪個Activity來看,它并不知道,而取決于Activity中的<intent-filter…/>配置,只要某個Activity配置中包含了該Action_view動作,則該Activity就可能啟動.Action案例1步驟一:打開新窗口代碼:open.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){ Intentintent=newIntent(); //注意:在這里并沒有設置一個具體的要打開的activity組件 //而只是一個字符串.
intent.setAction("com.icss.myaction");//一個Intent對象只能設置一個Action //在沒有設置Category類別的情況下,相當于設置了默認類別,//一個intent對象可以設置多個category //intent.addCategory(Intent.CATEGORY_DEFAULT); //因此在Intent-filter中,要設置對應的category startActivity(intent); }});Action案例1步驟二:新窗口的配置文件:
注意:在這里,intent-filter通??梢园缦略?0-N個<action…/>子元素0-N個<category…/>子元素0-N個<data…/>子元素<activityandroid:name=".SecondActivity"android:label="新窗口"><intent-filter><actionandroid:name="com.icss.myaction"/><categoryandroid:name="ent.category.DEFAULT"/></intent-filter></activity>Intent的成員-CategoryCategory的含義與Action類似,Category也是一段字符串常量不同的是一個Intent對象可以加多個CategoryCategory描述的信息可以幫助系統(tǒng)確定處理Intent的組件調用Intent.addCategory()可以在Intent中增加一個Category常量含義CATEGORY_HOME當設備啟動后,用戶看到的第一個Activity或者當用戶按下HOME鍵時顯示給用戶的Activity。CATEGORY_LAUNCHERActivity是一個task的初始Activity,并且此Activity會被顯示在啟動面板上。系統(tǒng)標準Action系統(tǒng)標準CategoriesIntent的成員-Data,TypeData的含義Data屬性用于向Action屬性提供操作的數(shù)據.Data屬性接受一個Uri對象,形式如下:content://com.android.contacts/contacts/1tel:123Data是以URI代表的數(shù)據和MIME代表的數(shù)據類型的集合Type屬性用于明確指定Data屬性的類型或MIME型.通常當Intent不指定Data屬性時Type屬性才會起作用.Intent的成員-Data,Type.一旦為Intent同時指定了Action,Data屬性,那么Android將可根據指定的數(shù)據類型來啟動特定的應用程序,并對指定數(shù)據執(zhí)行相應的操作.
下面是一些Action與Data屬性的組合.ACTION_VIEW:content://com.android.contacts/contacts/1:ACTION_EDIT:content://com.android.contacts/contacts/1ACTION_DIAL:content://com.android.contacts/contacts/1ACTION_VIEW:tel:123案例-Action,Data案例publicvoidonClick(Viewv){ Intentintent=newIntent(); Stringdata=""; Uriuri=Uri.parse(data); intent.setAction(Intent.ACTION_VIEW); intent.setData(uri); startActivity(intent);}Intent的成員-ExtrasExtras的含義Extras包含了鍵-值數(shù)據對,用于向目標組件傳遞數(shù)據。Intent中包含了一系列的putExtra()和getExtra()方法用于存儲和讀取相關的數(shù)據類型。//存儲一個nameintent.putExtra("name",peoples[position]);//讀取存入的nameStringname=intent.getStringExtra("name");Intent解析顯式解析,調用setComponent(Component)或setClass(Context,Class)設置Intent指定的運行類。Intentintent=newIntent(this,DetailActivity.class);intent.putExtra("name",peoples[position]);startActivity(intent);隱式解析,未直接標注組件,但是需要提供足夠的信息以便系統(tǒng)能夠確定運行哪個class。Intentintent=newIntent();intent.setAction(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_HOME);startActivity(intent);使用Intent調用系統(tǒng)組件瀏覽器調用Uriuri=Uri.parse("");Intentit=newIntent(Intent.ACTION_VIEW,uri);context.startActivity(it);電話功能調用Uriuri=Uri.parse("tel:2125551212");Intentit=newIntent(Intent.ACTION_CALL,uri);context.startActivity(it);演示Intent啟動Activity用Intent啟動Activity,并在Activity之間傳遞數(shù)據本節(jié)的例子代碼是demo\intent在同一個應用程序中往往會使用Intent對象來指定一個Activity,并通過startActivity或startActivityForResult方法啟動這個Activity。除此之外,通過Intent還可以調用其他應用程序中的Activity。在AndroidSDK中甚至還允許開發(fā)人員自定義ActivityAction。運行本節(jié)的例子,單擊【開始另一個Activity】按鈕,會顯示Brower,輸出的信息如下圖所示。用Intent啟動Activity,并在Activity之間傳遞數(shù)據演示調用其他應用程序中的Activity調用其他應用程序中的Activity本節(jié)的例子代碼是demo\invokeotherapp運行本節(jié)的例子,界面如下圖所示。1Activity2Intent4Service3ContentProvider課程目錄4BroadcastReceiver5ContentProviderAndroid平臺主要提供了文件,SharedPreference,數(shù)據庫和ContentProvider四種持久化存儲方案。ContentProvider是唯一一種能在應用程序之間共享數(shù)據的方案。Android上內置的ContentProvider。
音頻
視頻
聯(lián)系人
通話記錄ContentProvider數(shù)據的存儲方式ContentProvider不限制底層數(shù)據的存儲方式,子類可以通過擴展以下抽象方式實現(xiàn)自己的ContentProviderquery(Uri,String[],String,String[],String)insert(Uri,ContentValues)update(Uri,ContentValues,String,String[])delete(Uri,String,String[])getType(Uri)使用ContentResolver接口對ContentProvider進行數(shù)據操作ContentResolverresolver=getContentResolver創(chuàng)建一個ContentProvider選擇存儲數(shù)據的方案,通常使用SQLite數(shù)據庫來存儲數(shù)據擴展ContentProvider類,實現(xiàn)其中定義的抽象方法,實現(xiàn)數(shù)據訪問。在AndroidManifest.xml中聲明ContentProvider:<providerandroid:name="ContactContentProvider" android:authorities="com.A.mobile.contactcontentprovider"</provider> 使用ContentProvider獲取音頻數(shù)據使用ContentProvider獲取SD卡中音頻數(shù)據本節(jié)的例子代碼是demo\musicActivity在本例子中,由于需要掛載SD卡,所以需要首先創(chuàng)建一個SD卡,并向SD卡上傳輸一些MP3歌曲。向模擬器的SD卡中傳輸文件的方式如下:使用ContentProvider獲取音頻數(shù)據本例運行后的界面如下圖所示:1Activity2Intent4Service3ContentProvider課程目錄4BroadcastReceiver5Service介紹讓程序在后臺運行Service與線程常用的系統(tǒng)服務Service標題:ArialUnicodeMS,32,紅色目錄菜單(將要講解):
ArialUnicodeMS,28,加粗,深紅目錄菜單(未講解的):ArialUnicodeMS,24,黑ServiceService是一段在后臺長期運行的代碼,與用戶不直接交互。Service不是單獨的進程,一般來說,Service運行在所在應用程序的進程中。Service不是單獨的線程,因此如果在Service中處理耗時的工作,應該放到新線程中,避免堵塞主線程。子類需要繼承android.app.Service來實現(xiàn)自己的service。Service簡介Service是什么
Service是Android平臺重要的組件之一,運行于后臺,不直接與用戶交互。啟動后的Service具有較高的優(yōu)先級,系統(tǒng)一般會優(yōu)先保證Service的正常運行。只有當前臺的Activity的正常運行資源被Service占用時,系統(tǒng)才會暫停Service;一旦重新獲得空閑資源,系統(tǒng)會自動重啟之前被停掉的Service。為何要用Service Service為Android平臺上的應用提供了一種在后臺運行而不影響用戶操作的機制,例如媒體播放器在后臺播放音樂。Service還為Android應用提供了一種向其他應用暴露接口的能力。這也為應用間的交互提供了便利。Service開發(fā)步驟類似于Activity,分為兩步:定義一個類繼承自Service.在AndroidManifest.xml文件中配置該ServiceService中的方法:onCreate():onDestroy():AbstractIbinderonBind(Intentintent):該方法返回一個Ibind對象,應用程序可通過該對象與Service組件通信.BooleanonUnbind(Intentintent):當該Service上綁定的所有客戶端都斷開連接時將會回調該方法.VoidonStartCommand(Intentintent,intflags,intstartId):早期是onStart()方法,每次客戶端調用startService(Intent)方法啟動該Service時都會回調該方法.案例1-service的使用步驟步驟一:寫一個類繼承自Service
publicclassFirstServiceextendsService{ publicvoidonCreate(){ super.onCreate(); System.out.println("serviceoncreate()"); } publicvoidonStart(Intentintent,intstartId){ System.out.println("serviceonstart()"); super.onStart(intent,startId); }}步驟二:Service配置在項目清單文件<serviceandroid:name=".FirstService"> <intent-filter> <actionandroid:name="com.icss.myservice"/> </intent-filter></service>案例1-service的使用步驟在android系統(tǒng)中運行Service有如下兩種方式:1.通過Context的startService()方法:這樣啟動service,訪問者與service之間沒有關聯(lián),即使訪問者退出了,service仍然運行.2.通過Context的bindService()方法:這樣啟用service,訪問者與service綁定在了一起,訪問者一旦退出,service也就終止了.這樣就可以通信了.第一種方案測試:
finalIntentintent=newIntent();intent.setAction("com.icss.myservice");start.setOnClickListener(newView.OnClickListener(){ publicvoidonClick(Viewv){ startService(intent);}});stop.setOnClickListener(newView.OnClickListener(){ publicvoidonClick(Viewv){ stopService(intent); }});第一種方案分析Context.startService()當其他組件通過Context.startService()方法啟動Service時,系統(tǒng)會創(chuàng)建一個Service對象,并順序調用onCreate()方法和onStartCommand()方法。在調用Context.stopService()或者stopSelf()之前,Service一直處于運行的狀態(tài)。如果多次調用startService()方法,系統(tǒng)只會多次調用onStartCommand()方法,而不會重復調用onCreate()方法。無論調用了多少次startService(),只需要調用一次stopService()就可以停止Service。Service對象在銷毀之前,onDestroy()會被調用,因此與資源釋放相關的工作應該在此方法中完成。onCreate()onStart()onDestroy()案例1-service的使用步驟案例1-service的使用步驟第二種方案測試:如果service和訪問者之間需要進行方法調用或數(shù)據交換時,應該使用bindService()和unbindService()方法啟動,關閉服務.Context.bindService(Intentintent,ServiceConnectioncon,intflag)方法參數(shù)有:intent:指定要啟動的servicecon:一個ServiceConnection對象,用于監(jiān)聽訪問者與service之間的連接情況。當訪問者與Service之間連接成功地將回調該ServiceConnection對象的onServiceConnected(ComponentNamename,Ibinderservice)方法;
當訪問者與Service之間斷開連接時將回調該ServiceConnection對象的onServiceDisconnected(ComponentNamename)方法.flags:指定綁定時是否自動創(chuàng)建Service.
當開發(fā)Service類中,該Service類必須提供一個IBinderonBind(Intentintent)方法,在綁定本地Service的情況下,onBind(Intentintent)方法所返回的Ibinder對象將會傳給ServiceConnection對象里onServiceConnected(ComponentNamename,Ibinderservice)方法的service參數(shù),這樣訪問者就可以通過該Ibinder對象
與Service進行通信.
案例1-service的使用步驟第二種測試方案:publicclassBindServiceextendsService{ privateintcount; privatebooleanquit;//是否退出
privateMyBinderbinder=newMyBinder(); publicclassMyBinderextendsBinder{//用于交換數(shù)據的Binder對象 publicintgetCount(){ returncount; } } publicIBinderonBind(Intentintent){//注意當調用者使用時bindService時,回調此方法,它返回一個Binder對象 System.out.println("serviceonBind"); returnbinder; } publicvoidonCreate(){ super.onCreate(); System.out.println("serviceonCreate"); newThread(){ publicvoidrun(){ while(!quit){ try{ Thread.sleep(1000); }catch(InterruptedExceptione){ e.printStackTrace(); } count++; } } }.start(); } publicvoidonDestroy(){ this.quit=true; System.out.println("serviceonDestroy()"); super.onDestroy(); } publicbooleanonUnbind(Intentintent){ System.out.println("serviceonUnbind"); returnsuper.onUnbind(intent); }}
案例1-service的使用步驟第二種測試方案:主界面
定義一個對象ServiceConnection,當服務綁定后,則回調其中的onServiceConnectedBindService.MyBinderbinder;ServiceConnectioncon=newServiceConnection(){ @Override publicvoidonServiceConnected(ComponentNamename,IBinderservice){ System.out.println("serviceconnected"); binder=(BindService.MyBinder)service; } @Override publicvoidonServiceDisconnected(ComponentNamename){ System.out.println("servicedisconnected"); }};
在按鈕中調用bindService方法bindService(intent,con,Service.BIND_AUTO_CREATE);Service的生命周期系統(tǒng)服務跨進程(AIDL服務)Android系統(tǒng)中的進程之間不能共享內存,因此,需要提供一些機制在不同進程之間進行數(shù)據通信。Activity和Broadcast都可以跨進程通信,除此之外,還可以使用ContentProvider進行跨進程通信。現(xiàn)在我們已經了解了4個Android應用程序組件中的3個(Activity、Broadcast和ContentProvider)都可以進行跨進程訪問,另外一個Android應用程序組件Service同樣可以。這就是本節(jié)要介紹的AIDL服務??邕M程調用Service(AIDL服務)Android系統(tǒng)中,各應用程序都運行在自己的進程中,進程之間一般無法直接進行數(shù)據交換。以前,Corba可實現(xiàn)跨進程的調用;在java技術中,RMI也可實現(xiàn)跨進程調用;在Android中,可采用AIDL.AIDL實現(xiàn)原理:
在前面的綁定本地Service的案例中,本地Service將一個回調對象(Ibinder對象)通過onBind()方法返回給客戶端,因此AIDL遠程接口的實現(xiàn)類就是Ibinder的實現(xiàn)類.不過與綁定本地Service不同的是,本地Service是直接返回的Ibinder對象本身給客戶端的ServiceConnection的onServiceConnected方法的第二個參數(shù)。但遠程Service的onBind()方法只是將Ibinder對象的代理傳給客戶端的ServiceConnection的onServiceConnected方法的第二個參數(shù).跨進程調用Service(AIDL服務)-創(chuàng)建步驟創(chuàng)建AIDL接口文件實現(xiàn)AIDL接口,將接口暴露給客戶端客戶端訪問AIDLService案例:test_service5跨進程調用Service(AIDL服務)AIDL接口:android需要AIDL(androidinterfacedefinitionlanguage)來定義遠程接口.AIDL特點:注意文件名的后綴必須是.aidlADT工具會自動在包目錄上生成一個Icolor.java接口,該接口中包含一個Stub內部類,該內部類實現(xiàn)了Ibinder,Icolor兩個接口,這個Stub類將會作為遠程Service的回調類作為Service的onBind()方法的返回值.在Android開發(fā)中,遠程調用的接口需要定義在.aidl文件中。AIDL文件中只能聲明方法,可包含參數(shù)和返回值。AIDL支持的類型包括Java基本數(shù)據類型(char、int等)、String、CharSequence、List和Map。如果應用程序需要定義自己的數(shù)據類型,該類型必須實現(xiàn)Parcelable接口。publicinterfaceIColor{StringgetColor();}返回跨進程調用Service(AIDL服務)定義一個Service類,該Servicer的onBind()方法所返回的Ibinder對象應該是ADT所生成的Icolor.Stub的子類的實例.privateStringcolor; privateString[]colors=newString[]{"red","blue"}; privateColorBinderbinder; privateTimertimer=newTimer(); //繼承Stub,它實現(xiàn)了IColor接口,并實現(xiàn)了IBinder接口
publicclassColorBinderextendsStub{ publicStringgetColor()throwsRemoteException{ returncolor; } } publicvoidonCreate(){ super.onCreate(); binder=newColorBinder(); timer.schedule(newTimerTask(){ @Override publicvoidrun(){ intrand=(int)(Math.random()*2); color=colors[rand]; System.out.println(rand); }},0,800); } //在綁定的是本地service的情況下,該binder對象會直接傳給客戶端的ServiceConnection對象的onServiceConnected方法的第二個參數(shù)
//在綁定的是遠程service的情況下,只將該binder對象的代理傳給客戶端的ServiceConnection對象的onServiceConnected方法的第二個參數(shù). publicIBinderonBind(Intentintent){ returnbinder; } @Override publicvoidonDestroy(){ timer.cancel(); }跨進程調用Service(AIDL服務)接下來,在項目清單文件中進行配置.<serviceandroid:name=".AidlSerivce"><intent-filter><actionandroid:name="myservice"/></intent-filter></service>至此服務端已經完成,下面將布置項目到模擬器上.返回跨進程調用Service(AIDL服務)如前所述,AIDL接口定義了兩個進程之間的通信接口,因此客戶端也需要定義前面的AIDL接口.
客戶端開發(fā)步驟:1.將服務器端的AIDL文件復制到客戶端:
特別注意:AIDL文件的包也要一起復制過來,不然運行的時候會出現(xiàn)Binderinvocationtoanincorrectinterface異常2.創(chuàng)建ServiceConnection對象3.以ServiceConnection對象作為參數(shù),調用Context的bindService()方法綁定遠程Service即可.但這里ServiceConnection并不能直接獲得遠程Service的onBind()方法所返回的對象,它只是獲得了這個對象的代理,所以必須進行以下處理:colorService=Icolor.Stub.asInterface(service);
參見下面?zhèn)渥⒌拇a:Service與線程Service、進程與線程Android平臺多線程編程的一些基本概念Service、進程與線程Service是獨立的進程么 Service并不是一個獨立的進程。除非專門指定,默認情況下,Service對象本身是作為應用程序的一部分,在其進程空間內運行的。Service是線程么
同樣,Service也不是線程,所以Service并不是一種在主線程之外進行一些工作的方法。在默認情況下,Service恰恰運行在應用程序所在進程的主線程上,因此,直接在Service內運行耗時操作會直接導致主線程阻塞、應用程序無響應的現(xiàn)象。開發(fā)者如果想指定一個Service運行在某個特定的進程中,可在AndroidManifest.xml中對應的<service>標簽中添加android:process并指定,例如:<serviceandroid:name=".MusicService“android:process=“example.remote”/>。系統(tǒng)服務概述Android平臺提供了很多系統(tǒng)級的服務,以便應用程序能夠使用Android系統(tǒng)的基礎功能,如電話、窗口、通知、定位等通過Activity.getSystemService(Stringname)獲得系統(tǒng)服務:name:唯一的系統(tǒng)服務ID(在android.content.Context中定義)返回系統(tǒng)服務對象(通常定義為xxxManager)聲明使用系統(tǒng)服務所需的權限<uses-permission>標簽獲得系統(tǒng)服務系統(tǒng)服務實際上可以看作是一個對象,通過Activity類的getSystemService方法可以獲得指定的對象(系統(tǒng)服務)。getSystemService方法只有一個String類型的參數(shù),表示系統(tǒng)服務的ID,這個ID在整個Android系統(tǒng)中是唯一的。例如,audio表示音頻服務,window表示窗口服務,notification表示通知服務。案例1-獲取網絡和SIM卡信息通過TelephonyManager提供的系列方法即可獲取手機網絡,SIM卡的相關信息。案例:test_service_telephonyManager常用的系統(tǒng)服務簡介—TelephonyServiceTelephonyService能夠為應用提供電話相關的功能和信息,例如電話的狀態(tài),或者一些相關的運營商信息等。如果應用希望在電話狀態(tài)發(fā)生變化時收到通知,也可通過注冊PhoneStateListener,并按需實現(xiàn)其中的一些方法。//獲取TelephonyService的對象TelephonyManagertm=(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);//創(chuàng)建PhoneStateListener對象并按需實現(xiàn)其中定義的方法PhoneStateListenerphoneStateListener=newPhoneStateListener(){ …};//監(jiān)聽電話狀態(tài)tm.listen(phoneStateListener,PhoneStateListener.LISTEN_CALL_STATE);//取消監(jiān)聽tm.listen(phoneStateListener,PhoneStateListener.LISTEN_NONE);案例2-監(jiān)聽手機來電將來電信息記錄到一個手機文件中.開發(fā)步驟:創(chuàng)建一人PhoneStateListener,它是一個通話狀態(tài)監(jiān)聽器,當手機來電時,程序會將來電號碼記錄到文件中去.
案例:test_service_telephonyManager2常用的系統(tǒng)服務簡介——SMSServiceSmsManager是Android提供了系統(tǒng)sendXXXMessage()方法用于發(fā)送短信,但最常用的是sendTextMessage()方法發(fā)送.//創(chuàng)建PendingIntent,設置執(zhí)行動作Intentintent=newIntent(this,MyActivity.class);PendingIntentpendingActivityIntent=PendingIntent.getActivity(this,0,intent,0);//獲取AlarmService的對象AlarmManageram=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);//設置定時器,時間到達后AlarmService會發(fā)出Intentam.setRepeating(AlarmManager.RTC,0,5000,pendingActivityIntent);//取消定時器alarmManager.cancel(pendingActivityIntent);案例1-發(fā)送短信PendingIntent是對Intent的包裝,一般通過調用PendingIntent的getActivity(),getService(),getBroadcastReceiver()靜態(tài)方法來獲得PendingIntent對象。與Intent不同的是:PendingIntent通常會傳給其他應用組件。參考代碼:test_smsmanager步驟:1.權限<uses-permissionandroid:name="android.permission.SEND_SMS"/>2.代碼:
finalSmsManagersm=SmsManager.getDefault();
//創(chuàng)建一個PendingIntentPendingIntentpi=PendingIntent.getActivity(MainActivity.this,0,newIntent(),0);//發(fā)送短信sm.sendTextMessage(tel.getText().toString(),null,content.getText().toString(),pi,null);案例2-短信群發(fā)參考代碼:test_smsmanager2常用的系統(tǒng)服務簡介——AudioManager調用getSystemService()方法來獲取系統(tǒng)的音頻管理器AudioManager.AudioManager常用方法:adjustStreamVolume(intstreamType,intdirection,intflags):調整手機指定類型的聲音.streamType聲音類型包括:STREAM_ALARM:手機鬧鈴STREAM_DTMF:DTMF音調的聲音STREAM_MUSIC:STREAM_NOTIFICATION:STREAM_RING:STREAM_SYSTEM:手機系統(tǒng)的聲音STREAM_VOICE_CALL:語言電話的聲音第二個參數(shù)表示對聲音增大/減少,第三個參數(shù)是調整聲音時的標志.常用的系統(tǒng)服務簡介——AudioManagerAudioManager常用方法:setMicrophoneMute(booleanon):是否靜音setMode(intmode):聲音模式,NORMAL,RINGTONE,IN_CALLsetRingerMode(intringerMode):電話鈴聲模式RINGER_MODE_NORMALRINGER_MODE_SILENTRINGER_MODE_VIBRATE:setSpeakerphoneOn(booleanon):是否開擴音器setStreamMute(intstreamType,booleanstate):
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2022年大學輕工紡織食品專業(yè)大學物理下冊開學考試試題C卷-附解析
- 石河子大學《云計算概論》2023-2024學年期末試卷
- 大學生舉辦母親節(jié)策劃書集合10篇
- 學校配套設施施工組織設計
- 石河子大學《體操》2021-2022學年第一學期期末試卷
- 石河子大學《農村社會學》2022-2023學年第一學期期末試卷
- 石河子大學《畜產品加工工藝學》2022-2023學年第一學期期末試卷
- 沈陽理工大學《模擬電子技術基礎》2021-2022學年期末試卷
- 沈陽理工大學《機械制造基礎》2023-2024學年第一學期期末試卷
- 收費站收費班安全培訓
- 孩子分為四種:認知型、模仿型、逆思型、開放型
- 小班故事《快樂的輪胎》課件
- (2024年)反壟斷法及反不正當競爭法課件
- 九年級英語《Unit 13 Were trying to save the earth!》教學設計
- 《風電場項目經濟評價規(guī)范》(NB-T 31085-2016)
- 最簡單模具合同
- 工業(yè)物聯(lián)網理論知識試題
- 激光器技術發(fā)展與應用前景
- 中學物理校本課程
- 居士念佛團規(guī)章制度
- 3D打印技術與應用
評論
0/150
提交評論