引言: 畢業(yè)之后,我開始從事IT行業(yè),從一個(gè)什么都不懂的小子,變成現(xiàn)在技術(shù)算中等的IT人員。Android 工程師這個(gè)職位我已做了近5年之久,針對網(wǎng)上的一些面試題進(jìn)行收集一下,面試其實(shí)就是相互了解的過程,直到現(xiàn)在,我才發(fā)現(xiàn)其實(shí)公司招聘時(shí)給出的技術(shù)面試題目網(wǎng)上都可以找到答案,但是答題不是唯一的,只是為了確定一個(gè)人的態(tài)度問題。看過與沒看是兩回事,看過至少還有一點(diǎn)點(diǎn)印象,面試最好的方法便是出個(gè)題目,直接上機(jī)寫代碼,是不是真材實(shí)料看代碼便知曉。也有人會說,現(xiàn)在都是開源時(shí)代,基本上所有的代碼都是可以找到的,那這樣寫還有啥意義?錯(cuò),代碼可以體現(xiàn)一個(gè)人做事的態(tài)度,也是我們程序員接觸最多的,看到代碼我們可以體會當(dāng)時(shí)寫代碼人的思維與心情,出了Bug時(shí)解決問題的方法。好了,其他的不多說,下面的題目很多來自網(wǎng)絡(luò)。
1. 下列哪些語句關(guān)于內(nèi)存回收的說明是正確的? (b )
A、 程序員必須創(chuàng)建一個(gè)線程來釋放內(nèi)存?
B、 內(nèi)存回收程序負(fù)責(zé)釋放無用內(nèi)存
?C、 內(nèi)存回收程序允許程序員直接釋放內(nèi)存?
D、 內(nèi)存回收程序可以在指定的時(shí)間釋放內(nèi)存對象
2. 下面異常是屬于 Runtime Exception 的是(abcd)(多選)?
A、ArithmeticException?
B、IllegalArgumentException?
C、NullPointerException?
D、BufferUnderflowException
3. Math.round(11.5)等于多少(). Math.round(-11.5)等于多少(c). c?
A、11 ,-11? B、11 ,-12? C、12 ,-11? D、12 ,-12
4. 下列程序段的輸出結(jié)果是:(b )
?void complicatedexpression_r(){?
int x=20, y=30;?
boolean b;?
b=x>50&&y>60||x>50&&y<-60||x<-50&&y>60||x<-50&&y<-60;?
System.out.println(b);
?}
?A、true B、false C、1? ?D、0
5. activity 對一些資源以及狀態(tài)的操作保存,最好是保存在生命周期的哪個(gè)函數(shù)中進(jìn)行(d)?
A、onPause()? B、onCreate()? C、 onResume()? D、onStart()
6. Intent 傳遞數(shù)據(jù)時(shí),下列的數(shù)據(jù)類型哪些可以被傳遞(abcd)(多選)?
A、Serializable B、charsequence C、Parcelable D、Bundle
7. android 中下列屬于 Intent 的作用的是(c)?
A、實(shí)現(xiàn)應(yīng)用程序間的數(shù)據(jù)共享
?B、是一段長的生命周期,沒有用戶界面的程序,可以保持應(yīng)用在后臺運(yùn)行,而不會因?yàn)榍袚Q頁面而消失
?C、可以實(shí)現(xiàn)界面間的切換,可以包含動(dòng)作和動(dòng)作數(shù)據(jù),連接四大組件的紐帶?
D、處理一個(gè)應(yīng)用程序整體性的工作
8. 下列屬于 SAX 解析 xml 文件的優(yōu)點(diǎn)的是(b)?
A、將整個(gè)文檔樹在內(nèi)存中,便于操作,支持刪除,修改,重新排列等多種功能?
B、不用事先調(diào)入整個(gè)文檔,占用資源少
?C、整個(gè)文檔調(diào)入內(nèi)存,浪費(fèi)時(shí)間和空間?
D、不是長久駐留在內(nèi)存,數(shù)據(jù)不是持久的,事件過后,若沒有保存數(shù)據(jù),數(shù)據(jù)就會 消失
9. 下面的對自定 style 的方式正確的是(a)?

