android建立服務
1. 如何創建android系統服務
1、 撰寫一個aidl文件,定義服務的介面,將在編譯過程中通過aidl工具生成對應的java介面。一般系統服務的aidl文件都放在framework\base\core\java\android\os目錄中。
以我所寫的IMyTool.aidl為例。在.aidl中定義自己需要加入的方法,編寫規則和java介面差不多,這里不多說。
2、 將aidl文件名添加到frameworks\base\目錄下的Android.mk編譯腳本文件中。
如:
LOCAL_SRC_FILES += \
core/java/android/accessibilityservice/.aidl\
…\
core/java/android/os/IMyTool.aidl\
…
IMyTool.aidl即我加進去的aidl文件,加入後才能在make過程中編譯到,否則將在後面的SystemServer添加系統服務時會報錯提示找不到對應類。
3、 編寫真正工作的服務類,繼承IMyTool.Stub類(AIDL文件名.Stub,aidl生成的介面中的內部類,是一個Binder)。
服務類一般都放在framework\base\services\java\com\android\server目錄中。
例如:
public class MyToolService extends IMyTool.Stub {
實現IMyTool.aidl中定義的介面。
}
4、 將自定義服務注冊到SystemServer,使得開機過程中被添加。
在framework\base\services\java\com\android\server目錄中的SystemServer中啟動服務代碼處加入:
try {
Slog.i(TAG, "MyToolService");
ServiceManager.addService(Context.MY_TOOL_SERVICE,new MyToolService(context));// MyToolService構造函數自己定義,一般都會用到Context
} catch(Throwable e) {
Slog.e(TAG, "Failure startingMyToolService", e);
}
上面代碼中Context.MY_TOOL_SERVICE是自己在Context類中定義的常量,也就是給服務定義的名字,使用常量方便獲取服務,而不需要記住注冊服務時用的名字,且想換名字時只需改一個常量的值。
2. 如何給Android應用創建本地服務
本文通過代碼向大家詳細介紹和演示這兩種的服務的創建過程,代碼適用於Android2.3.3以後的版本。
1. 定義清單文件(AndroidManifest.xml)

