Android系统服务
概述
本篇博文主要介紹的是Android中的Java服務(wù)。
這部分服務(wù)大部分都有一個Manager類,其實(shí)就是一個RPC調(diào)用,用戶通過調(diào)用xxxManager的方法,實(shí)際上被Binder給遷移到system_server進(jìn)程中對應(yīng)的xxxManagerService中對應(yīng)的方法,并將結(jié)果再通過binder帶回。
常用的有如下幾個:
PowerManagerService –> PowerManager
| PowerManagerService –> PowerManager | Android 的電源管理 |
| ActivityManagerService->ActivityManager | 整個Android framework框架中最為核心的一個服務(wù),管理整個框架中任務(wù)、進(jìn)程管理, Intent解析等的核心實(shí)現(xiàn)。雖然名為Activity的Manager Service,但它管轄的范圍,不只是Activity,還有其他三大組件,和它們所在的進(jìn)程。也就是說用戶應(yīng)用程序的生命管理,都是由他負(fù)責(zé)的。 |
| TelephonyRegistry->TelephonyManager | 電話注冊、管理服務(wù)模塊,可以獲取電話的鏈接狀態(tài)、信號強(qiáng)度等等 |
| PackageManagerService -> PackageManager | 包括對軟件包的解包,驗(yàn)證,安裝以及升級等等,對于我們現(xiàn)在不能安裝.so文件的問題,應(yīng)該先從這塊著手分析原因。 |
| AccountManagerService -> AccountManager | 提供賬戶、密碼和authtoken管理設(shè)備上的賬戶 |
| ContentService -> ContentResolver | 內(nèi)容服務(wù),主要是數(shù)據(jù)庫等提供解決方法的服務(wù)。 |
| BatteryService | 監(jiān)控電池充電及狀態(tài)的服務(wù),當(dāng)狀態(tài)改變時,會廣播Intent |
| WindowManagerService -> WindowManager -> PhoneWindowManager | 和ActivityManagerService高度粘合窗口管理,這里最核心的就是輸入事件的分發(fā)和管理。 |
| AlarmManagerService -> AlarmManager | 鬧鐘服務(wù)程序 |
| BluetoothService -> BluetoothDevice | 藍(lán)牙的后臺管理和服務(wù)程序 |
| ClipboardService -> ClipboardManager | 和其他系統(tǒng)的clipBoard服務(wù)類似,提供復(fù)制黏貼功過。 |
| InputMethodManagerService -> InputMethodManager | 輸入法的管理服務(wù)程序,包括何時使能輸入法,切換輸入法等等。 |
| NetStatService | 手機(jī)網(wǎng)絡(luò)服務(wù) |
| ConnectivityService -> ConnectivityManager | 網(wǎng)絡(luò)連接狀態(tài)服務(wù),可供其他應(yīng)用查詢,當(dāng)網(wǎng)絡(luò)狀態(tài)變化時,也可廣播改變。 |
| NotificationManagerService -> NotificationManager | 負(fù)責(zé)管理和通知后臺事件的發(fā)生等,這個和statusbar膠黏在一起,一般會在statusbar上添加響應(yīng)圖標(biāo)。用戶可以通過這知道系統(tǒng)后臺發(fā)生了什么 |
| WallpaperManagerService -> WallpaperManager | 管理桌面背景的服務(wù),深度定制化桌面系統(tǒng) |
| AppWidgetService -> AppWidgetManager | Android可以讓用戶寫的程序以widget的方式放在桌面上,這就是這套管理和服務(wù)的接口 |
| AudioService -> AudioManager | AudioFlinger的上層管理封裝,主要是音量、音效、聲道及鈴聲等的管理 |
TelephonyManager(電話管理器)
官方API
TelecomManager
獲得TelephonyManager的服務(wù)對象
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);示例
調(diào)用撥號器撥打電話號碼
Uri uri=Uri.parse("tel:"+電話號碼); Intent intent=new Intent(Intent.ACTION_DIAL,uri); startActivity(intent);獲取Sim卡信息與網(wǎng)絡(luò)信息
public class MainActivity extends AppCompatActivity {private TextView tv_phone1;private TextView tv_phone2;private TextView tv_phone3;private TextView tv_phone4;private TextView tv_phone5;private TextView tv_phone6;private TextView tv_phone7;private TextView tv_phone8;private TextView tv_phone9;private TelephonyManager tManager;private String[] phoneType = {"未知","2G","3G","4G"};private String[] simState = {"狀態(tài)未知","無SIM卡","被PIN加鎖","被PUK加鎖","被NetWork PIN加鎖","已準(zhǔn)備好"};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//①獲得系統(tǒng)提供的TelphonyManager對象的實(shí)例tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);bindViews();}private void bindViews() {tv_phone1 = (TextView) findViewById(R.id.tv_phone1);tv_phone2 = (TextView) findViewById(R.id.tv_phone2);tv_phone3 = (TextView) findViewById(R.id.tv_phone3);tv_phone4 = (TextView) findViewById(R.id.tv_phone4);tv_phone5 = (TextView) findViewById(R.id.tv_phone5);tv_phone6 = (TextView) findViewById(R.id.tv_phone6);tv_phone7 = (TextView) findViewById(R.id.tv_phone7);tv_phone8 = (TextView) findViewById(R.id.tv_phone8);tv_phone9 = (TextView) findViewById(R.id.tv_phone9);tv_phone1.setText("設(shè)備編號:" + tManager.getDeviceId());tv_phone2.setText("軟件版本:" + (tManager.getDeviceSoftwareVersion()!= null?tManager.getDeviceSoftwareVersion():"未知"));tv_phone3.setText("運(yùn)營商代號:" + tManager.getNetworkOperator());tv_phone4.setText("運(yùn)營商名稱:" + tManager.getNetworkOperatorName());tv_phone5.setText("網(wǎng)絡(luò)類型:" + phoneType[tManager.getPhoneType()]);tv_phone6.setText("設(shè)備當(dāng)前位置:" + (tManager.getCellLocation() != null ? tManager.getCellLocation().toString() : "未知位置"));tv_phone7.setText("SIM卡的國別:" + tManager.getSimCountryIso());tv_phone8.setText("SIM卡序列號:" + tManager.getSimSerialNumber());tv_phone9.setText("SIM卡狀態(tài):" + simState[tManager.getSimState()]);} }訪問以上API,記得清單文件添加權(quán)限
<!-- 添加訪問手機(jī)位置的權(quán)限 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <!-- 添加訪問手機(jī)狀態(tài)的權(quán)限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>獲取手機(jī)的信號強(qiáng)度
網(wǎng)絡(luò)信號強(qiáng)度的單位是dBm(毫瓦分貝),一般用負(fù)數(shù)表示,正常手機(jī)信號變化范圍是從-110dBm (差)到-50dBm(好)之間,如果你比-50dBm還小的話,說明你就站在基站的附近。
另外2G,3G,4G獲得信號強(qiáng)度的方式都是重寫PhoneStateListener的onSignalStrengthsChanged() 方法,當(dāng)信號強(qiáng)度發(fā)生改變的時候就會觸發(fā)這個事件,我們可以在這個事件里獲取信號強(qiáng)度!
手機(jī)獲取信號強(qiáng)度代碼示例:
dBm =-113+2*asu這是一個固定公式,asu(獨(dú)立信號單元)
getEvdoDbm():電信3G
getCdmaDbm():聯(lián)通3G
getLteDbm():4G
監(jiān)聽手機(jī)的所有來電
詳見本人另外一篇博客來去電攔截
黑名單來電自動掛斷
詳見本人另外一篇博客AIDL與來去電自動掛斷
SmsManager(短信管理器)
官方API
不建議使用 android.telephony.gsm.SmsManager這個類
This class was deprecated in API level 4. Replaced by android.telephony.SmsManager that supports both GSM and CDMA.建議使用 android.telephony.SmsManager
SmsManager
調(diào)用系統(tǒng)發(fā)送短信功能
這樣發(fā)短信,app安裝的時候就可以少寫一條發(fā)短信的權(quán)限
核心代碼
public void SendSMSTo(String phoneNumber,String message){ //判斷輸入的phoneNumber是否為合法電話號碼 if(PhoneNumberUtils.isGlobalPhoneNumber(phoneNumber)){ //Uri.parse("smsto") 這里是轉(zhuǎn)換為指定Uri,固定寫法 Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:"+phoneNumber)); intent.putExtra("sms_body", message); startActivity(intent); } }調(diào)用系統(tǒng)提供的短信接口發(fā)送短信
這個就需要發(fā)短信的權(quán)限啦
uses-permission android:name="android.permission.SEND_SMS"/>我們直接調(diào)用SmsManager為我們提供的短信接口發(fā)送短信:
sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliverIntent);參數(shù)依次是:
- destinationAddress:收信人的電話號碼
- scAddress:短信中心的號碼,null的話使用當(dāng)前默認(rèn)的短信服務(wù)中心
- text:短信內(nèi)容
- sentIntent:短信發(fā)送狀態(tài)的信息:(發(fā)送狀態(tài)的Intent) 如果不為null,當(dāng)消息成功發(fā)送或失敗這個PendingIntent就廣播。結(jié)果代碼是Activity.RESULT_OK 表示成功,或RESULT_ERROR_GENERIC_FAILURE、RESULT_ERROR_RADIO_OFF、RESULT_ERROR_NULL_PDU 之一表示錯誤。對應(yīng)RESULT_ERROR_GENERIC_FAILURE,sentIntent可能包括額外的”錯誤代碼”包含一 個無線電廣播技術(shù)特定的值,通常只在修復(fù)故障時有用。每一個基于SMS的應(yīng)用程序控制檢測sentIntent。 如果sentIntent是空,調(diào)用者將檢測所有未知的應(yīng)用程序,這將導(dǎo)致在檢測的時候發(fā)送較小數(shù)量的SMS。
- deliverIntent:短信是否被對方收到的狀態(tài)信息:(接收狀態(tài)的Intent) 如果不為null,當(dāng)這個短信發(fā)送到接收者那里,這個PendtingIntent會被廣播, 狀態(tài)報告生成的pdu(指對等層次之間傳遞的數(shù)據(jù)單位)會拓展到數(shù)據(jù)(”pdu”)
核心代碼
public void sendSMS(String phoneNumber,String message){ //獲取短信管理器 android.telephony.SmsManager smsManager = android.telephony.SmsManager.getDefault(); //拆分短信內(nèi)容(手機(jī)短信長度限制),貌似長度限制為140個字符,就是//只能發(fā)送70個漢字,多了要拆分成多條短信發(fā)送//第四五個參數(shù),如果沒有需要監(jiān)聽發(fā)送狀態(tài)與接收狀態(tài)的話可以寫null List<String> divideContents = smsManager.divideMessage(message); for (String text : divideContents) { smsManager.sendTextMessage(phoneNumber, null, text, sentPI, deliverPI); } }可能你還需要監(jiān)聽短信是否發(fā)送成功,或者收信人是否接收到信息,就把下面的加上吧:
處理返回發(fā)送狀態(tài)的sentIntent:
//處理返回的發(fā)送狀態(tài) String SENT_SMS_ACTION = "SENT_SMS_ACTION"; Intent sentIntent = new Intent(SENT_SMS_ACTION); PendingIntent sentPI = PendingIntent.getBroadcast(context, 0, sentIntent, 0); //注冊發(fā)送信息的廣播接收者 context.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context _context, Intent _intent) { switch (getResultCode()) { case Activity.RESULT_OK:Toast.makeText(context, "短信發(fā)送成功", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: //普通錯誤break;case SmsManager.RESULT_ERROR_RADIO_OFF: //無線廣播被明確地關(guān)閉break; case SmsManager.RESULT_ERROR_NULL_PDU: //沒有提供pdubreak; case SmsManager.RESULT_ERROR_NO_SERVICE: //服務(wù)當(dāng)前不可用break; } } }, new IntentFilter(SENT_SMS_ACTION));處理返回接收狀態(tài)的deliverIntent:
//處理返回的接收狀態(tài) String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION"; //創(chuàng)建接收返回的接收狀態(tài)的Intent Intent deliverIntent = new Intent(DELIVERED_SMS_ACTION); PendingIntent deliverPI = PendingIntent.getBroadcast(context, 0,deliverIntent, 0); context.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context _context, Intent _intent) { Toast.makeText(context,"收信人已經(jīng)成功接收", Toast.LENGTH_SHORT).show(); } }, new IntentFilter(DELIVERED_SMS_ACTION));AudioManager(音頻管理器)
官方API
AudioManager
獲得AudioManager對象實(shí)例
AudioManager audiomanage = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);常用方法
示例
簡單的示例:使用Mediaplayer播放音樂,通過AudioManager調(diào)節(jié)音量大小與靜音!
對了,先在res下創(chuàng)建一個raw的文件夾,往里面丟一個MP3資源文件!
設(shè)置靜音的方法setStreamMute()在API 23版本過期, 可以使用另一個方法adjustStreamVolume(int, int, int),然后第三個屬性設(shè)置:
ADJUST_MUTE 或 ADJUST_UNMUTE!
對了,還有:
如果adjustStreamVolume()的第三個參數(shù)你設(shè)置了振動(Vibrator), 需要在AndroidManifest.xml中添加這個權(quán)限!
<uses-permission android:name=”android.permission.VIBRATE”/>
Vibrator(振動器)
官方API
Vibrator
獲得Vibrator實(shí)例:
Vibrator vb = (Vibrator)getSystemService(Service.VIBRATOR_SERVICE);相關(guān)方法:
- abstract void cancel():關(guān)閉或者停止振動器
- abstract boolean hasVibrator():判斷硬件是否有振動器
- void vibrate(long milliseconds):控制手機(jī)振動為milliseconds毫秒
- void vibrate(long[] pattern,int repeat):指定手機(jī)以pattern指定的模式振動! 比如:pattern為new int[200,400,600,800],就是讓他在200,400,600,800這個時間交替啟動與關(guān)閉振動器! 而第二個則是重復(fù)次數(shù),如果是-1的只振動一次,如果是0的話則一直振動 還有其他兩個方法用得不多~ 對了,使用振動器還需要在AndroidManifest.xml中添加下述權(quán)限: <uses-permission android:name="android.permission.VIBRATE"/>
示例:設(shè)置頻率不同的震動器
對于Vibrator用的最廣泛的莫過于所謂的手機(jī)按摩器類的app
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn_hasVibrator"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="判斷是否有振動器" /><Buttonandroid:id="@+id/btn_short"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="短振動" /><Buttonandroid:id="@+id/btn_long"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="長振動" /><Buttonandroid:id="@+id/btn_rhythm"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="節(jié)奏振動" /><Buttonandroid:id="@+id/btn_cancle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="取消振動" /> </LinearLayout> public class MainActivity extends AppCompatActivity implements View.OnClickListener {private Button btn_hasVibrator;private Button btn_short;private Button btn_long;private Button btn_rhythm;private Button btn_cancle;private Vibrator myVibrator;private Context mContext;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//獲得系統(tǒng)的Vibrator實(shí)例:myVibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);mContext = MainActivity.this;bindViews();}private void bindViews() {btn_hasVibrator = (Button) findViewById(R.id.btn_hasVibrator);btn_short = (Button) findViewById(R.id.btn_short);btn_long = (Button) findViewById(R.id.btn_long);btn_rhythm = (Button) findViewById(R.id.btn_rhythm);btn_cancle = (Button) findViewById(R.id.btn_cancle);btn_hasVibrator.setOnClickListener(this);btn_short.setOnClickListener(this);btn_long.setOnClickListener(this);btn_rhythm.setOnClickListener(this);btn_cancle.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_hasVibrator:Toast.makeText(mContext, myVibrator.hasVibrator() ? "當(dāng)前設(shè)備有振動器" : "當(dāng)前設(shè)備無振動器",Toast.LENGTH_SHORT).show();break;case R.id.btn_short:myVibrator.cancel();myVibrator.vibrate(new long[]{100, 200, 100, 200}, 0);Toast.makeText(mContext, "短振動", Toast.LENGTH_SHORT).show();break;case R.id.btn_long:myVibrator.cancel();myVibrator.vibrate(new long[]{100, 100, 100, 1000}, 0);Toast.makeText(mContext, "長振動", Toast.LENGTH_SHORT).show();break;case R.id.btn_rhythm:myVibrator.cancel();myVibrator.vibrate(new long[]{500, 100, 500, 100, 500, 100}, 0);Toast.makeText(mContext, "節(jié)奏振動", Toast.LENGTH_SHORT).show();break;case R.id.btn_cancle:myVibrator.cancel();Toast.makeText(mContext, "取消振動", Toast.LENGTH_SHORT).show();}} }清單文件權(quán)限
<uses-permission android:name="android.permission.VIBRATE"/>AlarmManager(鬧鐘服務(wù))
官方API
AlarmManager
相關(guān)方法
關(guān)鍵參數(shù)說明:
示例:一個簡單的定時任務(wù)
要說的是,此例子只在Android 4.4以下的系統(tǒng)可行,5.0以上并不可行,后續(xù)如果有5.0 以上AlarmManager的解決方案,到時再補(bǔ)上!另外,這里用set方法可能有點(diǎn)不準(zhǔn),如果要 更精確的話可以使用setExtra()方法來設(shè)置AlarmManager!
首先一個簡單的布局文件:activity_main.xml,另外在res創(chuàng)建一個raw文件夾,把音頻文件丟進(jìn)去! 另外創(chuàng)建一個只有外層布局的activity_clock.xml作為鬧鐘響時Activity的布局!
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/LinearLayout1"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn_set"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="設(shè)置鬧鐘" /><Buttonandroid:id="@+id/btn_cancel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="關(guān)閉鬧鐘"android:visibility="gone" /></LinearLayout> public class MainActivity extends AppCompatActivity implements View.OnClickListener{private Button btn_set;private Button btn_cancel;private AlarmManager alarmManager;private PendingIntent pi;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bindViews();}private void bindViews() {btn_set = (Button) findViewById(R.id.btn_set);btn_cancel = (Button) findViewById(R.id.btn_cancel);alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);Intent intent = new Intent(MainActivity.this, ClockActivity.class);pi = PendingIntent.getActivity(MainActivity.this, 0, intent, 0);btn_set.setOnClickListener(this);btn_cancel.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.btn_set:Calendar currentTime = Calendar.getInstance();new TimePickerDialog(MainActivity.this, 0,new TimePickerDialog.OnTimeSetListener() {@Overridepublic void onTimeSet(TimePicker view,int hourOfDay, int minute) {//設(shè)置當(dāng)前時間Calendar c = Calendar.getInstance();c.setTimeInMillis(System.currentTimeMillis());// 根據(jù)用戶選擇的時間來設(shè)置Calendar對象c.set(Calendar.HOUR, hourOfDay);c.set(Calendar.MINUTE, minute);// ②設(shè)置AlarmManager在Calendar對應(yīng)的時間啟動ActivityalarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pi);Log.e("HEHE",c.getTimeInMillis()+""); //這里的時間是一個unix時間戳// 提示鬧鐘設(shè)置完畢:Toast.makeText(MainActivity.this, "鬧鐘設(shè)置完畢~"+ c.getTimeInMillis(),Toast.LENGTH_SHORT).show();}}, currentTime.get(Calendar.HOUR_OF_DAY), currentTime.get(Calendar.MINUTE), false).show();btn_cancel.setVisibility(View.VISIBLE);break;case R.id.btn_cancel:alarmManager.cancel(pi);btn_cancel.setVisibility(View.GONE);Toast.makeText(MainActivity.this, "鬧鐘已取消", Toast.LENGTH_SHORT).show();break;}} }鬧鈴頁面的ClockActivity.java
public class ClockActivity extends AppCompatActivity {private MediaPlayer mediaPlayer;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_clock);mediaPlayer = mediaPlayer.create(this,R.raw.pig);mediaPlayer.start();//創(chuàng)建一個鬧鐘提醒的對話框,點(diǎn)擊確定關(guān)閉鈴聲與頁面new AlertDialog.Builder(ClockActivity.this).setTitle("鬧鐘").setMessage("小豬小豬快起床~").setPositiveButton("關(guān)閉鬧鈴", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {mediaPlayer.stop();ClockActivity.this.finish();}}).show();} }核心流程
- AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 獲得系統(tǒng)提供的AlarmManager服務(wù)的對象
- Intent設(shè)置要啟動的組件: Intent intent = new Intent(MainActivity.this, ClockActivity.class);
- PendingIntent對象設(shè)置動作,啟動的是Activity還是Service,又或者是廣播! PendingIntent pi = =PendingIntent.getActivity(MainActivity.this, 0, intent, 0);
- 調(diào)用AlarmManager的set( )方法設(shè)置單次鬧鐘的鬧鐘類型,啟動時間以及PendingIntent對象! alarmManager.set(AlarmManager.RTC_WAKEUP,c.getTimeInMillis(), pi);
另外假如出現(xiàn)鬧鈴無效的話,你可以從這些方面入手:
1.系統(tǒng)版本或者手機(jī),5.0以上基本沒戲,小米,自行百度吧~ 2.ClockActivity有注冊沒?
3.假如你用的是alarmManager發(fā)送廣播,廣播再激活A(yù)ctivity的話,則需要為Intent設(shè)置一個flag: i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
4. PendingIntent,要寫成getActivity啟動鬧鈴頁面
PowerManager(電源服務(wù))
powermanager
WindowManager(窗口管理服務(wù))
windowmanager
LayoutInflater(布局服務(wù))
layoutinflater
WallpaperManager(壁紙管理器)
wallpapermanager
總結(jié)
以上是生活随笔為你收集整理的Android系统服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebView完全解读
- 下一篇: Android5.0新特性-Materi