10. 在 android 中使用 Menu 時(shí)可能需要重寫的方法有(ac)。(多選)?
A、onCreateOptionsMenu()??
B、onCreateMenu()??
C、onOptionsItemSelected()?
D、onItemSelected()
11. 在 SQL Server Management Studio 中運(yùn)行下列 T-SQL 語句,其輸出值(c)。
SELECT @@IDENTITY?
A、 可能為 0.1? ? B、 可能為 3? ? C、 不可能為-100? ?D、 肯定為 0
12. 在 SQL Server 2005 中運(yùn)行如下 T-SQL 語句,假定 SALES 表中有多行數(shù)據(jù),執(zhí)行查詢之 后的結(jié)果是(d)。
BEGIN TRANSACTION AUpdate SALES Set qty=30?
WHERE qty<30BEGIN TRANSACTION BUpdate SALES Set qty=40?
WHERE qty<40Update SALES Set qty=50
?WHERE qty<50Update SALES Set qty=60?
WHERE qty<60COMMIT TRANSACTION BCOMMIT TRANSACTION A
A、SALES 表中 qty 列最小值大于等于 30
B、SALES 表中 qty 列最小值大于等于 40
C、SALES 表中 qty 列的數(shù)據(jù)全部為 50
D、SALES 表中 qty 列最小值大于等于 60
13. 在 android 中使用 SQLiteOpenHelper 這個(gè)輔助類時(shí),可以生成一個(gè)數(shù)據(jù)庫,并可以對數(shù)據(jù)庫版本進(jìn)行管理的方法可以是(ab)?
A、getWriteableDatabase()
B、getReadableDatabase()?
C、getDatabase()
D、getAbleDatabase()
14. android 關(guān)于 service 生命周期的 onCreate()和 onStart()說法正確的是(ad)(多選題)?
A、當(dāng)?shù)谝淮螁?dòng)的時(shí)候先后調(diào)用 onCreate()和 onStart()方法?
B、當(dāng)?shù)谝淮螁?dòng)的時(shí)候只會調(diào)用 onCreate()方法?
C、如果 service 已經(jīng)啟動(dòng),將先后調(diào)用 onCreate()和 onStart()方法
D、如果 service 已經(jīng)啟動(dòng),只會執(zhí)行 onStart()方法,不在執(zhí)行 onCreate()方法
15. 下面是屬于 GLSurFaceView 特性的是(abc)(多選)
A、管理一個(gè) surface,這個(gè) surface 就是一塊特殊的內(nèi)存,能直接排版到 android 的視圖 view 上。
B、管理一個(gè) EGL display,它能讓 opengl 把內(nèi)容渲染到上述的 surface 上。
C、讓渲染器在獨(dú)立的線程里運(yùn)作,和 UI 線程分離。
D、可以直接從內(nèi)存或者 DMA 等硬件接口取得圖像數(shù)據(jù)
16. 下面在 AndroidManifest.xml 文件中注冊 BroadcastReceiver 方式正確的(a) A、
A、<receiver android:name="NewBroad">
<intent-filter>
? <action android:name="android.provider.action.NewBroad"/>
</intent-filter>
</receiver>
B. <receiver android:name="NewBroad">
?<intent-filter>
android:name="android.provider.action.NewBroad"/>
</intent-filter>
</receiver>