4. 創建服務啟動界面(LocalServiceActivities.java)
package my.android.test;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
/**
* 該類中包含兩種類型服務的客戶端:
* 啟動類型服務客戶端:Controller
* 綁定類型服務客戶端:Binding
*/
publicclass LocalServiceActivities {
/**
* Controller類是啟動類型服務的客戶端,它包含兩個按鈕:
* start:點擊該按鈕時,啟動服務。
* stop: 點擊該按鈕時,終止服務。
*/
publicstaticclass Controller extends Activity{
/**
* Activity被首次啟動時,調用該方法。
*/
@Override
protectedvoid onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//填充布局
setContentView(R.layout.local_service_controller);
//查找布局中的啟動服務按鈕,並設置點擊事件監聽器。
Button button = (Button)findViewById(R.id.start);
button.setOnClickListener(mStartListener);
//查找布局中的終止服務按鈕,並設置點擊事件監聽器。
button = (Button)findViewById(R.id.stop);
button.setOnClickListener(mStopListener);
}
/**
* start按鈕的點擊事件監聽器實現。
*/
private OnClickListener mStartListener = new OnClickListener(){
publicvoid onClick(View v){
//啟動LocalService服務。
startService(new Intent(Controller.this, LocalService.class));
}
};
/**
* stop按鈕的點擊事件監聽器實現。
*/
private OnClickListener mStopListener = new OnClickListener(){
publicvoid onClick(View v){
//終止LocalService服務。
stopService(new Intent(Controller.this, LocalService.class));
}
};
}
/***************************************************************
*以下是綁定型服務客戶端的實現
***************************************************************/
/**
* Binding類是綁定類型服務的客戶端,它包含兩個按鈕:
* bind:點擊該按鈕時,調用bindService()方法綁定並啟動服務;
* unbind:點擊該按鈕時,調用unbindService()方法解除綁定並終止服務。
*/
publicstaticclass Binding extends Activity{
//用於保存服務的綁定狀態,true:綁定,false:未綁定
privatebooleanmIsBound;
//用於保存被綁定的本地服務實例。
private LocalService mBoundService;
/**
* 實現監視被綁定服務狀態的介面:ServiceConnection
* 綁定類型服務都要實現這個介面,以便監視服務的狀態,這個介面中的方法會在
* 應用的主線程中被調用。
*/
private ServiceConnection mConnection = new ServiceConnection(){
/**
* 當連接的服務被創建時,Android系統會調用這個方法,用IBinder對象跟服務建立通信通道。
* @param className:被連接的具體的服務組件的名稱
* @param service:服務的通信通道IBinder對象。
*/
publicvoid onServiceConnected(ComponentName className, IBinder service){
//從IBinder對象中獲取服務實例。
mBoundService = ((LocalService.LocalBinder)service).getService();
//顯示Activity已經與服務建立了連接的提示消息。
Toast.makeText(Binding.this, R.string.local_service_connected, Toast.LENGTH_SHORT).show();
}
/**
* 當服務被終止時,Android系統會調用這個方法。
*/
publicvoid onServiceDisconnected(ComponentName className){
//清除客戶端服務實例
mBoundService = null;
//顯示服務被終止的提示消息。
Toast.makeText(Binding.this, R.string.local_service_disconnected, Toast.LENGTH_SHORT).show();
}
};
/**
* 綁定並啟動服務,bind按鈕點擊時會調用這個方法。
*/
void doBindService(){
//綁定並啟動服務。
bindService(new Intent(Binding.this, LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
/**
* 解除與服務的綁定,unbind按鈕被點擊時會調用這個方法
*/
void doUnbindService(){
//如果服務被綁定,則解除與服務綁定。
if(mIsBound){
unbindService(mConnection);
mIsBound = false;
}
}
/**
* 當Activity被銷毀時,調用解除綁定服務的方法,解除被綁定的服務。
*/
@Override
protectedvoid onDestroy(){
super.onDestroy();
//解除被綁定的服務。
doUnbindService();
}
/**
* bind按鈕的點擊事件監聽器介面實現。
*/
private OnClickListener mBindListener = new OnClickListener(){
publicvoid onClick(View v){
//綁定並啟動服務。
doBindService();
}
};
/**
* unbind按鈕的點擊事件監聽器介面實現。
*/
private OnClickListener mUnbindListener = new OnClickListener(){
publicvoid onClick(View v){
//解除被綁定的服務。
doUnbindService();
}
};
/**
* Activity被首次啟動時,會調用這個方法。
*/
@Override
protectedvoid onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//填充Activity
setContentView(R.layout.local_service_binding);
//查找布局中的bind按鈕,並設置點擊事件的監聽器
Button button = (Button)findViewById(R.id.bind);
button.setOnClickListener(mBindListener);
//查找布局中的unbind按鈕,並設置點擊事件的監聽器
button = (Button)findViewById(R.id.unbind);
button.setOnClickListener(mUnbindListener);
}
}
}
5. 創建服務(LocalService.java)
package my.android.test;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;
import android.widget.Toast;
/**
* LocalService基礎Android的Service類,實現應用的本地服務組件。
* 該服務使用HandlerThread類創建了服務自己的線程和消息循環,
* 因此,不會因為服務中的長時處理,而阻塞界面的刷新,影響用戶體驗。
*/
publicclass LocalService extends Service {
//用於保存本服務自己的消息循環對象Looper
private Looper mServiceLooper;
//用於保存內部類ServiceHandler的對象實例,它繼承了Android的Handler類,
//用於處理發送給服務的消息。
private ServiceHandler mServiceHandler;
/**
* 這個類用於給客戶端提供綁定對象,因為本示例的服務與客戶端運行在同一個
* 主進程中,所以不需要處理進程間通信(IPC)
*/
publicclass LocalBinder extends Binder{
LocalService getService(){
//返回本服務的實例。
return LocalService.this;
}
}
/**
* 服務被首次創建時,系統調用這個方法。
* Android服務組件必須覆寫這個方法
*/
@Override
publicvoid onCreate(){
//創建線程對象,並啟動線程。
HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
//獲取線程的消息循環對象
mServiceLooper = thread.getLooper();
//用線程的消息循環對象創建消息處理對象。
mServiceHandler = new ServiceHandler(mServiceLooper);
}
/**
* 啟動類型服務必須實現這個方法,客戶端每次調用startService()方法時,
* 系統都會調用這個方法。
* @param intent:它是傳遞給startService()方法的Intent對象。
* @param flags:有關啟動請求的附加數據,可以是:0、START_FLAG_REDELIVERY或START_FLAG_RETRY.
* @param startId:一個唯一的整數,代表一次具體的請求,用於stopSelfResult(int)方法。
*/
@Override
publicint onStartCommand(Intent intent, int flags, int startId){
Log.i("LocalService", "Received star id" + startId + ":" + intent);
//顯示服務啟動的提示信息
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
//獲取要傳遞給服務消息循環的Message對象。
Message msg = mServiceHandler.obtainMessage();
//初始化Message對象的成員變數。
msg.arg1 = startId;
msg.obj = "Message processing......" + startId;
//把消息發送給服務線程的消息循環。
mServiceHandler.sendMessage(msg);
returnSTART_STICKY;
}
/**
* 必須覆寫這個方法,服務被終止時要調用這個方法,清理服務所佔用的資源。
*/
@Override
publicvoid onDestroy(){
//退出服務線程的消息循環。
mServiceLooper.quit();
//顯示服務被退出的提示信息。
Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();
}
/**
* 綁定型服務必須覆寫這個方法,啟動型服務也可覆寫這個方法,只要返回null即可。
*/
@Override
public IBinder onBind(Intent intent){
//返回本服務對象實例。
returnmBinder;
}
privatefinal IBinder mBinder = new LocalBinder();
/**
* 該類繼承Android的Handler類,為線程的消息循環提供發送和處理消息的功能,
* 本示例覆寫了handleMessage()方法,用來處理發送給服務消息循環的消息。
*/
privatefinalclass ServiceHandler extends Handler{
//類實例化時,需要傳入服務線程的消息循環對象
public ServiceHandler(Looper looper){
super(looper);
}
/**
* 覆寫Handler類的handleMessage()方法,當服務線程的消息循環接收到外部
* 發送的消息時,會調用這個方法來處理對應的消息,本示例只是簡單的向用戶提示消息被處理的信息。
*/
@Override
publicvoid handleMessage(Message msg){
long endTime = System.currentTimeMillis() + 5 * 1000;
while (System.currentTimeMillis() < endTime){
synchronized(this){
try{
wait(endTime - System.currentTimeMillis());
CharSequence cs = msg.obj.toString();
Toast.makeText(LocalService.this, cs, Toast.LENGTH_SHORT).show();
//showNotification();
}catch(Exception e){
//
}
}
}
//消息被處理之後,終止本服務。
LocalService.this.stopSelf();
}
}
}
3. 如何在Android中添加系統服務
這里說的系統服務,是指捆綁在system_process進程中的服務。仔細閱讀源碼可以發現,在frameworks/base/services/java/com/android/server/SystemServer.java中添加了很多服務,什麼熵信息、電量、wife等等服務,這些服務啟動都在launcher之前,一般要繼承Binder或者繼承一個AIDL。下面試著來添加一個簡單系統服務。
一、在frameworks/base/core/java/android/os/ 增加一個aidl文件,最後用aidl工具生產一個Java文件,這樣可以方便後面:然後在修改/frameworks/base/Android.mk,在LOCAL_SRC_FILES里添加一行:core/java/android/os/IYtTtsService.aidl \不確定補充:把AIDL文件寫在這個地方似乎可以避免加@hide
二 、在frameworks/base/services/java/com/android/server/ 新建要增加的service,繼承上面aidl生產的java
三、在frameworks/base/services/java/com/android/server/SystemServer.java, ServerThread中run()方法中增加代碼
四、在ContextImpl getSystemService中添加代碼
五、測試代碼
4. 在Android開發中怎麼將手機作為伺服器
工具/原料
root軟體:網路root為佳!如果你已經獲取了許可權,可以跳過。
ksweb軟體:用於搭建手機php伺服器的軟體。
nat123軟體:強大的內網埠映射軟體,不需要路由器許可權。
方法/步驟
1.安裝手機本地php+mysql伺服器環境篇:
1.1安裝ksweb軟體,安裝好ksweb後,會在手機上生成一個文件夾htdocs,其目錄是mnt/sdcard/htdocs,htdocs是網站的根目錄。
1.2安裝mysql直接點擊mysql管理,點擊選擇「是」然後解壓便可自動安裝。mysql的賬號密碼隨後再改(在設置裡面更改)。
1.3安裝好MySQL之後,我們需要對ksweb進行一些設置方可更好使用。
1.3.1埠的更改步驟:(啟用root→更改80埠)手機伺服器啟用root,在ksweb設置裡面把root打鉤。
1.3.2開啟手機80埠方法:把8080埠改為80埠,並把PHP服務,MySQL都打勾。其他一些設置比如MySQL密碼,開機自啟動等選項大家根據需要自行修改即可!
1.4ksweb全部設置好後,我們打開手機本地伺服器地址localhost:80,表示設置好了。
我們點擊頁面中的「EnterKSWEBWeb Interface」可以看到手機伺服器的一些配置信息(默認賬號密碼都是「admin」),表示手機服務搭建成功,一切正常!
2.利用nat123軟體進行內網80埠映射篇:
2.1注冊賬號,我們先到其官網注冊賬號官網,大家網路nat123即可。
2.2登陸並添加域名解析。
2.2.1應用名稱,要搭建自己的博客,可以填XX的博客,或者XX的個人博客等。
2.2.2內網埠,只有root的手機才填80埠。
2.2.3內網地址這個默認localhost就行。
2.2.4 外網域名,如果沒有自己的域名,可以用官方免費的二級域名,注意格式,一切填好之後,點擊確認保存即可!
2.3 下載並安裝登陸安卓版的nat123,就自動解析了。
3.4接下來在另一台電腦上輸入剛才的域名訪問,表示安卓手機web伺服器安裝成功,網站搭建成功!
注意事項
另外如果需要手機網站一直都可以訪問,需要下載一個永不關屏軟體,這樣手機就不會進入睡眠狀態,服務也不會停止,不過比較耗電。
外網能訪問內網手機web伺服器的關鍵是nat123埠映射功能,利用nat123埠映射功能,不只是搭建內網網站,還可以挖掘其他的許多用途。
