㈠ 怎麼添加靜態service 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文件,這樣可以方便後面:
㈡ Android Service啟動方式
1.startService
①.定義一個類繼承service
②.在manifest.xml文件中配置該service
③.使用context的startService(intent)啟動該service
④.不再使用時,調用stopService(Intent)停止該服務
2.bindService
①.創建bindService服務段,繼承自service並在類中,創建一個實現binder介面的實例對象並提供公共方法給客戶端調用
②.從onbind()回調方法返回此binder實例
③.在客戶端中,從onserviceconnected()回調方法接收binder,並使用提供的方法調用綁定服務
㈢ 如何在Android中添加系統服務
在android中添加系統服務,下面以SurfaceComposer這個service為例,
① 首先提供介面文件ISurfaceComposer.h
//frameworks\native\include\gui\ISurfaceComposer.h
//首先是介面,c++實現是虛函數
class ISurfaceComposer: public IInterface {
public:
DECLARE_META_INTERFACE(SurfaceComposer);
// flags for setTransactionState()
enum {
eSynchronous = 0x01,
eAnimation = 0x02,
};
enum {
eDisplayIdMain = 0,
};
/* create connection with surface flinger, requires
* ACCESS_SURFACE_FLINGER permission
*/
virtual sp<ISurfaceComposerClient> createConnection() = 0;
}
② 建立BnSurfaceComposer
建立BnSurfaceComposer,需要重寫BBinder的onTransact函數。
class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
public:
enum {
// Note: BOOT_FINISHED must remain this value, it is called from
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
CREATE_CONNECTION,
CREATE_GRAPHIC_BUFFER_ALLOC,
CREATE_DISPLAY_EVENT_CONNECTION,
CREATE_DISPLAY,
DESTROY_DISPLAY,
GET_BUILT_IN_DISPLAY,
SET_TRANSACTION_STATE,
AUTHENTICATE_SURFACE,
BLANK,
UNBLANK,
GET_DISPLAY_INFO,
CONNECT_DISPLAY,
CAPTURE_SCREEN,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags = 0);
};
③ Bpxxx的實現
frameworks\native\libs\gui\ISurfaceComposer.cpp中,
//Bp實現,代理端
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{
public:
BpSurfaceComposer(const sp<IBinder>& impl)
: BpInterface<ISurfaceComposer>(impl)
{
}
//代理介面
virtual sp<ISurfaceComposerClient> createConnection()
{
uint32_t n;
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
}
④ Bnxxx的實現
//Bn端,即server端
status_t BnSurfaceComposer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case CREATE_CONNECTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
//createConnection就是server端的實現函數
sp<IBinder> b = createConnection()->asBinder();
reply->writeStrongBinder(b);
return NO_ERROR;
}
default: {
return BBinder::onTransact(code, data, reply, flags);
}
}
// should be unreachable
return NO_ERROR;
}
⑤ 注冊service
通過上面幾步已經完成了service的建立,我們需要將service注冊到service manager中。
class SurfaceFlinger : public BnSurfaceComposer,
//在frameworks\native\services\surfaceflinger\main_surfaceflinger.cpp中,
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
⑥ 使用service
//首先獲取代理端BpSurfaceComposer
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
//直接調用代理BpSurfaceComposer的介面
sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
其中getComposerService()的實現為,
/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
assert(instance.mComposerService != NULL);
ALOGD("ComposerService reconnected");
}
return instance.mComposerService;
}
void ComposerService::connectLocked() {
const String16 name("SurfaceFlinger");
//獲取service,返回的mComposerService是BpSurfaceComposer,有了Bp就能直接調用代理介面了
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
assert(mComposerService != NULL);
// Create the death listener.
class DeathObserver : public IBinder::DeathRecipient {
ComposerService& mComposerService;
virtual void binderDied(const wp<IBinder>& who) {
ALOGW("ComposerService remote (surfaceflinger) died [%p]",
who.unsafe_get());
mComposerService.composerServiceDied();
}
public:
DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
};
mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
mComposerService->asBinder()->linkToDeath(mDeathObserver);
}
java添加service
Android為了方便開發人員,提供了AIDL工具,簡化了編寫service的難度。下面以添加TestService這個服務為例,
① 編寫AIDL文件
package android.app;
interface ITestService {
boolean enableWifi(boolean enabled);
}
TestService的AIDL文件提供了一個介面,enableWifi()。
② 創建TestService服務
TestService 服務需要繼承ITestService.Stub類,這個類就是通過AIDL工具對①中的AIDL文件處理後產生的,
class TestService extends ITestService.Stub {
//實現介面
public boolean enableWifi(boolean enabled)
{
......
}
}
③ Context.java中添加service名字字元串
// Context.java中添加service名字字元串
public static final String TEST_SERVICE = "my_test";
④ 向ServiceManager中注冊service
java中大部分的系統service都是在SystemServer中去向service manager注冊的,
//ServiceManager注冊service
// 在SystemServer.java中,模仿其他向ServiceManager添加service的方法
try {
TestService myService = new TestService(context);
ServiceManager.addService(Context.TEST_SERVICE, myService);
} catch (Throwable e) {
reportWtf("register my test service fail", e);
}
⑤創建服務對應的Manager
對於每一個service而言,通常會有一個相關的Manager。 Managers提供API給app使用,成為SDK的一部分,是apps和remote service的中間橋梁。Manager中的介面和Service中的介面必須一一對應。
public class TestServiceManager{
private final ITestService mService;
private final Context mContext;
//構造函數中傳入的service,其實就是BpTestService
TestServiceManager(Context context,ITestService service) {
mContext = context;
mService = service;
}
public boolean enableWifi(boolean enabled) {
try {
return mService.enableWifi(enabled);
} catch (RemoteException ex) {
}
return false;
}
}
到目前為止,我們只是完成了Service的注冊,但是還沒有使用,該如何使用?
⑥ contextImpl中注冊Manager
一旦我們實現了service和對應的Manager,需要有一種方法在app中調用他們。前面說過,Manager會成為SDK的一部分,供我們調用,那麼Manager和Service是如何聯系起來的?首先需要將我們的service和mangager注冊到execution context,即contextImpl中,
registerService(TEST_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(TEST_SERVICE);
//asInterface(BpBinder)後就是BpTestService
ITestService service = ITestService.Stub.asInterface(b);
//創建TestServiceManager,第二個參數為BpBpTestService
return new TestServiceManager(ctx.getOuterContext(), service);
}});
registerService的第二個參數是一個ServiceFetcher對象,這里直接在調用時,新建了一個ServiceFetcher類,重寫了createService方法。
ContextImpl.java中的registerService()方法,其核心就是把servicename和ServiceFetcher對象放到一個Hash的鍵值對中。
private static void registerService(String serviceName, ServiceFetcher fetcher) {
if (!(fetcher instanceof StaticServiceFetcher)) {
fetcher.mContextCacheIndex = ++;
}
SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}
⑦ app如何使用service
那麼app是如何調用的呢?
import android.app.TestServiceManager;
import android.content.Context;
TestServiceManager mTestServiceManager;
mTestServiceManager=(TestServiceManager)context.getSystemService(Context.TEST_SERVICE);
然後直接調用TestServiceManager中的方法即可,其中的奧秘需要分析下getSystemService函數。
ContextImpl.java中,
@Override
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
//從ServiceFetcher 中獲取service
return fetcher == null ? null : fetcher.getService(this);
}
getService()函數的核心就是上面重寫的createService()函數,返回的就是TestServiceManager對象,所以通過context.getSystemService返回的是Manager對象。
public Object getService(ContextImpl ctx) {
ArrayList<Object> cache = ctx.mServiceCache;
Object service;
synchronized (cache) {
if (cache.size() == 0) {
// Initialize the cache vector on first access.
// At this point
// is the number of potential services that are
// cached per-Context.
for (int i = 0; i < ; i++) {
cache.add(null);
}
} else {
service = cache.get(mContextCacheIndex);
if (service != null) {
return service;
}
}
//調用重載的createService函數,返回的就是TestServiceManager對象
service = createService(ctx);
cache.set(mContextCacheIndex, service);
return service;
}
}
㈣ 關於在Android框架中增加service
照葫蘆畫瓢唄,你看看framework/base/services/java/com/android/server/下的例子。一般一個server由xxxxService.java xxxxManager.java IxxxxManager.aidl組成。Manager和aidl在frameworks/base/core/java/android/。如果是要系統啟動時就運行,則需要在SystemServer.java中加上啟動你的Service的代碼。
㈤ android中如何自定義一個Service
在編寫Android應用程序時,我們一般將一些計算型的邏輯放在一個獨立的進程來處理,這樣主進程仍然可以流暢地響應界面事件,提高用戶體驗。Android系統為我們提供了一個Service類,我們可以實現一個以Service為基類的服務子類,在裡面實現自己的計算型邏輯,然後在主進程通過startService函數來啟動這個服務。在本文中,將詳細分析主進程是如何通過startService函數來在新進程中啟動自定義服務的。
㈥ android中怎麼在AndroidManifest.xml文件中配置Service
在AndroidManifest Application節點中增加<service>節點即可。
具體代碼:
創建Servie對象,並繼承anroid.os.service
在androidManifest中 Application中增加service節點
<service android:name="Service完整包名+類名"></service>
重寫Service onCreate onStartCommand() bindService() 即可
㈦ 用eclipse做Android開發,怎麼新建一個service類new裡面沒有service
一、用 eclipse 創建一個 WebService 伺服器端
1、 首先新建一個動態 web 工程,選擇 File->New->Dynamic Web Project,命名為 axis。
2、 創建一個包, 再新建一個類,右擊 src,選擇 New->Class,命名為 AddService 添加方法 add: public class AddService { public int add(int a, int b) { return a+b; } }
3、右擊 AddService.java 文件,選擇 Web Services->Create Web Service。
4、點擊 next,選擇方法 add,點擊 next->Start server->Finish。這時可以看到 WebContent 目 錄下多了個 wsdl 文件夾,axis 插件自動為我們生成了 AddService.wsdl。
5、我們可以對 AddService 的方法進行測試。右擊 AddService.wsdl,選擇 Web Services->Test with Web Services Explorer。選擇 add 就可以該方法進行測試。
6、將 AddService.java 復制到 WebContent 目錄下,並改名為 AddService.jws。
7、啟動 tomcat,在瀏覽器中輸入 http://localhost:8080/axis/AddService.jws,應該會看到提示: There is a Web Service here,點擊 Click to see the WSDL,看到一個 xml 文件就成功了。
8、將 workspace 下的 axis 工程里的 WebContent 復制到了 tomcat 的 webapps 目錄下,並改 名為 axis,方便訪問。 啟動 tomcat 伺服器,在瀏覽器中輸入:
http://localhost:8080/axis/AddService.jwswsdl
至此,WebService 服務端成功發布。
二、用 eclipse 創建一個 WebService 客戶端 1、 新建一個動態 Web 工程 addTest,再創建 WebService 客戶端: File->New->Other..->Web Services->Web Service Client。 (必須有 Web 工程才能創建 Web Service Client)
2、在 Service definition 輸入框中輸入地址: http://伺服器 ip 地址:8080/axis/services/AddServicewsdl,單擊下一步,選擇輸出文件夾,點 擊 Finish。可以看到 src 下生成了一個包 DefaultNameSpace,裡面有五個 java 文件。 (注意 輸入地址跟前面的不一樣) AddService.java 定義了 Web 服務介面; AddServiceService.java 定義了用於獲取 Web 服務介面的方法; AddServiceServiceLocator.java 介面 AddServiceService 的具體實現; AddServiceSoapBindingStub.java Web 服務客戶端樁,通過該類與伺服器交互。
3、新建一個測試類 TestAddService,為了方便,這個類和剛剛產生的五個類在一個包下。 內容如下:
package DefaultNamespace; public class TestAddService {
public static void main(String[] args) throws Exception{
try{
AddServiceService service = new AddServiceServiceLocator(); AddService add = service.getAddService(); System.out.println(add.add(1, 1)); }catch(Exception e){ e.printStackTrace(); } } }
4、右擊 TestAddService.java,Run As->Java Application。便可以控制台看到輸出結果。
㈧ android 怎麼在te裡面添加service許可權
先root,在下載個RE文件管理器,找到你要添加的文件,re管理器添加就好了
㈨ android怎麼寫一個殺不死的service
1.在service中重寫下面的方法,這個方法有三個返回值, START_STICKY是service被kill掉後自動重寫創建
[代碼]java代碼:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}----------------
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.v("TrafficService","startCommand");
flags = START_STICKY;
return super.onStartCommand(intent, flags, startId);
// return START_REDELIVER_INTENT;
}
2.在Service的onDestroy()中重啟Service.
public void onDestroy() {
Intent localIntent = new Intent();
localIntent.setClass(this, MyService.class); //銷毀時重新啟動Service
this.startService(localIntent);
}
用qq管家殺掉進程的時候,調用的是系統自帶的強制kill功能(即settings里的),在kill時,會將應用的整個進程停掉,當然包括service在內,如果在running里將service強制kill掉,顯示進程還在。不管是kill整個進程還是只kill掉進應用的 service,都不會重新啟動service。不知道你是怎麼實現重啟的,實在是不解。 在eclipse中,用stop按鈕kill掉進程的時候,倒是會重啟service
KILL問題:
1. settings 中stop service
onDestroy方法中,調用startService進行Service的重啟。
2.settings中force stop 應用
捕捉系統進行廣播(action為android.intent.action.PACKAGE_RESTARTED)
3. 藉助第三方應用kill掉running task
提升service的優先順序
service開機啟動
今天我們主要來探討android怎麼讓一個service開機自動啟動功能的實現。Android手機在啟動的過程中會觸發一個Standard Broadcast Action,名字叫android.intent.action.BOOT_COMPLETED(記得只會觸發一次呀),在這里我們可以通過構建一個廣播接收者來接收這個這個action.下面我就來簡單寫以下實現的步驟:
第一步:首先創建一個廣播接收者,重構其抽象方法 onReceive(Context context, Intent intent),在其中啟動你想要啟動的Service或app。
[代碼]java代碼:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class BootBroadcastReceiver extends BroadcastReceiver {
//重寫onReceive方法
@Override
public void onReceive(Context context, Intent intent) {
//後邊的XXX.class就是要啟動的服務
Intent service = new Intent(context,XXXclass);
context.startService(service);
Log.v("TAG", "開機自動服務自動啟動.....");
//啟動應用,參數為需要自動啟動的應用的包名
Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
context.startActivity(intent );
}
}
第二步:配置xml文件,在re
ceiver接收這種添加intent-filter配置
[代碼]java代碼:
<receiver android:name="BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
第三步:添加許可權 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
如何實現一個不會被殺死的進程
看Android的文檔知道,當進程長期不活動,或系統需要資源時,會自動清理門戶,殺死一些Service,和不可見的Activity等所在的進程。
但是如果某個進程不想被殺死(如數據緩存進程,或狀態監控進程,或遠程服務進程),應該怎麼做,才能使進程不被殺死。
add android:persistent="true" into the <application> section in your AndroidManifest.xml
切記,這個 不可濫用,系統中用這個的service,app一多,整個系統就完蛋了。
目前系統中有phone等非常有限的,必須一直活著的應用在試用。
提升service優先順序的方法
Android 系統對於內存管理有自己的一套方法,為了保障系統有序穩定的運信,系統內部會自動分配,控製程序的內存使用。當系統覺得當前的資源非常有限的時候,為了保 證一些優先順序高的程序能運行,就會殺掉一些他認為不重要的程序或者服務來釋放內存。這樣就能保證真正對用戶有用的程序仍然再運行。如果你的 Service 碰上了這種情況,多半會先被殺掉。但如果你增加 Service 的優先順序就能讓他多留一會,我們可以用 setForeground(true) 來設置 Service 的優先順序。
為什麼是 foreground ? 默認啟動的 Service 是被標記為 background,當前運行的 Activity 一般被標記為 foreground,也就是說你給 Service 設置了 foreground 那麼他就和正在運行的 Activity 類似優先順序得到了一定的提高。當讓這並不能保證你得 Service 永遠不被殺掉,只是提高了他的優先順序。
從Android 1.5開始,一個已啟動的service可以調用startForeground(int, Notification)將service置為foreground狀態,調用stopForeground(boolean)將service置為 background狀態。
我們會在調用startForeground(int, Notification)傳入參數notification,它會在狀態欄里顯示正在進行的foreground service。background service不會在狀態欄里顯示。
在Android 1.0中,將一個service置為foreground狀態:
setForeground(true);
mNM.notify(id, notification);
將一個service置為background狀態:
mNM.cancel(id);
setForeground(false);
對比看出,在1.0 API中調用setForeground(boolean)只是簡單的改變service的狀態,用戶不會有任何覺察。新API中強制將 notification和改變service狀態的動作綁定起來,foreground service會在狀態欄顯示,而background service不會。
Remote service controller & binding
跨進程調用Service。暫時不研究。
如何防止Android應用中的Service被系統回收? 很多朋友都在問,如何防止Android應用中的Service被系統回收?下面簡單解答一下。
對於Service被系統回收,一般做法是通過提高優先順序可以解決,在AndroidManifest.xml文件中對於intent-filter可以通過 android:priority = "1000"這個屬性設置最高優先順序,1000是最高值,如果數字越小則優先順序越低,同時實用於廣播,推薦大家如果你的應用很重要,可以考慮通過系統常用intent action來觸發。
㈩ Android源碼添加服務
1.添加.AIDL文件
/frameworks/base/core/java/android/os/IHelloService.aidl
[java] view plain
package android.os;
interface IHelloService
{
String test_service(String input);
}
在/frameworks/base/Android.mk 把aidl文件加入到源碼編譯器中
[java] view plain
core/java/android/os/IHelloService.aidl \
2.編寫服務類
/frameworks/base/services/java/com/android/server/HelloService.java
[java] view plain
package com.android.server;
import android.os.IHelloService;
import android.os.IBinder;
import android.content.Context;
import android.util.Log;
public class HelloService extends IHelloService.Stub
{
private static final String TAG="HelloService";
@Override
public String test_service(String input){
Log.i(TAG,"eva HelloService HelloService,test_service()) method");
return input;
}
public HelloService()
{
super();
Log.i(TAG,"eva HelloService Constructor method");
}
}
3.編寫服務管理器
/frameworks/base/core/java/android/os/TestServiceManager/frameworks/base/core/java/android/os/HelloManager.java
[java] view plain
package android.os;
import android.os.IHelloService;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
public class HelloManager
{
//Basic Member
android.os.IHelloService mService;
private static final String TAG="HelloManager";
//Constructor
public HelloManager(Context ctx,android.os.IHelloService service)
{
mService=service;
Log.i(TAG,"eva HelloManager Constructor method");
}
public String test_service(String input){
try{
Log.i(TAG,"eva HelloManager Constructor mService.test_service");
return mService.test_service(input);
}catch(RemoteException e)
{
return e.getMessage();
}
}
}
4.注冊服務
/frameworks/base/core/java/android/app/SystemServiceRegistry.java
[java] view plain
import android.os.IHelloService;
import android.os.HelloManager;
registerService("HELLO_SERVICE",HelloManager.class,
new CachedServiceFetcher<HelloManager>(){
@Override
public HelloManager createService(ContextImpl ctx)
{
IBinder b = ServiceManager.getService("HELLO_SERVICE");
Log.i(TAG,"eva SystemServiceRegistry registerService method");
return new HelloManager(ctx,IHelloService.Stub.asInterface(b));
}});
5.啟動服務
/frameworks/base/services/java/com/android/server/SystemServer.java
[java] view plain
import com.android.server.HelloService;
ServiceManager.addService("HELLO_SERVICE", new HelloService());
6.將服務加入到源碼中,編譯備份
/external/sepolicy/service.te
[java] view plain
type hello_service, system_api_service, system_server_service, service_manager_type;
7.給服務許可權
/external/sepolicy/service_contexts
[java] view plain
HELLO_SERVICE u:object_r:hello_service:s0
8.Demo
MainActivity.java
[java] view plain
package com.example.testservicedemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.os.HelloManager;
public class MainActivity extends Activity {
private EditText writeEdit;
private Button readBtn;
private TextView showInfo;
private HelloManager mTestServiceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
writeEdit = (EditText)findViewById(R.id.input);
readBtn = (Button)findViewById(R.id.read);
showInfo = (TextView)findViewById(R.id.showinfo);
mTestServiceManager = (HelloManager)getSystemService("HELLO_SERVICE");
readBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String inputString = writeEdit.getText().toString();
String result = mTestServiceManager.test_service(inputString);
showInfo.setText(result);
}
});
}
}