17. 關(guān)于 ContenValues 類說法正確的是(a)?
A、他和 Hashtable 比較類似,也是負(fù)責(zé)存儲一些名值對,但是他存儲的名值對當(dāng)中的 名是 String 類型,而值都是基本類型?
B、他和 Hashtable 比較類似,也是負(fù)責(zé)存儲一些名值對,但是他存儲的名值對當(dāng)中的 名是任意類型,而值都是基本類型?
C、他和 Hashtable 比較類似,也是負(fù)責(zé)存儲一些名值對,但是他存儲的名值對當(dāng)中的 名,可以為空,而值都是 String 類型
?D、他和 Hashtable 比較類似,也是負(fù)責(zé)存儲一些名值對,但是他存儲的名值對當(dāng)中 的名是 String 類型,而值也是 String 類型
18. 我們都知道 Hanlder 是線程與 Activity 通信的橋梁,如果線程處理不當(dāng),你的機(jī)器就會變得越慢,那么線程銷毀的方法是(a)?
A、onDestroy() B、onClear() C、onFinish() D、onStop()
19. 下面退出 Activity 錯(cuò)誤的方法是(c)?
A、finish() B、拋異常強(qiáng)制退出 C、System.exit() D、onStop()
20. 下面屬于 android 的動(dòng)畫分類的有(ab)(多項(xiàng))
?A、Tween B、Frame C、Draw D、Animation
21. 下面關(guān)于 Android dvm 的進(jìn)程和 Linux 的進(jìn)程,應(yīng)用程序的進(jìn)程說法正確的是(d)?
A、DVM 指 dalivk 的虛擬機(jī).每一個(gè) Android 應(yīng)用程序都在它自己的進(jìn)程中運(yùn)行,不一定擁有一個(gè)獨(dú)立 的 Dalvik 虛擬機(jī)實(shí)例.而每一個(gè) DVM 都是在 Linux 中的一個(gè)進(jìn)程,所以說可以認(rèn)為是同一個(gè)概念.
?B、DVM 指 dalivk 的虛擬機(jī).每一個(gè) Android 應(yīng)用程序都在它自己的進(jìn)程中運(yùn)行,不一定擁有一個(gè)獨(dú)立的 Dalvik 虛擬機(jī)實(shí)例.而每一個(gè) DVM 不一定都是在 Linux 中的一個(gè)進(jìn)程,所以說不是一個(gè)概念.
?C、DVM 指 dalivk 的虛擬機(jī).每一個(gè) Android 應(yīng)用程序都在它自己的進(jìn)程中運(yùn)行,都擁有一個(gè)獨(dú)立的 Dalvik 虛擬機(jī)實(shí)例.而每一個(gè) DVM 不一定都是在 Linux 中的一個(gè)進(jìn)程,所以說不是一個(gè)概念.?
D、DVM 指 dalivk 的虛擬機(jī).每一個(gè) Android 應(yīng)用程序都在它自己的進(jìn)程中運(yùn)行,都擁有一個(gè)獨(dú)立的 Dalvik 虛擬機(jī)實(shí)例.而每一個(gè) DVM 都是在 Linux 中的一個(gè)進(jìn)程,所以說可以認(rèn)為是同一個(gè)概念.
22. Android 項(xiàng)目工程下面的 assets 目錄的作用是什么 (b)
A、放置應(yīng)用到的圖片資源。
B、主要放置多媒體等數(shù)據(jù)文件
C、放置字符串,顏色,數(shù)組等常量數(shù)據(jù)
D、放置一些與 UI 相應(yīng)的布局文件,都是 xml 文件
23. 關(guān)于 res/raw 目錄說法正確的是(a)
A、 這里的文件是原封不動(dòng)的存儲到設(shè)備上不會轉(zhuǎn)換為二進(jìn)制的格式B、 這里的文件是原封不動(dòng)的存儲到設(shè)備上會轉(zhuǎn)換為二進(jìn)制的格式
C、 這里的文件最終以二進(jìn)制的格式存儲到指定的包中
D、 這里的文件最終不會以二進(jìn)制的格式存儲到指定的包中
24. 下列對 android NDK 的理解正確的是(abcd )
A、 NDK 是一系列工具的集合
B、 NDK 提供了一份穩(wěn)定、功能有限的 API 頭文件聲明。
C、 使 “Java+C” 的開發(fā)方式終于轉(zhuǎn)正,成為官方支持的開發(fā)方式
D、 NDK 將是 Android 平臺支持 C 開發(fā)的開端
二.填空題
25. android 中常用的四個(gè)布局是 framlayout,linenarlayout,relativelayout 和 tablelayout。
26. android 的四大組件是 activiey,service,broadcast 和 contentprovide。
27. java.io 包中的 objectinputstream 和 objectoutputstream 類主要用于對對象(Object)的讀寫。
28. android 中 service 的實(shí)現(xiàn)方法(兩種)是:startservice 和 bindservice。
29. activity 一般會重載 7 個(gè)方法用來維護(hù)其生命周期,除了onCreate(),onStart(),onDestory() 外還有 onrestart,onresume,onpause,onstop。
30. android 的數(shù)據(jù)存儲的方式 sharedpreference,文件,SQlite,contentprovider,網(wǎng)絡(luò)。
31. 當(dāng)啟動(dòng)一個(gè)Activity并且新的Activity執(zhí)行完后需要返回到啟動(dòng)它的Activity來執(zhí)行 的回調(diào)函數(shù)是 startActivityResult()。
32. 請使用命令行的方式創(chuàng)建一個(gè)名字為 myAvd,sdk 版本為 2.2,sd 卡是在 d 盤的根目錄下,名字為 scard.img, 并指定屏幕大小 HVGA.____________________________________。
33. 程序運(yùn)行的結(jié)果是:_____good and gbc__(錯(cuò)過一次了)________。
?public class Example{?
String str=new String("good");?
char[]ch={'a','b','c'};?
public static void main(String args[]){?
Example ex=new Example();?
ex.change(ex.str,ex.ch);?
System.out.print(ex.str+" and "); Sytem.out.print(ex.ch);
?}
? public void change(String str,char ch[])
{ str="test ok"; ch[0]='g';?
}
}
34. 在 android 中,請簡述 jni 的調(diào)用過程。(8 分)(考過一次了)
1)安裝和下載 Cygwin,下載 Android NDK?
2)在 ndk 項(xiàng)目中 JNI 接口的設(shè)計(jì)?
3)使用 C/C++實(shí)現(xiàn)本地方法?
4)JNI 生成動(dòng)態(tài)鏈接庫.so 文件?
5)將動(dòng)態(tài)鏈接庫復(fù)制到 java 工程,在 java 工程中調(diào)用,運(yùn)行 java 工程即可
35. 簡述 Android 應(yīng)用程序結(jié)構(gòu)是哪些?(7 分)
Android 應(yīng)用程序結(jié)構(gòu)是: Linux Kernel(Linux 內(nèi)核)、Libraries(系統(tǒng)運(yùn)行庫或者是 c/c++核心庫)、Application Framework(開發(fā)框架包)、Applications (核心應(yīng)用程序)
第一層:Linux 操作系統(tǒng)和驅(qū)動(dòng)(Linux kernel)
第二層:各種庫和 Android 運(yùn)行環(huán)境(Android Runtime)
第三層:java 框架(有 activity manager,contentprovide 等)
第四層:應(yīng)用程序
36. 請繼承 SQLiteOpenHelper 實(shí)現(xiàn):(10 分)?
1).創(chuàng)建一個(gè)版本為 1 的“diaryOpenHelper.db”的數(shù)據(jù)庫,
?2).同時(shí)創(chuàng)建一個(gè) “diary” 表(包含一個(gè)_id 主鍵并自增長,topic 字符型 100 長度, content 字符型 1000 長度)?
3).在數(shù)據(jù)庫版本變化時(shí)請刪除 diary 表,并重新創(chuàng)建出 diary 表。
public class DBHelper extends SQLiteOpenHelper {
public final static String DATABASENAME = "diaryOpenHelper.db";
public final static int DATABASEVERSION = 1;//創(chuàng)建數(shù)據(jù)庫
public DBHelper(Context context,String name,CursorFactory factory,int version){
super(context, name, factory, version);
}
//創(chuàng)建表等機(jī)構(gòu)性文件
public void onCreate(SQLiteDatabase db){
String sql ="create table diary"+"("+"_id integer primary key autoincrement,"+"topic varchar(100),"+"content varchar(1000)"+")";db.execSQL(sql);
}
//若數(shù)據(jù)庫版本有更新,則調(diào)用此方法
public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){
String sql = "drop table if exists diary";
db.execSQL(sql);
this.onCreate(db);
}
}
37. 頁面上現(xiàn)有 ProgressBar 控件 progressBar,請用書寫線程以 10 秒的的時(shí)間完成其進(jìn)度顯示工作。(10 分)
答案:
public class ProgressBarStu extends Activity {
private ProgressBar progressBar = null;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.progressbar);//從這到下是關(guān)鍵
progressBar = (ProgressBar)findViewById(R.id.progressBar);
Thread thread = new Thread(new Runnable()?
{@Overridepublic void run() {
int progressBarMax = progressBar.getMax();try {while(progressBarMax!=progressBar.getProgress()){
int stepProgress = progressBarMax/10;
int currentprogress = progressBar.getProgress();
progressBar.setProgress(currentprogress+stepProgress);
Thread.sleep(1000);
}
} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();
}
}
}
);
thread.start();}}
38. 請描述下 Activity 的生命周期。 必調(diào)用的三個(gè)方法:onCreate() --> onStart() --> onResume(),用 AAA 表示
(1)父 Activity 啟動(dòng)子 Activity,子 Actvity 退出,父 Activity 調(diào)用順序如下AAA --> onFreeze() --> onPause() --> onStop() --> onRestart() --> onStart(),onResume() …
(2)用戶點(diǎn)擊 Home,Actvity 調(diào)用順序如下AAA --> onFreeze() --> onPause() --> onStop() -- Maybe --> onDestroy() – Maybe
(3)調(diào)用 finish(), Activity 調(diào)用順序如下AAA --> onPause() --> onStop() --> onDestroy()(4)在 Activity 上顯示 dialog, Activity 調(diào)用順序如下AAA
(5)在父 Activity 上顯示透明的或非全屏的 activity,Activity 調(diào)用順序如下AAA --> onFreeze() --> onPause()
(6)設(shè)備進(jìn)入睡眠狀態(tài),Activity 調(diào)用順序如下AAA --> onFreeze() --> onPause()
39. 如果后臺的 Activity 由于某原因被系統(tǒng)回收了,如何在被系統(tǒng)回收之前保存當(dāng)前狀態(tài)?
答:onSaveInstanceState()當(dāng)你的程序中某一個(gè) Activity A 在運(yùn)行時(shí),主動(dòng)或被動(dòng)地運(yùn)行另一個(gè)新的 Activity B,這個(gè)時(shí)候 A 會執(zhí)行 onSaveInstanceState()。B 完成以后又會來找 A,這個(gè)時(shí)候就有兩種情況:一是 A 被回收,二是 A 沒有被回收,被回收的 A 就要重新調(diào)用 onCreate()方法,不同于直接啟動(dòng)的是這回 onCreate()里是帶上了參數(shù) savedInstanceState;而沒被收回的就直接執(zhí)行onResume(),跳過 onCreate()了。
40. 如何將一個(gè) Activity 設(shè)置成窗口的樣式。
答: 在 AndroidManifest.xml 中定義 Activity 的地方一句話android:theme="@android:style/Theme.Dialog"或android:theme="@android:style/Theme.Translucent"就變成半透明的
41. 如何退出 Activity?如何安全退出已調(diào)用多個(gè) Activity 的 Application?
答:對于單一 Activity 的應(yīng)用來說,退出很簡單,直接 finish()即可。當(dāng)然,也可以用 killProcess()和 System.exit()這樣的方法。但是,對于多 Activity 的應(yīng)用來說,在打開多個(gè) Activity 后,如果想在最后打開的 Activity直接退出,上邊的方法都是沒有用的,因?yàn)樯线叺姆椒ǘ际墙Y(jié)束一個(gè) Activity 而已。當(dāng)然,網(wǎng)上也有人說可以。就好像有人問,在應(yīng)用里如何捕獲 Home 鍵,有人就會說用 keyCode 比較 KEYCODE_HOME即可,而事實(shí)上如果不修改 framework,根本不可能做到這一點(diǎn)一樣。所以,最好還是自己親自試一下。那么,有沒有辦法直接退出整個(gè)應(yīng)用呢?
在 2.1 之前,可以使用 ActivityManager 的 restartPackage 方法。它可以直接結(jié)束整個(gè)應(yīng)用。在使用時(shí)需要權(quán)限 android.permission.RESTART_PACKAGES。注意不要被它的名字迷惑。
可是,在 2.2,這個(gè)方法失效了。在 2.2 添加了一個(gè)新的方法,killBackgroundProcesses(),需要權(quán)限android.permission.KILL_BACKGROUND_PROCESSES??上У氖?,它和 2.2 的 restartPackage 一樣,根本起不到應(yīng)有的效果。另外還有一個(gè)方法,就是系統(tǒng)自帶的應(yīng)用程序管理里,強(qiáng)制結(jié)束程序的方法,forceStopPackage()。它需要權(quán)限 android.permission.FORCE_STOP_PACKAGES。并且需要添加 android:sharedUserId="android.uid.system"屬性同樣可惜的是,該方法是非公開的,他只能運(yùn)行在系統(tǒng)進(jìn)程,第三方程序無法調(diào)用。因?yàn)樾枰?Android.mk 中添加 LOCAL_CERTIFICATE := platform。而 Android.mk 是用于在 Android 源碼下編譯程序用的。
從以上可以看出,在 2.2,沒有辦法直接結(jié)束一個(gè)應(yīng)用,而只能用自己的辦法間接辦到?,F(xiàn)提供幾個(gè)方法,供參考:
1、拋異常強(qiáng)制退出:該方法通過拋異常,使程序 Force Close。驗(yàn)證可以,但是,需要解決的問題是,如何使程序結(jié)束掉,而不彈出 Force Close 的窗口。
2、記錄打開的 Activity:每打開一個(gè) Activity,就記錄下來。在需要退出時(shí),關(guān)閉每一個(gè) Activity 即可。
3、發(fā)送特定廣播:在需要結(jié)束應(yīng)用時(shí),發(fā)送一個(gè)特定的廣播,每個(gè) Activity 收到廣播后,關(guān)閉即可。
4、遞歸退出在打開新的 Activity 時(shí)使用 startActivityForResult,然后自己加標(biāo)志,在 onActivityResult 中處理,遞歸關(guān)閉。除了第一個(gè),都是想辦法把每一個(gè) Activity 都結(jié)束掉,間接達(dá)到目的。但是這樣做同樣不完美。你會發(fā)現(xiàn),如果自己的應(yīng)用程序?qū)γ恳粋€(gè) Activity 都設(shè)置了 nosensor,在兩個(gè) Activity 結(jié)束的間隙,sensor 可能有效了。但至少,我們的目的達(dá)到了,而且沒有影響用戶使用。為了編程方便,最好定義一個(gè) Activity 基類,處理這些共通問題。
42. 請介紹下 Android 中常用的五種布局。
FrameLayout(框架布局),LinearLayout (線性布局),AbsoluteLayout(絕對布局),RelativeLayout(相對布局),TableLayout(表格布局)
43. 請介紹下 Android 的數(shù)據(jù)存儲方式。
一.SharedPreferences 方式
二.文件存儲方式
三.SQLite?數(shù)據(jù)庫方式
四.內(nèi)容提供器(Content provider)方式
五. 網(wǎng)絡(luò)存儲方式
44. 請介紹下 ContentProvider 是如何實(shí)現(xiàn)數(shù)據(jù)共享的。
創(chuàng)建一個(gè)屬于你自己的 Content provider 或者將你的數(shù)據(jù)添加到一個(gè)已經(jīng)存在的 Contentprovider 中,前提是有相同數(shù)據(jù)類型并且有寫入 Content provider 的權(quán)限。
45. 如何啟用 Service,如何停用 Service。
Android 中的 service 類似于 windows 中的 service,service 一般沒有用戶操作界面,它運(yùn)行于系統(tǒng)中不容易被用戶發(fā)覺,可以使用它開發(fā)如監(jiān)控之類的程序。
一、步驟第一步:繼承 Service 類public class SMSService extends Service { }
第二步:在 AndroidManifest.xml 文件中的節(jié)點(diǎn)里對服務(wù)進(jìn)行配置:
二。Context.startService()和 Context.bindService服務(wù)不能自己運(yùn)行,需要通過調(diào)用 Context.startService()或 Context.bindService()方法啟動(dòng)服務(wù)。
這兩個(gè)方法都可以啟動(dòng) Service,但是它們的使用場合有所不同。
1.使用 startService()方法啟用服務(wù),調(diào)用者與服務(wù)之間沒有關(guān)連,即使調(diào)用者退出了,服務(wù)仍然運(yùn)行。使用 bindService()方法啟用服務(wù),調(diào)用者與服務(wù)綁定在了一起,調(diào)用者一旦退出,服務(wù)也就終止。
2.采用 Context.startService()方法啟動(dòng)服務(wù),在服務(wù)未被創(chuàng)建時(shí),系統(tǒng)會先調(diào)用服務(wù)的onCreate()方法,接著調(diào)用 onStart()方法。如果調(diào)用 startService()方法前服務(wù)已經(jīng)被創(chuàng)建,多次調(diào)用 startService()方法并不會導(dǎo)致多次創(chuàng)建服務(wù),但會導(dǎo)致多次調(diào)用 onStart()方法。采用 startService()方法啟動(dòng)的服務(wù),只能調(diào)用 Context.stopService()方法結(jié)束服務(wù),服務(wù)結(jié)束時(shí)會調(diào)用onDestroy()方法。
3.采用 Context.bindService()方法啟動(dòng)服務(wù),在服務(wù)未被創(chuàng)建時(shí),系統(tǒng)會先調(diào)用服務(wù)的onCreate()方法,接著調(diào)用 onBind()方法。這個(gè)時(shí)候調(diào)用者和服務(wù)綁定在一起,調(diào)用者退出了,系統(tǒng)就會先調(diào)用服務(wù)的 onUnbind()方法,。接著調(diào)用 onDestroy()方法。如果調(diào)用 bindService()方法前服務(wù)已經(jīng)被綁定,多次調(diào)用bindService()方法并不會導(dǎo)致多次創(chuàng)建服務(wù)及綁定(也就是說 onCreate()和 onBind()方法并不會被多次調(diào)用)。如果調(diào)用者希望與正在綁定的服務(wù)解除綁定,可以調(diào)用 unbindService()方法,調(diào)用該方法也會導(dǎo)致系統(tǒng)調(diào)用服務(wù)的onUnbind()-->onDestroy()方法。
三。Service 的生命周期
1.Service 常用生命周期回調(diào)方法如下:onCreate() 該方法在服務(wù)被創(chuàng)建時(shí)調(diào)用,該方法只會被調(diào)用一次,無論調(diào)用多少次startService()或 bindService()方法,服務(wù)也只被創(chuàng)建一次。 onDestroy()該方法在服務(wù)被終止時(shí)調(diào)用。
2. Context.startService()啟動(dòng) Service 有關(guān)的生命周期方法onStart() 只有采用 Context.startService()方法啟動(dòng)服務(wù)時(shí)才會回調(diào)該方法。該方法在服務(wù)開始運(yùn)行時(shí)被調(diào)用。多次調(diào)用 startService()方法盡管不會多次創(chuàng)建服務(wù),但 onStart() 方法會被多次調(diào)用。
3. Context.bindService()啟動(dòng) Service 有關(guān)的生命周期方法onBind()只有采用 Context.bindService()方法啟動(dòng)服務(wù)時(shí)才會回調(diào)該方法。該方法在調(diào)用者與服務(wù)綁定時(shí)被調(diào)用,當(dāng)調(diào)用者與服務(wù)已經(jīng)綁定,多次調(diào)用 Context.bindService()方法并不會導(dǎo)致該方法被多次調(diào)用。onUnbind()只有采用 Context.bindService()方法啟動(dòng)服務(wù)時(shí)才會回調(diào)該方法。該方法在調(diào)用者與服務(wù)解除綁定時(shí)被調(diào)用。備注:
1. 采用 startService()啟動(dòng)服務(wù) Intent intent = new Intent(DemoActivity.this, DemoService.class); startService(intent);
2.Context.bindService()啟動(dòng) Intent intent = new Intent(DemoActivity.this, DemoService.class); bindService(intent, conn, Context.BIND_AUTO_CREATE); //unbindService(conn);//解除綁定
46. 注冊廣播有幾種方式,這些方式有何優(yōu)缺點(diǎn)?請談?wù)?Android 引入廣播機(jī)制的用意。
?答:Android 廣播機(jī)制(兩種注冊方法)在 android 下,要想接受廣播信息,那么這個(gè)廣播接收器就得我們自己來實(shí)現(xiàn)了,我們可以繼承 BroadcastReceiver,就可以有一個(gè)廣播接受器了。有個(gè)接受器還不夠,我們還得重寫B(tài)roadcastReceiver 里面的 onReceiver 方法,當(dāng)來廣播的時(shí)候我們要干什么,這就要我們自己來實(shí)現(xiàn),不過我們可以搞一個(gè)信息防火墻。
第一種不是常駐型廣播,也就是說廣播跟隨程序的生命周期。
?2)第二種是常駐型,也就是說當(dāng)應(yīng)用程序關(guān)閉后,如果有信息廣播來,程序也會被系統(tǒng)調(diào)用自動(dòng)運(yùn)行。
47. 請解釋下在單線程模型中 Message、Handler、Message Queue、Looper 之間的關(guān)系。
答:Handler 簡介:一個(gè) Handler 允許你發(fā)送和處理 Message 和 Runable 對象,這些對象和一個(gè)線程的MessageQueue 相關(guān)聯(lián)。每一個(gè)線程實(shí)例和一個(gè)單獨(dú)的線程以及該線程的 MessageQueue 相關(guān)聯(lián)。當(dāng)你創(chuàng)建一個(gè)新的 Handler 時(shí),它就和創(chuàng)建它的線程綁定在一起了。這里,線程我們也可以理解為線程的 MessageQueue。從這一點(diǎn)上來看,Handler 把 Message 和 Runable 對象傳遞給 MessageQueue,而且在這些對象離開 MessageQueue 時(shí),Handler 負(fù)責(zé)執(zhí)行他們。
Handler 有兩個(gè)主要的用途:
(1)確定在將來的某個(gè)時(shí)間點(diǎn)執(zhí)行一個(gè)或者一些 Message 和Runnable 對象。
(2)在其他線程(不是 Handler 綁定線程)中排入一些要執(zhí)行的動(dòng)作。Scheduling Message,即(1),可以通過以下方法完成:post(Runnable):Runnable 在 handler 綁定的線程上執(zhí)行,也就是說不創(chuàng)建新線程。
postAtTime(Runnable,long):
postDelayed(Runnable,long):
sendEmptyMessage(int):
sendMessage(Message):
sendMessageAtTime(Message,long):
sendMessageDelayed(Message,long):
post 這個(gè)動(dòng)作讓你把 Runnable 對象排入 MessageQueue,MessageQueue 受到這些消息的時(shí)候執(zhí)行他們,當(dāng)然以一定的排序。sendMessage 這個(gè)動(dòng)作允許你把 Message 對象排成隊(duì)列,這些 Message 對象包含一些信息,Handler 的 hanlerMessage(Message)會處理這些 Message.當(dāng)然,handlerMessage(Message)必須由 Handler 的子類來重寫。這是編程人員需要作的事。當(dāng) posting 或者 sending 到一個(gè) Hanler 時(shí),你可以有三種行為:當(dāng) MessageQueue 準(zhǔn)備好就處理,定義一個(gè)延遲時(shí)間,定義一個(gè)精確的時(shí)間去處理。后兩者允許你實(shí)現(xiàn) timeout,tick,和基于時(shí)間的行為。當(dāng)你的應(yīng)用創(chuàng)建一個(gè)新的進(jìn)程時(shí),主線程(也就是 UI 線程)自帶一個(gè) MessageQueue,這個(gè)MessageQueue 管理頂層的應(yīng)用對象(像 activities,broadcast receivers 等)和主線程創(chuàng)建的窗體。你可以創(chuàng)建自己的線程,并通過一個(gè) Handler 和主線程進(jìn)行通信。這和之前一樣,通過post 和 sendmessage 來完成,差別在于在哪一個(gè)線程中執(zhí)行這么方法。在恰當(dāng)?shù)臅r(shí)候,給定的 Runnable 和 Message 將在 Handler 的 MessageQueue 中被 Scheduled。Message 簡介:Message 類就是定義了一個(gè)信息,這個(gè)信息中包含一個(gè)描述符和任意的數(shù)據(jù)對象,這個(gè)信息被用來傳遞給 Handler.Message 對象提供額外的兩個(gè) int 域和一個(gè) Object 域,這可以讓你在大多數(shù)情況下不用作分配的動(dòng)作。盡管 Message 的構(gòu)造函數(shù)是 public 的,但是獲取 Message 實(shí)例的最好方法是調(diào)用Message.obtain(),或者 Handler.obtainMessage()方法,這些方法會從回收對象池中獲取一個(gè)。
MessageQueue 簡介:這是一個(gè)包含 message 列表的底層類。Looper 負(fù)責(zé)分發(fā)這些 message。Messages 并不是直接加到一個(gè) MessageQueue 中,而是通過 MessageQueue.IdleHandler 關(guān)聯(lián)到 Looper。你可以通過 Looper.myQueue()從當(dāng)前線程中獲取 MessageQueue。Looper 簡介:Looper 類被用來執(zhí)行一個(gè)線程中的 message 循環(huán)。默認(rèn)情況,沒有一個(gè)消息循環(huán)關(guān)聯(lián)到線程。在線程中調(diào)用 prepare()創(chuàng)建一個(gè) Looper,然后用 loop()來處理 messages,直到循環(huán)終止。大多數(shù)和 message loop 的交互是通過 Handler。
下面是一個(gè)典型的帶有 Looper 的線程實(shí)現(xiàn)。?
class LooperThread extends Thread {?
public Handler mHandler; public void run() {?
Looper.prepare();
?mHandler = new Handler() {
?public void handleMessage(Message msg) { // process incoming messages here?
} };
?Looper.loop();?
} }
48. AIDL 的全稱是什么?如何工作?能處理哪些類型的數(shù)據(jù)?
答:AIDL 的英文全稱是 Android Interface Define Language。當(dāng) A 進(jìn)程要去調(diào)用 B 進(jìn)程中的 service 時(shí),并實(shí)現(xiàn)通信,我們通常都是通過 AIDL 來操作的A 工程:
首先我們在 net.blogjava.mobile.aidlservice 包中創(chuàng)建一個(gè) RemoteService.aidl 文件,在里面我們自定義一個(gè)接口,含有方法get。ADT插件會在gen目錄下自動(dòng)生成一個(gè)RemoteService.java文件,該類中含有一個(gè)名為 RemoteService.stub 的內(nèi)部類,該內(nèi)部類中含有 aidl 文件接口的get 方法。說明一:aidl 文件的位置不固定,可以任意然后定義自己的 MyService 類,在 MyService 類中自定義一個(gè)內(nèi)部類去繼承RemoteService.stub 這個(gè)內(nèi)部類,實(shí)現(xiàn) get 方法。在 onBind 方法中返回這個(gè)內(nèi)部類的對象,系統(tǒng)會自動(dòng)將這個(gè)對象封裝成 IBinder 對象,傳遞給他的調(diào)用者。其次需要在 AndroidManifest.xml 文件中配置 MyService 類,代碼如下:為什么要指定調(diào)用 AIDL 服務(wù)的 ID,就是要告訴外界 MyService 這個(gè)類能夠被別的進(jìn)程訪問,只要?jiǎng)e的進(jìn)程知道這個(gè) ID,正是有了這個(gè) ID,B 工程才能找到 A 工程實(shí)現(xiàn)通信。說明:AIDL 并不需要權(quán)限B 工程: 首先我們要將 A 工程中生成的 RemoteService.java 文件拷貝到 B 工程中,在bindService 方法中綁定 aidl 服務(wù) 綁定 AIDL 服務(wù)就是將 RemoteService 的 ID 作為 intent 的 action 參數(shù)。
說明:如果我們單獨(dú)將 RemoteService.aidl 文件放在一個(gè)包里,那個(gè)在我們將 gen 目錄下的該包拷貝到 B 工程中。如果我們將 RemoteService.aidl 文件和我們的其他類存放在一起,那么我們在 B 工程中就要建立相應(yīng)的包,以保證 RmoteService.java 文件的報(bào)名正確,我們不能修改 RemoteService.java 文件?
bindService(new Inten("net.blogjava.mobile.aidlservice.RemoteService"),serviceConnection, Context.BIND_AUTO_CREATE); ServiceConnection 的 onServiceConnected(ComponentName name, IBinder service)方法中的service參數(shù)就是A工程中MyService類中繼承了RemoteService.stub類的內(nèi)部類的對象。
49. 請解釋下 Android 程序運(yùn)行時(shí)權(quán)限與文件系統(tǒng)權(quán)限的區(qū)別。運(yùn)行時(shí)權(quán)限 Dalvik( android 授權(quán))文件系統(tǒng) linux 內(nèi)核授權(quán)50. 系統(tǒng)上安裝了多種瀏覽器,能否指定某瀏覽器訪問指定頁面?請說明原由。
通過直接發(fā)送 Uri 把參數(shù)帶過去,或者通過 manifest 里的 intentfilter 里的 data 屬性。