• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            life02

              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              197 隨筆 :: 3 文章 :: 37 評(píng)論 :: 0 Trackbacks
            Android面試題
            http://topic.csdn.net/u/20101219/21/b6f83d6f-35b5-49ea-b281-d47ca662ea17.html?57324
            1. 請(qǐng)描述下Activity的生命周期。
            2. 如果后臺(tái)的Activity由于某原因被系統(tǒng)回收了,如何在被系統(tǒng)回收之前保存當(dāng)前狀態(tài)?
            3. 如何將一個(gè)Activity設(shè)置成窗口的樣式。(Edited by Sodino)
            4. 如何退出Activity?如何安全退出已調(diào)用多個(gè)Activity的Application?
            5. 請(qǐng)介紹下Android中常用的五種布局。
            6. 請(qǐng)介紹下Android的數(shù)據(jù)存儲(chǔ)方式。(Edited by Sodino)
            7. 請(qǐng)介紹下ContentProvider是如何實(shí)現(xiàn)數(shù)據(jù)共享的。(Edited by Sodino)
            8. 如何啟用Service,如何停用Service。(Edited by Sodino)
            9. 注冊(cè)廣播有幾種方式,這些方式有何優(yōu)缺點(diǎn)?請(qǐng)談?wù)凙ndroid引入廣播機(jī)制的用意。
            10. 請(qǐng)解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關(guān)系。
            11. AIDL的全稱是什么?如何工作?能處理哪些類(lèi)型的數(shù)據(jù)?
            12. 請(qǐng)解釋下Android程序運(yùn)行時(shí)權(quán)限與文件系統(tǒng)權(quán)限的區(qū)別。(Edited by Sodino)
            13. 系統(tǒng)上安裝了多種瀏覽器,能否指定某瀏覽器訪問(wèn)指定頁(yè)面?請(qǐng)說(shuō)明原由。
            14. 有一個(gè)一維整型數(shù)組int[]data保存的是一張寬為width,高為height的圖片像素值信息。請(qǐng)寫(xiě)一個(gè)算法,將該圖片所有的白色不透明(0xffffffff)像素點(diǎn)的透明度調(diào)整為50%。
            15. 你如何評(píng)價(jià)Android系統(tǒng)??jī)?yōu)缺點(diǎn)。


            1.activity的生命周期。 

            2.橫豎屏切換時(shí)候activity的生命周期 

            總結(jié):

            1、不設(shè)置Activity的android:configChanges時(shí),切屏?xí)匦抡{(diào)用各個(gè)生命周期,切橫屏?xí)r會(huì)執(zhí)行一次,切豎屏?xí)r會(huì)執(zhí)行兩次

            2、設(shè)置Activity的android:configChanges="orientation"時(shí),切屏還是會(huì)重新調(diào)用各個(gè)生命周期,切橫、豎屏?xí)r只會(huì)執(zhí)行一次

            3、設(shè)置Activity的android:configChanges="orientation|keyboardHidden"時(shí),切屏不會(huì)重新調(diào)用各個(gè)生命周期,只會(huì)執(zhí)行onConfigurationChanged方法


            3.android中的動(dòng)畫(huà)有哪幾類(lèi),它們的特點(diǎn)和區(qū)別是什么 


            4.handler機(jī)制的原理 


            5.說(shuō)說(shuō)activity,intent,service是什么關(guān)系 

            6.android中線程與線程,進(jìn)程與進(jìn)程之間如何通信 

            7.widget相對(duì)位置的完成在antivity的哪個(gè)生命周期階段實(shí)現(xiàn) 

            8.說(shuō)說(shuō)mvc模式的原理,它在android中的運(yùn)用 

            9.說(shuō)說(shuō)在android中有哪幾種數(shù)據(jù)存儲(chǔ)方式 

            10.android中有哪幾種解析xml的類(lèi),官方推薦哪種?以及它們的原理和區(qū)別

            3. 如何將一個(gè)Activity設(shè)置成窗口的樣式。
              設(shè)置Activity窗口化:
              android:theme="@android:style/Theme.Dialog"
              設(shè)置Activity透明化:  
              android:theme="@android:style/Theme.Translucent"
            6. 請(qǐng)介紹下Android的數(shù)據(jù)存儲(chǔ)方式
              ㈠.文件存儲(chǔ)方式:
            在Android中通常使用File存儲(chǔ)方式是用 Context.openFileOutput(String fileName, int mode)和Context.openFileInput(String fileName)。
              Context.openFileOutput(String fileName, int mode)生成的文件自動(dòng)存儲(chǔ)在/data/data/PackageName/file目錄下,其全路徑是/data/data/Package Name/files/fileName 。注意下,這里的參數(shù)fileName不可以包含路徑分割符(如"/")。
              通常來(lái)說(shuō),這種方式生成的文件只能在這個(gè)apk內(nèi)訪問(wèn)。但這個(gè)結(jié)論是指使用Context.openFileInput(String fileName)的方式。使用這種方式,每個(gè)apk只可以訪問(wèn)自己的/data/data/Package Name/files目錄下的文件,原因很簡(jiǎn)單,參數(shù)fileName中不可以包含路徑分割符,Android會(huì)自動(dòng)在/data/data /Package Name/files目錄下尋找文件名為fileName的文件。
            具體實(shí)例如下:
            String fn = “moandroid.log”;
            FileInputStream fis = openFileInput(fn);
            FileOutputStream fos = openFileOutput(fn.Context.MODE_PRIVATE);

            ㈡.使用SharedPreferences存儲(chǔ)數(shù)據(jù)
            首先說(shuō)明SharedPreferences存儲(chǔ)方式,它是 Android提供的用來(lái)存儲(chǔ)一些簡(jiǎn)單配置信息的一種機(jī)制,例如:登錄用戶的用戶名與密碼。其采用了Map數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)數(shù)據(jù),以鍵值的方式存儲(chǔ),可以簡(jiǎn)單的讀取與寫(xiě)入,具體實(shí)例如下:
              void ReadSharedPreferences(){
              String strName,strPassword;
              SharedPreferences user = getSharedPreferences(“user_info”,0);
              strName = user.getString(“NAME”,””);
              strPassword = user getString(“PASSWORD”,””);
              }
              void WriteSharedPreferences(String strName,String strPassword){
              SharedPreferences user = getSharedPreferences(“user_info”,0);
              uer.edit()//獲得編輯器;
              user.putString(“NAME”, strName);
              user.putString(“PASSWORD” ,strPassword);
              user.commit();
              }
              數(shù)據(jù)讀取與寫(xiě)入的方法都非常簡(jiǎn)單,只是在寫(xiě)入的時(shí)候有些區(qū)別:先調(diào)用edit()使其處于編輯狀態(tài),然后才能修改數(shù)據(jù),最后使用commit()提交修改的數(shù)據(jù)。實(shí)際上SharedPreferences是采用了XML格式將數(shù)據(jù)存儲(chǔ)到設(shè)備中,在DDMS中的File Explorer中的/data/data/<package name>/shares_prefs下。以上面的數(shù)據(jù)存儲(chǔ)結(jié)果為例,打開(kāi)后可以看到一個(gè)user_info.xml的文件,打開(kāi)后可以看到:
              <?xml version=”1.0″ encoding=”UTF-8″?>
              <map>
              <string name=”NAME”>moandroid</string>
              <string name=” PASSWORD”>SharedPreferences</string>
              </map>
            使用SharedPreferences是有些限制的:只能在同一個(gè)包內(nèi)使用,不能在不同的包之間使用。

            ㈢:網(wǎng)絡(luò)存儲(chǔ)數(shù)據(jù)
            網(wǎng)絡(luò)存儲(chǔ)方式,需要和Android網(wǎng)絡(luò)數(shù)據(jù)包打交道。

            ㈣.ContentProvider數(shù)據(jù)存儲(chǔ)
            1、ContentProvider簡(jiǎn)介
            當(dāng)應(yīng)用繼承ContentProvider類(lèi),并重寫(xiě)該類(lèi)用于提供數(shù)據(jù)和存儲(chǔ)數(shù)據(jù)的方法,就可以向其他應(yīng)用共享其數(shù)據(jù)。雖然使用其他方法也可以對(duì)外共享數(shù)據(jù),但數(shù)據(jù)訪問(wèn)方式會(huì)因數(shù)據(jù)存儲(chǔ)的方式而不同,如:采用文件方式對(duì)外共享數(shù)據(jù),需要進(jìn)行文件操作讀寫(xiě)數(shù)據(jù);采用sharedpreferences共享數(shù)據(jù),需要使用sharedpreferences API讀寫(xiě)數(shù)據(jù)。而使用ContentProvider共享數(shù)據(jù)的好處是統(tǒng)一了數(shù)據(jù)訪問(wèn)方式。與之相關(guān)聯(lián)的是uri,下面是uri的簡(jiǎn)介:
            2、Uri類(lèi)簡(jiǎn)介
            Uri代表了要操作的數(shù)據(jù),Uri主要包含了兩部分信息:需要操作的ContentProvider和對(duì)ContentProvider中的什么數(shù)據(jù)進(jìn)行操作,一個(gè)Uri由以下幾部分組成:
              1).scheme:ContentProvider(內(nèi)容提供者)的scheme已經(jīng)由Android所規(guī)定為:content://。
              2).主機(jī)名(或Authority):用于唯一標(biāo)識(shí)這個(gè)ContentProvider,外部調(diào)用者可以根據(jù)這個(gè)標(biāo)識(shí)來(lái)找到它。
              3).路徑(path):可以用來(lái)表示我們要操作的數(shù)據(jù),路徑的構(gòu)建應(yīng)根據(jù)業(yè)務(wù)而定,如下:
              要操作contact表中id為10的記錄,可以構(gòu)建這樣的路徑:/contact/10
              要操作contact表中id為10的記錄的name字段, contact/10/name
              要操作contact表中的所有記錄,可以構(gòu)建這樣的路徑:/contact?
              要操作的數(shù)據(jù)不一定來(lái)自數(shù)據(jù)庫(kù),也可以是文件等他存儲(chǔ)方式,如下:
              要操作xml文件中contact節(jié)點(diǎn)下的name節(jié)點(diǎn),可以構(gòu)建這樣的路徑:/contact/name
            如果要把一個(gè)字符串轉(zhuǎn)換成Uri,可以使用Uri類(lèi)中的parse()方法,如下:
            Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")
              3、UriMatcher、ContentUrist和ContentResolver簡(jiǎn)介
            因?yàn)閁ri代表了要操作的數(shù)據(jù),所以我們很經(jīng)常需要解析Uri,并從 Uri中獲取數(shù)據(jù)。Android系統(tǒng)提供了兩個(gè)用于操作Uri的工具類(lèi),分別為UriMatcher 和ContentUris 。掌握它們的使用,會(huì)便于我們的開(kāi)發(fā)工作。
            ? UriMatcher:用于匹配Uri,它的用法如下:
              1).首先把你需要匹配Uri路徑全部給注冊(cè)上,如下:
            //常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼(-1)。
            UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
            //如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider /contact路徑,返回匹配碼為1
            uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);//添加需要匹配uri,如果匹配就會(huì)返回匹配碼
            //如果match()方法匹配 content://com.changcheng.sqlite.provider.contactprovider/contact/230路徑,返回匹配碼為2
            uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);//#號(hào)為通配符

              2).注冊(cè)完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法對(duì)輸入的Uri進(jìn)行匹配,如果匹配就返回匹配碼,匹配碼是調(diào)用 addURI()方法傳入的第三個(gè)參數(shù),假設(shè)匹配 content://com.changcheng.sqlite.provider.contactprovider/contact路徑,返回的匹配碼為1。

            ContentUris:用于獲取Uri路徑后面的ID部分,它有兩個(gè)比較實(shí)用的方法:
             withAppendedId(uri, id)用于為路徑加上ID部分
             parseId(uri)方法用于從路徑中獲取ID部分
             ContentResolver:當(dāng)外部應(yīng)用需要對(duì)ContentProvider中的數(shù)據(jù)進(jìn)行添加、刪除、修改和查詢操作時(shí),可以使用 ContentResolver 類(lèi)來(lái)完成,要獲取ContentResolver 對(duì)象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,來(lái)操作數(shù)據(jù)。
            ㈤.數(shù)據(jù)庫(kù)存儲(chǔ)方式?
            數(shù)據(jù)庫(kù)存儲(chǔ)方式,最長(zhǎng)用的是SQLite
            8. 如何啟用Service,如何停用Service
              ● 啟動(dòng)方式和停止方式:
            ㈠.Context.startService() / Context.stopService();
            ㈡. Context.bindService() / Context.unbindService();
            9. 注冊(cè)廣播有幾種方式,這些方式有何優(yōu)缺點(diǎn)?請(qǐng)談?wù)凙ndroid引入廣播機(jī)制的用意。
              在android下,要想接受廣播信息,那么這個(gè)廣播接收器就得我們自己來(lái)實(shí)現(xiàn)了,我們可以繼承BroadcastReceiver,就可以有一個(gè)廣播接受器了。有個(gè)接受器還不夠,我們還得重寫(xiě)B(tài)roadcastReceiver里面的onReceiver方法,當(dāng)來(lái)廣播的時(shí)候我們要干什么,這就要我們自己來(lái)實(shí)現(xiàn),不過(guò)我們可以搞一個(gè)信息防火墻。具體的代碼:
            public class SmsBroadCastReceiver extends BroadcastReceiver  
            {  
              public void onReceive(Context context, Intent intent)  
              {  
              Bundle bundle = intent.getExtras();  
              Object[] object = (Object[])bundle.get("pdus");  
              SmsMessage sms[]=new SmsMessage[object.length];  
              for(int i=0;i<object.length;i++)  
              {  
              sms[0] = SmsMessage.createFromPdu((byte[])object[i]);  
              Toast.makeText(context, "來(lái)自 "+sms[i].getDisplayOriginatingAddress()+" 的消息是:"+sms[i].getDisplayMessageBody(), Toast.LENGTH_SHORT).show();  
              }  
              //終止廣播,在這里我們可以稍微處理,根據(jù)用戶輸入的號(hào)碼可以實(shí)現(xiàn)短信防火墻。  
              abortBroadcast();  
              }  
               
            }  
            當(dāng)實(shí)現(xiàn)了廣播接收器,還要設(shè)置廣播接收器接收廣播信息的類(lèi)型,這里是信息:android.provider.Telephony.SMS_RECEIVED
              我們就可以把廣播接收器注冊(cè)到系統(tǒng)里面,可以讓系統(tǒng)知道我們有個(gè)廣播接收器。這里有兩種,
            ? 一種是代碼動(dòng)態(tài)注冊(cè):
            //生成廣播處理  
            smsBroadCastReceiver = new SmsBroadCastReceiver();  
            //實(shí)例化過(guò)濾器并設(shè)置要過(guò)濾的廣播  
            IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); 

            //注冊(cè)廣播  
            BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver, intentFilter);  
            ? 一種是在AndroidManifest.xml中配置廣播
            <?xml version="1.0" encoding="utf-8"?>  
            <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="spl.broadCastReceiver"  
              android:versionCode="1"  
              android:versionName="1.0">  
              <application android:icon="@drawable/icon" android:label="@string/app_name">  
              <activity android:name=".BroadCastReceiverActivity"  
              android:label="@string/app_name">  
              <intent-filter>  
              <action android:name="android.intent.action.MAIN" />  
              <category android:name="android.intent.category.LAUNCHER" />  
              </intent-filter>  
              </activity>  
               
              <!--廣播注冊(cè)-->  
              <receiver android:name=".SmsBroadCastReceiver">  
              <intent-filter android:priority="20">  
              <action android:name="android.provider.Telephony.SMS_RECEIVED"/>  
              </intent-filter>  
              </receiver>  
               
              </application>  
               
              <uses-sdk android:minSdkVersion="7" />  
               
              <!-- 權(quán)限申請(qǐng) -->  
              <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>  
               
            </manifest>  
              兩種注冊(cè)類(lèi)型的區(qū)別是:
              1)第一種不是常駐型廣播,也就是說(shuō)廣播跟隨程序的生命周期。
              2)第二種是常駐型,也就是說(shuō)當(dāng)應(yīng)用程序關(guān)閉后,如果有信息廣播來(lái),程序也會(huì)被系統(tǒng)調(diào)用自動(dòng)運(yùn)行
            請(qǐng)解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關(guān)系。
              2.2 Message Queue
              在單線程模型下,為了解決類(lèi)似的問(wèn)題,Android設(shè)計(jì)了一個(gè)Message Queue(消息隊(duì)列), 線程間可以通過(guò)該Message Queue并結(jié)合Handler和Looper組件進(jìn)行信息交換。下面將對(duì)它們進(jìn)行分別介紹:
            1. Message
              Message消息,理解為線程間交流的信息,處理數(shù)據(jù)后臺(tái)線程需要更新UI,則發(fā)送Message內(nèi)含一些數(shù)據(jù)給UI線程。
            2. Handler
              Handler處理者,是Message的主要處理者,負(fù)責(zé)Message的發(fā)送,Message內(nèi)容的執(zhí)行處理。后臺(tái)線程就是通過(guò)傳進(jìn)來(lái)的 Handler對(duì)象引用來(lái)sendMessage(Message)。而使用Handler,需要implement 該類(lèi)的 handleMessage(Message)
            方法,它是處理這些Message的操作內(nèi)容,例如Update UI。通常需要子類(lèi)化Handler來(lái)實(shí)現(xiàn)handleMessage方法。
            3. Message Queue
              Message Queue消息隊(duì)列,用來(lái)存放通過(guò)Handler發(fā)布的消息,按照先進(jìn)先出執(zhí)行。
              每個(gè)message queue都會(huì)有一個(gè)對(duì)應(yīng)的Handler。Handler會(huì)向message queue通過(guò)兩種方法發(fā)送消息:sendMessage或post。這兩種消息都會(huì)插在message queue隊(duì)尾并按先進(jìn)先出執(zhí)行。但通過(guò)這兩種方法發(fā)送的消息執(zhí)行的方式略有不同:通過(guò)sendMessage發(fā)送的是一個(gè)message對(duì)象,會(huì)被 Handler的handleMessage()函數(shù)處理;而通過(guò)post方法發(fā)送的是一個(gè)runnable對(duì)象,則會(huì)自己執(zhí)行。
            4. Looper
              Looper是每條線程里的Message Queue的管家。Android沒(méi)有Global的Message Queue,而Android會(huì)自動(dòng)替主線程(UI線程)建立Message Queue,但在子線程里并沒(méi)有建立Message Queue。所以調(diào)用Looper.getMainLooper()得到的主線程的Looper不為NULL,但調(diào)用Looper.myLooper() 得到當(dāng)前線程的Looper就有可能為NULL。
              對(duì)于子線程使用Looper,API Doc提供了正確的使用方法:

              這個(gè)Message機(jī)制的大概流程:
              1. 在Looper.loop()方法運(yùn)行開(kāi)始后,循環(huán)地按照接收順序取出Message Queue里面的非NULL的Message。
              2. 一開(kāi)始Message Queue里面的Message都是NULL的。當(dāng)Handler.sendMessage(Message)到Message Queue,該函數(shù)里面設(shè)置了那個(gè)Message對(duì)象的target屬性是當(dāng)前的Handler對(duì)象。隨后Looper取出了那個(gè)Message,則調(diào)用該Message的target指向的Hander的dispatchMessage函數(shù)對(duì)Message進(jìn)行處理。
              在dispatchMessage方法里,如何處理Message則由用戶指定,三個(gè)判斷,優(yōu)先級(jí)從高到低:
              1) Message里面的Callback,一個(gè)實(shí)現(xiàn)了Runnable接口的對(duì)象,其中run函數(shù)做處理工作;
              2) Handler里面的mCallback指向的一個(gè)實(shí)現(xiàn)了Callback接口的對(duì)象,由其handleMessage進(jìn)行處理;
              3) 處理消息Handler對(duì)象對(duì)應(yīng)的類(lèi)繼承并實(shí)現(xiàn)了其中handleMessage函數(shù),通過(guò)這個(gè)實(shí)現(xiàn)的handleMessage函數(shù)處理消息。
              由此可見(jiàn),我們實(shí)現(xiàn)的handleMessage方法是優(yōu)先級(jí)最低的!
              3. Handler處理完該Message (update UI) 后,Looper則設(shè)置該Message為NULL,以便回收!
              在網(wǎng)上有很多文章講述主線程和其他子線程如何交互,傳送信息,最終誰(shuí)來(lái)執(zhí)行處理信息之類(lèi)的,個(gè)人理解是最簡(jiǎn)單的方法——判斷Handler對(duì)象里面的 Looper對(duì)象是屬于哪條線程的,則由該線程來(lái)執(zhí)行!
              1. 當(dāng)Handler對(duì)象的構(gòu)造函數(shù)的參數(shù)為空,則為當(dāng)前所在線程的Looper;
              2. Looper.getMainLooper()得到的是主線程的Looper對(duì)象,Looper.myLooper()得到的是當(dāng)前線程的Looper對(duì)象。

            11. AIDL的全稱是什么?如何工作?能處理哪些類(lèi)型的數(shù)據(jù)?
              AIDL(AndRoid接口描述語(yǔ)言)是一種接口描述語(yǔ)言; 編譯器可以通過(guò)aidl文件生成一段代碼,通過(guò)預(yù)先定義的接口達(dá)到兩個(gè)進(jìn)程內(nèi)部通信進(jìn)程的目的. 如果需要在一個(gè)Activity中, 訪問(wèn)另一個(gè)Service中的某個(gè)對(duì)象, 需要先將對(duì)象轉(zhuǎn)化成AIDL可識(shí)別的參數(shù)(可能是多個(gè)參數(shù)), 然后使用AIDL來(lái)傳遞這些參數(shù), 在消息的接收端, 使用這些參數(shù)組裝成自己需要的對(duì)象.
            AIDL的IPC的機(jī)制和COM或CORBA類(lèi)似, 是基于接口的,但它是輕量級(jí)的。它使用代理類(lèi)在客戶端和實(shí)現(xiàn)層間傳遞值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相關(guān)類(lèi).; 2. 調(diào)用aidl產(chǎn)生的class.
            AIDL的創(chuàng)建方法:
            AIDL語(yǔ)法很簡(jiǎn)單,可以用來(lái)聲明一個(gè)帶一個(gè)或多個(gè)方法的接口,也可以傳遞參數(shù)和返回值。由于遠(yuǎn)程調(diào)用的需要, 這些參數(shù)和返回值并不是任何類(lèi)型.
            下面是些AIDL支持的數(shù)據(jù)類(lèi)型:
            1. 不需要import聲明的簡(jiǎn)單Java編程語(yǔ)言類(lèi)型(int,boolean等)
            2. String, CharSequence不需要特殊聲明 
            3. List, Map和Parcelables類(lèi)型, 這些類(lèi)型內(nèi)所包含的數(shù)據(jù)成員也只能是簡(jiǎn)單數(shù)據(jù)類(lèi)型, String等其他比支持的類(lèi)型.
            12. 請(qǐng)解釋下Android程序運(yùn)行時(shí)權(quán)限與文件系統(tǒng)權(quán)限的區(qū)別
              要區(qū)分apk運(yùn)行時(shí)的擁有的權(quán)限與在文件系統(tǒng)上被訪問(wèn)(讀寫(xiě)執(zhí)行)的權(quán)限兩個(gè)概念。
              apk程序是運(yùn)行在虛擬機(jī)上的,對(duì)應(yīng)的是Android獨(dú)特的權(quán)限機(jī)制,只有體現(xiàn)到文件系統(tǒng)上時(shí)才使用linux的權(quán)限設(shè)置
            (一)linux文件系統(tǒng)上的權(quán)限
            -rwxr-x--x system system 4156 2010-04-30 16:13 test.apk
              代表的是相應(yīng)的用戶/用戶組及其他人對(duì)此文件的訪問(wèn)權(quán)限,與此文件運(yùn)行起來(lái)具有的權(quán)限完全不相關(guān)。比如上面的例子只能說(shuō)明system用戶擁有對(duì)此文件的讀寫(xiě)執(zhí)行權(quán)限;system組的用戶對(duì)此文件擁有讀、執(zhí)行權(quán)限;其他人對(duì)此文件只具有執(zhí)行權(quán)限。
            而test.apk運(yùn)行起來(lái)后可以干哪些事情,跟這個(gè)就不相關(guān)了。
            千萬(wàn)不要看apk文件系統(tǒng)上屬于system/system用戶及用戶組,或者root/root用戶及用戶組,就認(rèn)為apk具有system或root權(quán)限
              (二)Android的權(quán)限規(guī)則
              (1)Android中的apk必須簽名
              這種簽名不是基于權(quán)威證書(shū)的,不會(huì)決定某個(gè)應(yīng)用允不允許安裝,而是一種自簽名證書(shū)。重要的是,android系統(tǒng)有的權(quán)限是基于簽名的。比如:system等級(jí)的權(quán)限有專(zhuān)門(mén)對(duì)應(yīng)的簽名,簽名不對(duì),權(quán)限也就獲取不到。
            默認(rèn)生成的APK文件是debug簽名的。
            (2)基于UserID的進(jìn)程級(jí)別的安全機(jī)制
            大家都知道,進(jìn)程有獨(dú)立的地址空間,進(jìn)程與進(jìn)程間默認(rèn)是不能互相訪問(wèn)的,是一種很可靠的保護(hù)機(jī)制。
            Android通過(guò)為每一個(gè)安裝在設(shè)備上的包(apk)分配唯一的linux userID來(lái)實(shí)現(xiàn),名稱為"app_"加一個(gè)數(shù)字,比如app_43
            不同的UserID,運(yùn)行在不同的進(jìn)程,所以apk之間默認(rèn)便不能相互訪問(wèn)。
            Android提供了如下的一種機(jī)制,可以使兩個(gè)apk打破前面講的這種壁壘。
            在AndroidManifest.xml中利用sharedUserId屬性給不同的package分配相同的userID,通過(guò)這樣做,兩個(gè)package可以被當(dāng)做同一個(gè)程序,
            系統(tǒng)會(huì)分配給兩個(gè)程序相同的UserID。當(dāng)然,基于安全考慮,兩個(gè)package需要有相同的簽名,否則沒(méi)有驗(yàn)證也就沒(méi)有意義了。
            (這里補(bǔ)充一點(diǎn):并不是說(shuō)分配了同樣的UserID,兩程序就運(yùn)行在同一進(jìn)程, 下面為PS指令摘取的,
            顯然,system、app_2分別對(duì)應(yīng)的兩個(gè)進(jìn)程的PID都不同,不知Android到底是怎樣實(shí)現(xiàn)它的機(jī)制的)
            User PID PPID
            system 953 883 187340 55052 ffffffff afe0cbcc S system_server
            app_2 1072 883 100264 19564 ffffffff afe0dcc4 S com.android.inputmethod.
            system 1083 883 111808 23192 ffffffff afe0dcc4 S android.process.omsservi
            app_2 1088 883 156464 45720 ffffffff afe0dcc4 S android.process.acore
            (3)默認(rèn)apk生成的數(shù)據(jù)對(duì)外是不可見(jiàn)的
            實(shí)現(xiàn)方法是:Android會(huì)為程序存儲(chǔ)的數(shù)據(jù)分配該程序的UserID。
            借助于Linux嚴(yán)格的文件系統(tǒng)訪問(wèn)權(quán)限,便實(shí)現(xiàn)了apk之間不能相互訪問(wèn)似有數(shù)據(jù)的機(jī)制。
            例:我的應(yīng)用創(chuàng)建的一個(gè)文件,默認(rèn)權(quán)限如下,可以看到只有UserID為app_21的程序才能讀寫(xiě)該文件。
            -rw------- app_21 app_21 87650 2000-01-01 09:48 test.txt
            如何對(duì)外開(kāi)放?
            <1> 使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE 標(biāo)記。
            When creating a new file with getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.

            (4)AndroidManifest.xml中的顯式權(quán)限聲明
            Android默認(rèn)應(yīng)用是沒(méi)有任何權(quán)限去操作其他應(yīng)用或系統(tǒng)相關(guān)特性的,應(yīng)用在進(jìn)行某些操作時(shí)都需要顯式地去申請(qǐng)相應(yīng)的權(quán)限。
            一般以下動(dòng)作時(shí)都需要申請(qǐng)相應(yīng)的權(quán)限:
            A particular permission may be enforced at a number of places during your program's operation: 
            • At the time of a call into the system, to prevent an application from executing certain functions.
            • When starting an activity, to prevent applications from launching activities of other applications.
            • Both sending and receiving broadcasts, to control who can receive your broadcast or who can send a broadcast to you.
            • When accessing and operating on a content provider.
            • Binding or starting a service.

            在應(yīng)用安裝的時(shí)候,package installer會(huì)檢測(cè)該應(yīng)用請(qǐng)求的權(quán)限,根據(jù)該應(yīng)用的簽名或者提示用戶來(lái)分配相應(yīng)的權(quán)限。
            在程序運(yùn)行期間是不檢測(cè)權(quán)限的。如果安裝時(shí)權(quán)限獲取失敗,那執(zhí)行就會(huì)出錯(cuò),不會(huì)提示用戶權(quán)限不夠。
            大多數(shù)情況下,權(quán)限不足導(dǎo)致的失敗會(huì)引發(fā)一個(gè) SecurityException, 會(huì)在系統(tǒng)log(system log)中有相關(guān)記錄。
            (5)權(quán)限繼承/UserID繼承
            當(dāng)我們遇到apk權(quán)限不足時(shí),我們有時(shí)會(huì)考慮寫(xiě)一個(gè)linux程序,然后由apk調(diào)用它去完成某個(gè)它沒(méi)有權(quán)限完成的事情,很遺憾,這種方法是行不通的。
            前面講過(guò),android權(quán)限是經(jīng)營(yíng)在進(jìn)程層面的,也就是說(shuō)一個(gè)apk應(yīng)用啟動(dòng)的子進(jìn)程的權(quán)限不可能超越其父進(jìn)程的權(quán)限(即apk的權(quán)限),
            即使單獨(dú)運(yùn)行某個(gè)應(yīng)用有權(quán)限做某事,但如果它是由一個(gè)apk調(diào)用的,那權(quán)限就會(huì)被限制。
            實(shí)際上,android是通過(guò)給子進(jìn)程分配父進(jìn)程的UserID實(shí)現(xiàn)這一機(jī)制的。
            (三)常見(jiàn)權(quán)限不足問(wèn)題分析

            首先要知道,普通apk程序是運(yùn)行在非root、非system層級(jí)的,也就是說(shuō)看要訪問(wèn)的文件的權(quán)限時(shí),看的是最后三位。
            另外,通過(guò)system/app安裝的apk的權(quán)限一般比直接安裝或adb install安裝的apk的權(quán)限要高一些。

            言歸正傳,運(yùn)行一個(gè)android應(yīng)用程序過(guò)程中遇到權(quán)限不足,一般分為兩種情況:
            (1)Log中可明顯看到權(quán)限不足的提示。
            此種情況一般是AndroidManifest.xml中缺少相應(yīng)的權(quán)限設(shè)置,好好查找一番權(quán)限列表,應(yīng)該就可解決,是最易處理的情況。
            有時(shí)權(quán)限都加上了,但還是報(bào)權(quán)限不足,是什么情況呢?
            Android系統(tǒng)有一些API及權(quán)限是需要apk具有一定的等級(jí)才能運(yùn)行的。
            比如 SystemClock.setCurrentTimeMillis()修改系統(tǒng)時(shí)間,WRITE_SECURE_SETTINGS權(quán)限好像都是需要有system級(jí)的權(quán)限才行。
            也就是說(shuō)UserID是system.
            (2)Log里沒(méi)有報(bào)權(quán)限不足,而是一些其他Exception的提示,這也有可能是權(quán)限不足造成的。
            比如:我們常會(huì)想讀/寫(xiě)一個(gè)配置文件或其他一些不是自己創(chuàng)建的文件,常會(huì)報(bào)java.io.FileNotFoundException錯(cuò)誤。
            系統(tǒng)認(rèn)為比較重要的文件一般權(quán)限設(shè)置的也會(huì)比較嚴(yán)格,特別是一些很重要的(配置)文件或目錄。

            -r--r----- bluetooth bluetooth 935 2010-07-09 20:21 dbus.conf
            drwxrwx--x system system 2010-07-07 02:05 data 

            dbus.conf好像是藍(lán)牙的配置文件,從權(quán)限上來(lái)看,根本就不可能改動(dòng),非bluetooth用戶連讀的權(quán)利都沒(méi)有。
            /data目錄下存的是所有程序的私有數(shù)據(jù),默認(rèn)情況下android是不允許普通apk訪問(wèn)/data目錄下內(nèi)容的,通過(guò)data目錄的權(quán)限設(shè)置可知,其他用戶沒(méi)有讀的權(quán)限。
            所以adb普通權(quán)限下在data目錄下敲ls命令,會(huì)得到opendir failed, Permission denied的錯(cuò)誤,通過(guò)代碼file.listfiles()也無(wú)法獲得data目錄下的內(nèi)容。
            13. 系統(tǒng)上安裝了多種瀏覽器,能否指定某瀏覽器訪問(wèn)指定頁(yè)面?請(qǐng)說(shuō)明原由。
              如果在你的android系統(tǒng)上安裝了多種瀏覽器,能否指定某瀏覽器訪問(wèn)指定頁(yè)面?答案當(dāng)然是:肯定的。
            問(wèn)題的關(guān)鍵在于我們?cè)O(shè)置了class name,也就是我們想要跳轉(zhuǎn)的pakcage的activity。如果你想要跳轉(zhuǎn)到其它的瀏覽器,只需要修改一下這個(gè)函數(shù)就OK了。
              好,我們現(xiàn)在來(lái)讓剛剛的思路來(lái)指導(dǎo)我們的實(shí)踐。假如我們現(xiàn)在要直接啟動(dòng)UC瀏覽器,那么我們?cè)撛趺醋瞿兀孔屛覀僺tep by step吧。

            1.下載UC apk:http://i-uc.net/read.php?2

            2. 用7zip解壓apk文件,得到classes.dex文件

            3.下載反編譯dex文件工具:http://nchc.dl.sourceforge.net/project/dedexer/dedexer/1.5/ddx1.5.jar(Dedexer 項(xiàng)目主頁(yè): http://dedexer.sourceforge.net/)
            4.執(zhí)行命令:java -jar ddx1.5.jar -o -D -d c:\ c:\classes.dex
            5. 得到package name是:com.uc.browser,啟動(dòng)的activity是:com.uc.browser.ActivityUpdate(補(bǔ)充:當(dāng)我在這里選擇采用ActivityBrowser的時(shí)候發(fā)覺(jué)權(quán)限不夠,報(bào)permiss denied 異常,而且也不是我們要的那個(gè)activity,幸運(yùn)的是在第二次嘗試用ActivityUpdate,剛好能滿足要求)
            6.修改上面的代碼為intent.setClassName("com.uc.browser","com.uc.browser.ActivityUpdate");
            posted on 2011-12-06 16:38 life02 閱讀(876) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): android面試題
            亚洲天堂久久精品| 国产精自产拍久久久久久蜜| 久久国产免费| 国产ww久久久久久久久久| 99久久成人国产精品免费| 久久久久AV综合网成人| 国内精品久久久久久久久电影网| 久久成人精品| 久久久噜噜噜久久| 久久午夜免费视频| 久久99热这里只有精品66| 亚洲国产综合久久天堂| 伊人久久一区二区三区无码| 久久亚洲色一区二区三区| 亚洲国产成人久久笫一页| 性做久久久久久久久浪潮| 久久久久久午夜精品| 久久精品卫校国产小美女| 中文字幕无码精品亚洲资源网久久| 亚洲中文字幕无码久久2017| 久久久精品国产sm调教网站| 99久久婷婷国产综合亚洲| 国产精品一久久香蕉国产线看 | 亚洲天堂久久久| 思思久久精品在热线热| 日本久久久久亚洲中字幕| 精品久久久久久无码中文字幕一区 | 丁香久久婷婷国产午夜视频| 久久精品无码一区二区日韩AV| 日韩久久无码免费毛片软件| 久久精品中文字幕大胸| 久久久久久久人妻无码中文字幕爆 | 亚洲国产精品综合久久一线| 精品一二三区久久aaa片| 精品久久久久久国产潘金莲| 久久福利片| 亚洲色欲久久久综合网| 国产精品美女久久久免费| 久久精品免费全国观看国产| 国产精品禁18久久久夂久| 看全色黄大色大片免费久久久|