androidservice許可權
A. 針對android 有哪些關於訪問訪問方面的許可權
Android是一個多進程系統,在這個系統中,應用程序(或者系統的部分)會在自己的進程中運行。系統和應用之間的安全性是通過Linux的facilities(工具,功能)在進程級別來強制實現的,比如會給應用程序分配user ID和Group ID。更細化的安全特性是通過"Permission"機制對特定的進程的特定的操作進行限制,而"per-URI permissions"可以對獲取特定數據的access專門許可權進行限制。
安全架構
Android安全架構中一個中心思想就是:應用程序在默認的情況下不可以執行任何對其他應用程序,系統或者用戶帶來負面影響的操作。這包括讀或寫用戶的私有數據(如聯系人數據或email數據),讀或寫另一個應用程序的文件,網路連接,保持設備處於非睡眠狀態。
一個應用程序的進程就是一個安全的沙盒。它不能幹擾其它應用程序,除非顯式地聲明了"permissions",以便它能夠獲取基本沙盒所不具備的額外的能力。它請求的這些許可權"permissions"可以被各種各樣的操作處理,如自動允許該許可權或者通過用戶提示或者證書來禁止該許可權。應用程序需要的那些"permissions"是靜態的在程序中聲明,所以他們會在程序安裝時就被知曉,並不會再改變。
應用程序簽名
所有的Android應用程序(.apk文件)必須用證書進行簽名認證,而這個證書的私鑰是由開發者保有的。該證書可以用以識別應用程序的作者。該證書也不需要CA簽名認證(註:CA就是一個第三方的證書認證機構,如verisign等)。Android應用程序允許而且一般也都是使用self-signed證書(即自簽名證書)。證書是用於在應用程序之間建立信任關系,而不是用於控製程序是否可以安裝。簽名影響安全性的最重要的方式是通過決定誰可以進入基於簽名的permisssions,以及誰可以share 用戶IDs。
用戶IDs和文件存取
每一個Android應用程序(.apk文件)都會在安裝時就分配一個獨有的Linux用戶ID,這就為它建立了一個沙盒,使其不能與其他應用程序進行接觸(也不會讓其它應用程序接觸它)。這個用戶ID會在安裝時分配給它,並在該設備上一直保持同一個數值。
由於安全性限制措施是發生進程級,所以兩個package中的代碼不會運行在同一個進程當中,他們要作為不同的Linux用戶出現。我們可以通過使用AndroidManifest.xml文件中的manifest標簽中的sharedUserId屬性,來使不同的package共用同一個用戶ID。通過這種方式,這兩個package就會被認為是同一個應用程序,擁有同一個用戶ID(實際不一定),並且擁有同樣的文件存取許可權。注意:為了保持安全,只有當兩個應用程序被同一個簽名簽署的時候(並且請求了同一個sharedUserId)才會被分配同樣的用戶ID.
所有存儲在應用程序中的數據都會賦予一個屬性-該應用程序的用戶ID,這使得其他package無法訪問這些數據。當通過這些方法getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory)來創建一個新文件時,你可以通過使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE標志位來設置是否允許其他package來訪問讀寫這個文件。當設置這些標志位時,該文件仍然屬於該應用程序,但是它的global read and/or write許可權已經被設置,使得它對於其他任何應用程序都是可見的。
Using Permissions 使用許可權
一個基本的Android程序通常是沒有任何permissions與之關聯的,這就是說它不能做任何擾亂用戶或破壞數據的勾當。那麼為了使用設備被保護的features,我們就必須在AndroidManifest.xml添加一個或多個<uses-permission> 標簽,用以聲明你的應用程序需要的permissions.
下面是個例子
For example, an application that needs to monitor incoming SMS messages would specify:
Xml代碼
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.app.myapp" > <uses-permission android:name="android.permission.RECEIVE_SMS" /> ... </manifest>
應用程序安裝的時候,應用程序請求的permissions是通過package installer來批准獲取的。package installer是通過檢查該應用程序的簽名和/或用戶的交換結果來確定是否給予該程序request的許可權。在用戶使用過程中不會去檢查許可權,也就是說要麼在安裝的時候就批准該許可權,使其按照設計可以使用該許可權;要麼就不批准,這樣用戶也就根本無法使用該feature,也不會有任何提示告知用戶嘗試失敗。
很多時候, 一個permission failure會導致一個SecurityException被拋回該應用程序. 但是Android並不保證這種情況會處處發生。例如,當數據被deliver到每一個receiver的時候,sendBroadcast(Intent) 方法會去檢查permissions,在這個方法調用返回之後,你也不會收到任何exception。幾乎絕大多數情況,一個permission failure都會列印到log當中。
Android系統定義的許可權可以在Manifest.permission中找到。任何一個程序都可以定義並強制執行自己獨有的permissions,因此Manifest.permission中定義的permissions並不是一個完整的列表(即有肯能有自定義的permissions)。
一個特定的permission可能會在程序操作的很多地方都被強制實施:
當系統有來電的時候,用以阻止程序執行其它功能;
啟動一個activity的時候,會控制誰可以啟動你的Acitivity;
在發送和接收廣播的時候,去控制誰可以接收你的廣播或誰可以發送廣播給你;
當進入並操作一個content provider的時候;
當綁定或開始一個service的時候。
聲明和使用Permissions
為了實現你自己的permissions,你必須首先在AndroidManifest.xml文件中聲明該permissions.通常我們通過使用一到多個<permission> tag來進行聲明。
下面例子說明了一個應用程序它想控制誰才可以啟動它的Activity:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.me.app.myapp" > <permissionandroid:name="com.me.app.myapp.permission.DEADLY_ACTIVITY" android:label="@string/permlab_deadlyActivity"android:description="@string/permdesc_deadlyActivity" android:permissionGroup="android.permission-group.COST_MONEY" android:protectionLevel="dangerous" /> ... </manifest>
這里<protectionLevel>屬性是需要聲明的(通常系統自有的permission都會有它對應的protection level,而我們自己定義的permission一般都需要定義protecdtion level, 若不去定義,則默認為normal)。通過聲明該屬性,我們就可以告知系統如何去通告用戶以及通告哪些內容,或者告知系統誰才可以擁有該permission。具體請參看鏈接的文檔。
這我多說兩句啊,這個protectionLevel分四個等級,分別是Normal, Dangerous, Signature, SignatureOrSystem,越往後安全等級越高。
這個<permissionGroup>屬性是可選項, 只是用於幫助系統顯示permissions給用戶(實際是告知系統該permission是屬於哪個permission group的)。你通常會選擇使用標準的system group來設定該屬性,或者用你自己定義的group(更為罕見)。通常使用一個已經存在的group會更合適,因為這樣UI顯示的時候會更簡單。
需要注意的是label和description都是需要為permission提供的。這些都是字元串資源,當用戶去看permission列表(android:label)或者某個permission的詳細信息(android:description)時,這些字元串資源就可以顯示給用戶。label應當盡量簡短,之需要告知用戶該permission是在保護什麼功能就行。而description可以用於具體描述獲取該permission的程序可以做哪些事情,實際上讓用戶可以知道如果他們同意程序獲取該許可權的話,該程序可以做什麼。我們通常用兩句話來描述permission,第一句描述該permission,第二句警告用戶如果批准該許可權會可能有什麼不好的事情發生。下面是一個描述CALL_PHONE permission的label和description的例子:
<string name="permlab_callPhone">directly call phone numbers</string> <string name="permdesc_callPhone">Allows the application to call phone numbers without your intervention. Malicious applications may cause unexpected calls on your phone bill. Note that this does not allow the application to call emergency numbers.</string>
你可以通過shell指令 adb shell pm list permissions 來查看目前系統已有的permissions. 特別的,"-s"選項會以一種用戶會看到的格式一樣的格式來顯示這些permissions.
在AndroidManifest.xml中強制使用Permissions
通過AP的AndroidManifest.xml文件可以設置該AP中各個組件的訪問許可權,包括Activity,
Service,BroadcastReceiver,ContentProvider。這些組件中都包含android:permission屬性,設置這個屬性就可以控制訪問該組件的許可權。
Activity permissions許可權限制了誰才可以啟動相應的activity。Permission會在Context.startActivity()和Activity.startActivityForResult()的時候進行檢查,如果caller沒有所需的許可權,則會拋出一個SecurityException。
Service permissions用於限制誰才可以start或bind該service。在Context.startService() , Context.stopService() 和 Context.bindService() 調用的時候會進行許可權檢查。如果caller沒有所需的許可權,則會拋出一個SecurityException。
BroadcastReceiver permissions用於限制誰才可以向該receiver發送廣播。許可權檢查會在Context.sendBroadcast() 返回時進行,由系統去發送已經提交的廣播給相應的Receiver。最終,一個permission failure不會再返回給Caller一個exception;它只是不會去deliver該Intent而已。同樣地,Context.registerReceiver() 也可以有自己permission用於限制誰才可以向一個在程序中注冊的receiver發送廣播。另一種方式是,一個permission也可以提供給Context.sendBroadcast() 用以限制哪一個BroadcastReceiver才可以接收該廣播。
ContentProvider permission用於限制誰才可以訪問ContentProvider提供的數據。(Content providers有一套另外的安全機制叫做URI permissions,這些在稍後討論)不同於其它的Components,這里有兩種不同的permission屬性可以設置: android:readPermission 用於限制誰可以讀取provider中的數據,而 android:writePermission 用於限制誰才可以向provider中寫入數據。需要注意的是如果provider既被read permission保護,也被write permission保護的話,如果這時只有write permission並不意味著你就可以讀取provider中的數據了。當你第一次獲取provider的時候就要進行許可權檢查(如果你沒有任何permission,則會拋出SecurityException)。當使用ContentResolver.query() 時需要讀許可權,而當使用 ContentResolver.insert() , ContentResolver.update() , ContentResolver.delete() 時需要寫許可權。在所有這些情況下,沒有所需的permission將會導致SecurityException被拋出。
在Sending Broadcasts時強制使用Permissions
除了之前說過的Permission(用於限制誰才可以發送廣播給相應的broadcastReceiver),你還可以在發送廣播的時候指定一個permission。在調用Context.sendBroadcast() 的時候使用一個permission string,你就可以要求receiver的宿主程序必須有相應的permission。值得注意的是Receiver和broadcaster都可以要求permission。當這種情況發生時,這兩種permission檢查都需要通過後才會將相應的intent發送給相關的目的地。
其它強制使用Permissions的方式
在調用service的過程中可以設置任意的fine-grained permissions(這里我理解的是更為細化的許可權)。這是通過Context.checkCallingPermission(String) 方法來完成的。呼叫的時候使用一個想得到的permission string,並且當該許可權獲批的時候可以返回給呼叫方一個Integer(沒有獲批也會返回一個Integer)。需要注意的是這種情況只能發生在來自另一個進程的呼叫,通常是一個service發布的IDL介面或者是其他方式提供給其他的進程。
Android提供了很多其他的方式用於檢查permissions。如果你有另一個進程的pid,你就可以通過context method Context.checkPermission(String, int, int) 去針對那個pid去檢查permission。如果你有另一個應用程序的package name,你可以直接用PackageManager method PackageManager.checkPermission(String, String) 來確定該package是否已經擁有了相應的許可權。
URI Permissions
到目前為止我們討論的標準的permission系統對於content provider來說是不夠的。一個content provider可能想保護它的讀寫許可權,而同時與它對應的直屬客戶端也需要將特定的URI傳遞給其它應用程序,以便其它應用程序對該URI進行操作。一個典型的例子就是郵件程序處理帶有附件的郵件。進入郵件需要使用permission來保護,因為這些是敏感的用戶數據。然而,如果有一個指向圖片附件的URI需要傳遞給圖片瀏覽器,那個圖片瀏覽器是不會有訪問附件的權利的,因為他不可能擁有所有的郵件的訪問許可權。
針對這個問題的解決方案就是per-URI permission: 當啟動一個activity或者給一個activity返回結果的時候,呼叫方可以設置Intent.FLAG_GRANT_READ_URI_PERMISSION 和/或 Intent.FLAG_GRANT_WRITE_URI_PERMISSION . 這會使接收該intent的activity獲取到進入該Intent指定的URI的許可權,而不論它是否有許可權進入該intent對應的content provider。
這種機制允許一個通常的capability-style模型, 這種模型是以用戶交互(如打開一個附件, 從列表中選擇一個聯系人)為驅動,特別獲取更細粒化的許可權。這是一種減少不必要許可權的重要方式,這種方式主要針對的就是那些和程序的行為直接相關的許可權。
這些URI permission的獲取需要content provider(包含那些URI)的配合。強烈推薦在content provider中提供這種能力,並通過android:grantUriPermissions 或者<grant-uri-permissions> 標簽來聲明支持。
更多的信息可以參考Context.grantUriPermission() , Context.revokeUriPermission() , and Context.checkUriPermission() methods.
轉載
B. Android中怎麼啟動關閉Service及功能解釋
啟動:
//首先注冊服務
<service
android:name="com.wangdeyu.service.MusicService"
android:exported="false" >
<intent-filter>
<action android:name="com.abc" />
</intent-filter>
</service>
//啟動服務
Intent service=new Intent(" com.abc");
startService(service);
//Service生命周期
①onCreate() 創建Service
②onStart(Intent intent, int startId) 啟動Service
③onDestroy() 銷毀Service
//關閉服務
stopService(service);
Service的生命周期方法比Activity少一些,只有onCreate, onStart, onDestroy
我們有兩種方式啟動一個Service,他們對Service生命周期的影響是不一樣的。
1 通過startService,就是上面這種
Service會經歷 onCreate --> onStart
stopService的時候直接onDestroy
如果是 調用者 直接退出而沒有調用stopService的話,Service會一直在後台運行。
下次調用者再起來仍然可以stopService。
2 通過bindService
Service只會運行onCreate, 這個時候 調用者和Service綁定在一起
調用者退出了,Srevice就會調用onUnbind-->onDestroyed
所謂綁定在一起就共存亡了。
注意:Service的onCreate的方法只會被調用一次,
就是你無論多少次的startService又 bindService,Service只被創建一次。
如果先是bind了,那麼start的時候就直接運行Service的onStart方法,
如果先是start,那麼bind的時候就直接運行onBind方法。如果你先bind上了,就stop不掉了,
只能先UnbindService, 再StopService,所以是先start還是先bind行為是有區別的。
Android中的服務和windows中的服務是類似的東西,服務一般沒有用戶操作界面,它運行於系統中不容易被用戶發覺,可以使用它開發如監控之類的程序。
服務不能自己運行,需要通過調用Context.startService()或Context.bindService()方法啟動服務。
這兩個方法都可以啟動Service,但是它們的使用場合有所不同。使用startService()方法啟用服務,調用者與服務之間沒有關連,
即使調用者退出了,服務仍然運行。使用bindService()方法啟用服務,調用者與服務綁定在了一起,調用者一旦退出,服務也就終止,大有「不求同時生,必須同時死」的特點。
如果打算採用Context.startService()方法啟動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,
接著調用onStart()方法。如果調用startService()方法前服務已經被創建,多次調用startService()方法並不會導致多次創建服務,
但會導致多次調用onStart()方法。採用startService()方法啟動的服務,只能調用Context.stopService()方法結束服務,服務結束時會調用onDestroy()方法。
如果打算採用Context.bindService()方法啟動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,
接著調用onBind()方法。這個時候調用者和服務綁定在一起,調用者退出了,系統就會先調用服務的onUnbind()方法,
接著調用onDestroy()方法。如果調用bindService()方法前服務已經被綁定,
多次調用bindService()方法並不會導致多次創建服務及綁定(也就是說onCreate()和onBind()方法並不會被多次調用)。
如果調用者希望與正在綁定的服務解除綁定,可以調用unbindService()方法,調用該方法也會導致系統調用服務的onUnbind()-->onDestroy()方法.
C. Android 服務的限制
Google官網將Android服務分為了三種,前台服務,後台服務和綁定服務:
前台服務執行一些用戶能注意到的操作。例如,音頻應用會使用前台服務來播放音頻曲目。前台服務必須顯示 通知 。即使用戶停止與應用的交互,前台服務仍會繼續運行。
後台服務執行用戶不會直接注意到的操作。例如,如果應用使用某個服務來壓縮其存儲空間,則此服務通常是後台服務。
當應用組件通過調用 bindService() 綁定到服務時,服務即處於 綁定 狀態。綁定服務會提供客戶端-伺服器介面,以便組件與服務進行交互、發送請求、接收結果,甚至是利用進程間通信 (IPC) 跨進程執行這些操作。僅當與另一個應用組件綁定時,綁定服務才會運行。多個組件可同時綁定到該服務,但全部取消綁定後,該服務即會被銷毀。
我個人理解服務可以分為兩種, 前台 和 後台 ,而 綁定 應該是被當作一種狀態,因為 前台服務 和 後台服務 都可以進行綁定。
基於這個理解,我們將限制分成了前台和後台兩個部分:
從 Android 5.0(API 級別 21)開始,如果使用隱式 Intent 調用 bindService() ,則系統會拋出異常。為確保應用的安全性,在啟動 Service 時,請始終使用顯式 Intent,且不要為服務聲明 Intent 過濾器。
在後台中運行的 Service 會消耗設備資源,這可能會降低用戶體驗。 為了緩解這一問題,系統對這些 Service 施加了一些限制。
處於前台時,應用可以自由創建和運行前台與後台 Service。
Android 8.0 開始:系統不允許後台應用創建後台 Service。否則該函數將引發一個 IllegalStateException。
Android 8.0 開始:進入後台時,在一個持續數分鍾的時間窗內,應用仍可以創建和使用 Service。 在該時間窗結束後,應用將被視為處於 空閑 狀態。 此時,系統將停止應用的後台 Service,就像應用已經調用 Service 的 Service.stopSelf() 方法一樣。
為了解除這種限制,可以使用 JobScheler 作業替換後台 Service。
在 Android 8.0 之前,創建前台 Service 的方式通常是先創建一個後台 Service,然後將該 Service 推到前台。
而在Android 8.0 之後,系統不允許後台應用創建後台 Service。
解決方案:調用 startForegroundService() ,以在前台啟動新 Service。
在系統創建 Service 後,應用有五秒的時間來調用該 Service 的 startForeground() 方法以顯示新 Service 的用戶可見通知。 如果應用在此時間限制內 未 調用 startForeground() ,則系統將停止此 Service 並聲明此應用為 ANR 。
前台服務必須顯示優先順序為 PRIORITY_LOW 或更高的 狀態欄通知 ,這有助於確保用戶知道應用正在執行的任務。如果某操作不是特別重要,因而您希望使用最低優先順序通知,則可能不適合使用服務;相反,您可以考慮使用 計劃作業 。
在 Android 9 (API 28)之後,使用前台服務必須申請 FOREGROUND_SERVICE 許可權,否則會報 SecurityException 。 這是普通許可權,因此,系統會自動為請求許可權的應用授予此許可權。
每個運行服務的應用都會給系統帶來額外負擔,從而消耗系統資源。如果應用嘗試使用低優先順序通知隱藏其服務,則可能會降低用戶正在主動交互的應用的性能。因此,如果某個應用嘗試運行擁有最低優先順序通知的服務,則系統會在抽屜式通知欄的底部調用出該應用的行為。
以 Android 12 為目標平台的應用在後台運行時無法再啟動 前台服務 。
在 Android 11 及以後,系統對前台服務何時可以訪問設備的位置、攝像頭或麥克風進行了限制。
如果您的應用以 Android 11 或更高版本為目標平台,且在前台服務中訪問攝像頭或麥克風,則必須添加 前台服務類型 camera 和 microphone 。
如果你的應用 在後台運行時啟動了某項前台服務 :
如果某服務的功能(位置、麥克風 和 相機)受到了限制,則Logcat中會列印如下語句:
D. 我在android框架層中自定義了一個service,請教一下,該在哪個文件中添加相關許可權
也是在AndroidManifest中,service注冊後寫在 <service >標簽里衫帆
application頁面application Nodes中點擊你要更改的services,右讓亂邊的permission中改也行。
比如 android.intent.action.ACTION_DATE_CHANGE 即可允許修改系坦塌檔統日期
E. Android中怎麼啟動關閉Service及功能解釋
下面根據問題,作出詳細解答:
Service不是分離開的進程,除非其他特殊情況,它不會運行在自己的進程,而是作為啟動運行它的進程的一部分。
Service不是線程,這意味著它將在主線程里勞作。
啟動service有兩種方法:
Context.startService()調用者與服務之間沒有關聯,即使調用者退出,服務仍可運行
Context.bindService() 調用者與服務綁定在一起,調用者一旦退出,服務也就終止
Service的生命周期
如果使用startService()啟動service,系統將通過傳入的Intent在底層搜索相關符合Intent裡面信息的service。如果服務沒有啟動則先運行onCreate,然後運行onStartCommand (可在裡面處理啟動時傳過來的Intent和其他參數),直到明顯調用stopService或者stopSelf才將停止Service。無論運行startService多少次,只要調用一次stopService或者stopSelf,Service都會停止。使用stopSelf(int)方法可以保證在處理好intent後再停止。
控制service運行的主要方式有兩種,主要是根據onStartCommand方法返回的數值。方法:
START_STICKY
START_NOT_STICKY or START_REDELIVER_INTENT
這里主要解釋這三個變數的意義:
START_STICKY
在運行onStartCommand後service進程被kill後,那將保留在開始狀態,但是不保留那些傳入的intent。不久後service就會再次嘗試重新創建,因為保留在開始狀態,在創建 service後將保證調用onstartCommand。如果沒有傳遞任何開始命令給service,那將獲取到null的intent
START_NOT_STICKY
在運行onStartCommand後service進程被kill後,並且沒有新的intent傳遞給它。Service將移出開始狀態,並且直到新的明顯的方法(startService)調用才重新創建。因為如果沒有傳遞任何未決定的intent那麼service是不會啟動,也就是期間onstartCommand不會接收到任何null的intent。
START_REDELIVER_INTENT
在運行onStartCommand後service進程被kill後,系統將會再次啟動service,並傳入最後一個intent給onstartCommand。直到調用stopSelf(int)才停止傳遞intent。如果在被kill後還有未處理好的intent,那被kill後服務還是會自動啟動。因此onstartCommand不會接收到任何null的intent。
客戶端也可以使用bindService來保持跟service持久關聯。謹記:如果使用這種方法,那麼將不會調用onstartCommand(跟startService不一樣,下面例子注釋也有解析,大家可試試)。客戶端將會在onBind回調中接收到IBinder介面返回的對象。通常IBinder作為一個復雜的介面通常是返回aidl數據。
Service也可以混合start和bind一起使用。
要運行service,首先必須在AndroidManifest.xml里申明<service>標簽。
Service能夠保護個人的IPC調用,所以在執行實現該調用時前先使用checkCallingPermission(String) 方法檢查是否有這個許可權。
進程生命周期
當service運行在低內存的環境時,將會kill掉一下存在的進程。因此進程的優先順序將會很重要:
如果service當前正在執行onCreate、onStartCommand、onDestroy方法,主進程將會成為前台進程來保證代碼可以執行完成避免被kill
如果service已經啟動了,那麼主進程將會比其他可見的進程的重要性低,但比其他看不見的進程高。因為只有少部分進程始終是用戶可見的,因此除非在極度低內存的時候,不然 service是不會被kill的。
如果有客戶端關聯到service,那麼service永遠比客戶端重要。也就是說客戶端可見,那麼service也可見(我理解這里的可見並不是可以看到,而是重要性,因為可見往往就表示重要性高)。
Service可以使用startForeground API將service放到前台狀態。這樣在低內存時被kill的幾率更低,但是文檔後面又寫了,如果在極度極度低內存的壓力下,該service理論上還是會被kill掉。但這個情況基本不用考慮。
當然如果service怎麼保持還是被kill了,那你可以通過重寫onStartCommand返回變數來設置它的啟動方式。比如:START_STICKY、START_REDELIVER_INTENT等等,前面已經討論了它們的作用,這里就不再累贅了
另外:
service 的onCreate和onStartCommand 是運行在主線程的,所以如果裡面有處理耗時間的任務。兩種處理:
請將它們都挪到新的線程里。
用系統提供的IntentService,它繼承了Service,它處理數據是用自身新開的線程。
F. android調用webservice怎麼授權
具體調用調用webservice的方法為:
(1) 指定webservice的命名空間和調用的方法名,如:
SoapObject request =new SoapObject(http://service,」getName」);
SoapObject類的第一個參數表示WebService的命名空間,可以從WSDL文檔中找到WebService的命名空間。第二個參數表示要調用的WebService方法名。
(2) 設置調用方法的參數值,如果沒有參數,可以省略,設置方法的參數值的代碼如下:
Request.addProperty(「param1」,」value」);
Request.addProperty(「param2」,」value」);
要注意的是,addProperty方法的第1個參數雖然表示調用方法的參數名,但該參數值並不一定與服務端的WebService類中的方法參數名一致,只要設置參數的順序一致即可。
(3) 生成調用Webservice方法的SOAP請求信息。該信息由SoapSerializationEnvelope對象描述,代碼為:
SoapSerializationEnvelope envelope=new
SoapSerializationEnvelope(SoapEnvelope.VER11);
Envelope.bodyOut = request;
創建SoapSerializationEnvelope對象時需要通過SoapSerializationEnvelope類的構造方法設置SOAP協議的版本號。該版本號需要根據服務端WebService的版本號設置。在創建SoapSerializationEnvelope對象後,不要忘了設置SOAPSoapSerializationEnvelope類的bodyOut屬性,該屬性的值就是在第一步創建的SoapObject對象。
(4) 創建HttpTransportsSE對象。通過HttpTransportsSE類的構造方法可以指定WebService的WSDL文檔的URL:
HttpTransportSE ht=new HttpTransportSE(「http://192.168.18.17:80
/axis2/service/SearchNewsService?wsdl」);
(5)使用call方法調用WebService方法,代碼:
ht.call(null,envelope);
Call方法的第一個參數一般為null,第2個參數就是在第3步創建的SoapSerializationEnvelope對象。
(6)使用getResponse方法獲得WebService方法的返回結果,代碼:
SoapObject soapObject =( SoapObject) envelope.getResponse();
G. Android應用程序怎樣獲取root許可權
一般來說, Android 下的應用程序可以「直接」得到的最大的許可權為 system ,但是如果我們需要在程序中執行某些需要 root 許可權的命令,如 ifconfig 等,就需要 root 許可權了。按照 Simon 的文章中提到的,應用程序有以下兩種辦法臨時獲得 root 許可權:
1) 實現一個 init 實現一個 Service ,來幫助 Android 應用程序執行 root 許可權的命令。
2) 實現一個虛擬設備,這個設備幫助 Android 應用程序執行 root 許可權的命令。
第二種辦法我這里沒有嘗試,暫時也不會。這里講講我在實現第一種辦法的過程和遇到的一些問題。
1. 將我們要執行的命令寫成腳本,或者可執行程序。
下面是我的腳本 ifconfig_test.sh :
# ! /system/bin/sh
ifconfig
注意: 腳本的第一行必須為 # ! /system/bin/sh ,否則無法執行,通過 dmesg 可以查看到信息內容為 cannot execve ./ifconfig_test.sh: Exec format error
也可以採用 C/C++ 編寫需要執行的命令或者程序,並在編譯 image 的時候編譯成可執行程序。
2. 在 init.rc 中注冊 service
Android 中的 service 需要在 init.rc 中注冊, Init.rc 中定義的 Service 將會被 init 進程創建,這樣將可以獲得 root 許可權。當得到相應的通知(通過屬性設置)後, init 進程會啟動該 service 。
本文中注冊的內容如下:
service ifconfig_test /system/etc/ifconfig_test.sh
oneshot
disabled
其中, oneshot 表示程序退出後不再重新啟動, disabled 表示不在系統啟動時啟動。
注意: 這里 service name 不能超過 16 個字元。我之前的 service name 由於定義的比較長, 18 個字元,設置屬性通知 service 啟動後查看 dmesg 可以看到提示: init: no such service 。查看 /system/core/init/parser.c 的源代碼,在 parse_service->valid_name 函數中可以看到如下內容: if (strlen(name) > 16) { return 0; } ,證明 service 的名字的確不能超過 16 個字元。
3. 將 Android 應用程序提升為 system 許可權
既然應用程序可以通過啟動 service 獲得 root 許可權,那麼豈不是很不安全。 Android 考慮到了這點,規定只有 system 許可權的應用程序才能設置屬性,通知 service 啟動。關於提升 system 許可權的文章網上已有很多,這里就不再細說,
4. 在應用程序中添加屬性設置代碼
前面已經提到,對於 Android 來說,應用程序通知 init 啟動 service 是通過設置系統屬性來完成的,具體為設置 System 系統屬性 「ctl.start」 為 「ifconfig_test」 ,這樣 Android 系統將會幫我們運行 ifconfig_test 這個 service 了。
對該系統屬性的設置有三種方法,分別對應三種不同的應用程序:
1) Java 代碼
Android 在 Java 庫中提供 System.getProperty 和 System.setProperty 方法, Java 程序可以通過他們來設置和獲得屬性。代碼如下:
SystemProperties.set("ctl.start", "ifconfig_test");
上面的代碼是通知 Android 執行 ifconfig_test service ,如果需要查詢當前 service 執行的狀態,如是否執行完畢,可以通過如下代碼查詢:
ret = SystemProperties.get("init.svc. ifconfig_test ", "");
if(ret != null && ret.equals("stopped"))
{
return true;
}
2) JNI 代碼
當編寫 NDK 的程序時,可以使用 property_get 和 property_set 這兩個 API 來獲得和設置屬性。使用這兩個 API 必須要包含頭文件 cutils/properties.h 和鏈接 libcutil 庫。
3) Shell 腳本
Android 提供了命令行 setprop 和 getprop 來設置和獲取屬性,他們可以在腳本中被使用。
由於我的程序是在 JNI 中調用腳本,腳本中又執行 ifconfig ,因此我將設置屬性的部分放在了腳本中完成,代碼如下:
setprop ctl.start ifconfig_test
#wait for the service until it stops
ret=1
while [ $ret -ne 0 ]
do
getprop | grep "$ENABLE_MAPPER_SRV" | grep stopped
ret=$?
done
通過上面 4 個步驟, Android 應用程序就獲得了 root 許可權,更具體的說,是在執行我們需要執行的命令時臨時獲得了 root 許可權。