編輯:關於Android編程
Service簡介
跨進程調用Service(AIDL服務)
電話管理器
短信管理器
Service簡介
Service是Android四大組件中與Activity最相似的組件,它們都代表可執行的程序。Service與Activity的區別在於: Service一直在後台運行,它沒有用戶界面,一旦Service被啟動起來之後,它與Activity一樣,也具有自己的生命周期。
Service組件也是可執行程序,它也有自己的生命周期。創建、配置Service與創建配置Activity的過程基本相似,下面介紹Service的開發過程。
1.1 開發Service
開發Service的步驟如下:
定義一個繼承Service的子類。
在AndroidManifest.xml文件中配置該Service。
與Activity相似的是, Service中也定義了一系列生命周期的方法,如下所示:
onStartCommand():每當客戶端調用startService(Intent)方法啟動該Service時都會回調該方法。
IBinder onBind(Intent intent):該方法是Service子類必須實現的方法,通過返回的IBinder對象,與其他Service進行通信。
onCreate():當該Service第一次被創建時回調該方法。
onDestroy():當該Service被關閉之前將會回調該方法。
onUnbind():當Service上綁定的所有客戶端都斷開連接時將會回調該方法。
配置Service使用
Android系統中, Service不能夠自己運行,需要通過一個Activity或者其他Context對象來調用,啟動Service有兩種方法:
通過Context的startService()方法:通過該方法啟動Service,訪問者與Service之間沒有關聯,即使訪問者退出了, Service仍在運行。
通過Context的bindService()方法:通過該方法啟動Service,訪問者與Service綁在了一起,訪問者一旦退出, Service也就終止。
例:Service使用:
MainActivity.java
public class MainActivity extends Activity
{
Button start , stop;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 獲取程序界面中的start、stop兩個按鈕
start = (Button) findViewById(R.id.start);
stop = (Button) findViewById(R.id.stop);
//創建啟動Service的Intent
final Intent intent = new Intent();
//為Intent設置Action屬性
intent.setAction(com.boby.service.FIRST_SERVICE);
start.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
//啟動指定Serivce
startService(intent);
}
});
stop.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
//停止指定Serivce
stopService(intent);
}
});
}
}
在配置文件中配置Service:
1.2 綁定本地Service並與之通信
當程序通過startService()和stopService()啟動、關閉Service時,Service與訪問者之間基本上不存在太多關聯,因此Service和訪問者之間也無法進行通信、數據交換。
如果要Service和訪問者交換數據需要進行方法調用或者數據交換。則應該使用bindService()和unbindService()啟動和關閉服務。
通過Context的bindService(Intent service,ServiceConnection conn, int flags),當訪問者與Service之間連接成功時將回調該ServiceConnection對象的onSerciceConnected(ComponentName name,IBinder service)方法,當訪問者與Service之間斷開連接時將回調ServiceConnection的onSerciceDisconnected(ComponentName name)方法。
當開發Service類時,該Service類必須提供一個IBinder onBind(Intent intent)方法,在綁定本地Service的情況下,onBind(Intent intent)方法返回的IBinder對象將會傳遞給onSerciceConnected(ComponentName name,IBinder service)方法中的service參數,這樣訪問者就可以通過該IBinder對象與Service進行通信。
例:Activity綁定本地Service:
MainActivity.java
public class MainActivity extends Activity
{
Button bind , unbind , getServiceStatus;
// 保持所啟動的Service的IBinder對象
BindService.MyBinder binder;
// 定義一個ServiceConnection對象
private ServiceConnection conn = new ServiceConnection()
{
// 當該Activity與Service連接成功時回調該方法
@Override
public void onServiceConnected(ComponentName name
, IBinder service)
{
System.out.println(--Service Connected--);
// 獲取Service的onBind方法所返回的MyBinder對象
binder = (BindService.MyBinder) service;
}
// 當該Activity與Service斷開連接時回調該方法
@Override
public void onServiceDisconnected(ComponentName name)
{
System.out.println(--Service Disconnected--);
}
};
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 獲取程序界面中的start、stop、getServiceStatus按鈕
bind = (Button) findViewById(R.id.bind);
unbind = (Button) findViewById(R.id.unbind);
getServiceStatus = (Button) findViewById(R.id.getServiceStatus);
//創建啟動Service的Intent
final Intent intent = new Intent();
//為Intent設置Action屬性
intent.setAction(com.boby.service.BIND_SERVICE);
bind.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
//綁定指定Serivce
bindService(intent , conn , Service.BIND_AUTO_CREATE);
}
});
unbind.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
//解除綁定Serivce
unbindService(conn);
}
});
getServiceStatus.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
// 獲取、並顯示Service的count值
Toast.makeText(MainActivity.this
, Serivce的count值為: + binder.getCount()
, 4000)
.show();
}
});
}
}
在配置文件中配置Service:
1.3 Service的生命周期
應用程序中啟動Service的方式不同, Service的生命周期也略有差異。
跨進程調用Service(AIDL服務)
2.1 AIDL服務簡介
跨進程訪問(AIDL服務)Android系統中的進程之間不能共享內存,因此,需要提供一些機制在不同進程之間進行數據通信。
為了使其他的應用程序也可以訪問本應用程序提供的服務,Android使用一種接口定義語言(Interface Definition Language,IDL)來公開服務的接口。因此,可以將這種可以跨進程訪問的服務稱為AIDL(Android Interface Definition Language)服務。
Android的遠程Service調用,需要先定義一個遠程調用的接口,然後提供該接口的實現類。
客戶端訪問本地Service時, Service只是將一個回調對象(IBinder對象)通過onBind()方法返回給客戶端。遠程Service的onBind()方法只是將IBinder對象的代理傳給客戶端的ServiceConnection的onServiceConnected方法的第二個參數。當客戶端獲取了遠程Service的IBinder對象的代理後,就可以通過該IBinder對象去回調遠程Service的屬性或方法了。
2.2 建立AIDL服務的步驟
建立AIDL服務要比建立普通的服務復雜一些,具體步驟如下:
(1)在Eclipse Android工程的Java包目錄中建立一個擴展名為aidl的文件。該文件的語法類似於Java代碼,但會稍有不同。
(2)如果aidl文件的內容是正確的,ADT會自動生成一個Java接口文件(*.java)。
(3)建立一個服務類(Service的子類)。
(4)實現由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服務,尤其要注意的是,標簽中android:name的屬性值就是客戶端要引用該服務的ID,也就是Intent類的參數值。
2.3 將數據暴露給客戶端
上一步定義好一個AIDL接口之後,接下來定義一個Service的實現類,該Service的onBind()方法所返回的IBinder對象應該是ADT所生成的ICat.Stub的子類的實例。
AndroidManifest.xml
例:跨進程調用Service:
AidlService.java
public class AidlService extends Service
{
private CatBinder catBinder;
Timer timer = new Timer();
String[] colors = new String[]{
紅色,
黃色,
黑色
};
double[] weights = new double[]{
2.3,
3.1,
1.58
};
private String color;
private double weight;
// 繼承Stub,也就是實現額ICat接口,並實現了IBinder接口
public class CatBinder extends Stub
{
@Override
public String getColor() throws RemoteException
{
return color;
}
@Override
public double getWeight() throws RemoteException
{
return weight;
}
}
@Override
public void onCreate()
{
super.onCreate();
catBinder = new CatBinder();
timer.schedule(new TimerTask()
{
@Override
public void run()
{
// 隨機地改變Service組件內color、weight屬性的值。
int rand = (int)(Math.random() * 3);
color = colors[rand];
weight = weights[rand];
System.out.println(-------- + rand);
}
} , 0 , 800);
}
@Override
public IBinder onBind(Intent arg0)
{
/* 返回catBinder對象
* 在綁定本地Service的情況下,該catBinder對象會直接
* 傳給客戶端的ServiceConnection對象
* 的onServiceConnected方法的第二個參數;
* 在綁定遠程Service的情況下,只將catBinder對象的代理
* 傳給客戶端的ServiceConnection對象
* 的onServiceConnected方法的第二個參數;
*/
return catBinder;
}
@Override
public void onDestroy()
{
timer.cancel();
}
}
2.4 客戶端訪問AIDLService
AIDL接口定義了兩個進程間的通信接口,因此客戶端也需要剛才定義的AIDL接口,因此開發客戶端的第一步就是將Service端的AIDL接口文件復制到客戶端應用中。復制到客戶端後ADT工具會為AIDL接口生成相應的實現。
客戶端綁定遠程Service,需要以下兩步:
創建ServiceConnection對象。
以ServiceConnection對象為參數,調用Context的bindService()方法遠程調用Service。
綁定遠程Service的ServiceConnection並不能直接獲取Service的onBind()方法所返回的對象,只能返回onBind()方法所返回的對象的代理。所以, ServiceConnection的on ServiceConnected方法中需要通過如下代碼處理:
AidlClient.java
public class AidlClient extends Activity
{
private ICat catService;
private Button get;
EditText color, weight;
private ServiceConnection conn = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
// 獲取遠程Service的onBind方法返回的對象的代理
catService = ICat.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name)
{
catService = null;
}
};
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
get = (Button) findViewById(R.id.get);
color = (EditText) findViewById(R.id.color);
weight = (EditText) findViewById(R.id.weight);
// 創建所需綁定服務的Intent
Intent intent = new Intent();
intent.setAction(com.boby.aidl.action.AIDL_SERVICE);
// 綁定遠程服務
bindService(intent, conn, Service.BIND_AUTO_CREATE);
get.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
try
{
// 獲取、並顯示遠程Service的狀態
color.setText(catService.getColor());
weight.setText(catService.getWeight() + );
}
catch (RemoteException e)
{
e.printStackTrace();
}
}
});
}
@Override
public void onDestroy()
{
super.onDestroy();
// 解除綁定
this.unbindService(conn);
}
}
電話管理器
電話管理TelephonyManager是一個管理手機通信狀態、電話網絡信息的服務類,該類提供了大量的getXxx()方法來獲取電話網絡的相關信息。
在程序中獲取TelephonyManager,只需調用如下代碼即可:
例:監聽手機來電:
MonitorPhone.java
public class MonitorPhone extends Activity
{
TelephonyManager tManager;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 取得TelephonyManager對象
tManager = (TelephonyManager) getSystemService
(Context.TELEPHONY_SERVICE);
// 創建一個通話狀態監聽器
PhoneStateListener listener = new PhoneStateListener()
{
@Override
public void onCallStateChanged(int state
, String incomingNumber)
{
switch (state)
{
// 無任何狀態
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
// 來電鈴響時
case TelephonyManager.CALL_STATE_RINGING:
OutputStream os = null;
try
{
os = openFileOutput(phoneList, MODE_APPEND);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
PrintStream ps = new PrintStream(os);
// 將來電號碼記錄到文件中
ps.println(new Date() + 來電: + incomingNumber);
ps.close();
break;
default:
break;
}
super.onCallStateChanged(state, incomingNumber);
}
};
//監聽電話通話狀態的改變
tManager.listen(listener
, PhoneStateListener.LISTEN_CALL_STATE);
}
}
注:在DDMS中的File Explorer面板的data/data/com.boby/files目錄下,看到一個phoneList文件,導出該文件,並查看其內容,記錄了來自另一個模擬器的電話呼入。
短信管理器
SmsManager是Android提供的另一個非常常見的服務, SmsManager提供了系統sendXxxMessage()方法用於發送短信。短信通常是普通的文本內容,也就是調用sendTextMessage()方法進行發送即可。
例:兩個模擬器互發短信:
下面的程序中用到了一個PendingIntent對象,是對Intent的包裝,一般通過調用PendingIntent的getActivity()、getService()、getBroadcastReceiver()靜態方法來獲取PendingIntent對象。
PendingIntent通常會傳給其他應用組件,從而由其他應用程序來執行PendingIntent所包裝的”Intent”。
例:
SendSms.java
public class SendSms extends Activity
{
EditText number , content;
Button send;
SmsManager sManager;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 獲取SmsManager
sManager = SmsManager.getDefault();
// 獲取程序界面上的兩個文本框和按鈕
number = (EditText) findViewById(R.id.number);
content = (EditText) findViewById(R.id.content);
send = (Button) findViewById(R.id.send);
// 為send按鈕的單擊事件綁定監聽器
send.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
// 創建一個PendingIntent對象
PendingIntent pi = PendingIntent.getActivity(SendSms.this
, 0, new Intent(), 0);
// 發送短信
sManager.sendTextMessage(number.getText().toString()
, null, content.getText().toString(), pi, null);
// 提示短信發送完成
Toast.makeText(SendSms.this
, 短信發送完成, 8000)
.show();
}
});
}
}
Android中onInterceptTouchEvent與onTouchEvent
Hi,大家好,今天給大家分享一下Android中onInterceptTouchEvent與onTouchEvent,,記得樓主以前剛開始找工作的時候,被人問了關於And
Android LaunchMode四種啟動模式詳細介紹
Android LaunchMode詳解越是做的時間越長,基礎知識就忘的越干淨,最近做一個項目中,發現啟動的幾個Activity居然重疊了,我ri~~,再不回憶一下就要退
從零開始學android實現計算器功能示例分享(計算器源碼)
下面是效果展示:復制代碼 代碼如下:<?xml version=1.0 encoding=utf-8?><LinearLayout xmlns:andr
Android使用GridLayout繪制自定義日歷控件
效果圖思路:就是先設置Gridlayout的行列數,然後往裡面放置一定數目的自定義日歷按鈕控件,最後實現日歷邏輯就可以了。步驟:第一步:自定義日歷控件(初步)第二步:實現