最近在思索著Android命令行下可以執(zhí)行C語言寫的命令行程序(Android是基于Linux的,那么Linux支持的总处,在Android上也是支持的)贤惯,那么Android上層基于JAVA的Dalvik虛擬機(jī)是否也可以讓JAVA程序在命令行下執(zhí)行挠日,答案是肯定的佑刷,我們發(fā)現(xiàn)在Android源碼目錄下的frameworks/base/cmds/目錄下有相應(yīng)的程序弃舒,可將普通的JAVA程序打包成JAR痰娱,讓其運(yùn)行于Dalvik虛擬機(jī)上牍疏,而不是標(biāo)準(zhǔn)的JVM上杖剪。為了對其研究實(shí)踐一番冻押,編寫了如下例子:
Android4.0狀態(tài)欄控制命令:基于Android4.0.4系統(tǒng),需要在源碼環(huán)境下編譯(即需要有Android源碼和編譯環(huán)境)盛嘿,實(shí)現(xiàn)功能有:
1洛巢、控制整個(gè)狀態(tài)欄的顯示、隱藏次兆;
2稿茉、控制BACK、HOME芥炭、RECENT這三個(gè)按鍵的顯示漓库、隱藏;
首先园蝠,我們在Android源碼目錄下的frameworks/base/cmds目錄下創(chuàng)建sbstate目錄(StatusBarState)渺蒿,該目錄下包含Android.mk、sbstate兩文件和src目錄彪薛,其中src目錄下包含了整個(gè)JAVA包的層級目錄及類源碼茂装,其路徑結(jié)構(gòu)為src/com/cmds/xinu/Sbstate.java怠蹂。
Sbstate.java源碼如下:
package com.cmds.xinu;
import android.content.Context;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.view.View;
import com.android.internal.statusbar.IStatusBarService;
public class Sbstate {
public static void main(String[] args) {
(new Sbstate()).run(args);
}
private void run(String[] args){
if (args.length < 1){
showUsage();
return;
}
String command = args[0];
IStatusBarService mBarService;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
if (command.equals("sbvis")){
try {
mBarService.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);//View.STATUS_BAR_VISIBLE
} catch (RemoteException ex) {
}
System.out.println("Status Bar Visible!");
} else if (command.equals("sbdis")){
try {
mBarService.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);//View.STATUS_BAR_HIDDEN
} catch (RemoteException ex) {
}
System.out.println("Status Bar Disable/Unvisible!");
} else if (command.equals("bvis")){
try{
mBarService.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE & ~View.STATUS_BAR_DISABLE_BACK);
} catch (RemoteException ex) {
}
System.out.println("Back button visible!");
} else if (command.equals("bdis")){
try{
mBarService.setSystemUiVisibility(View.STATUS_BAR_DISABLE_BACK);
} catch (RemoteException ex) {
}
System.out.println("Back button Disable/Unvisible!");
} else if (command.equals("hvis")){
try{
mBarService.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE & ~View.STATUS_BAR_DISABLE_HOME);
} catch (RemoteException ex) {
}
System.out.println("Home button visible!");
} else if (command.equals("hdis")){
try{
mBarService.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
} catch (RemoteException ex) {
}
System.out.println("Home button Disable/Unvisible!");
} else if (command.equals("rvis")){
try{
mBarService.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE & ~View.STATUS_BAR_DISABLE_RECENT);
} catch (RemoteException ex) {
}
System.out.println("Recent button visible!");
} else if (command.equals("rdis")){
try{
mBarService.setSystemUiVisibility(View.STATUS_BAR_DISABLE_RECENT);
} catch (RemoteException ex) {
}
System.out.println("Recent button Disable/Unvisible!");
}
}
private void showUsage(){
System.err.println("Usage:sbstate [sbvis|sbdis|bvis|bdis|hvis|hdis|rvis|rdis]");
System.err.println("? ? ? sbvis:statusbar visible");
System.err.println("? ? ? sbdis:statusbar disable");
System.err.println("? ? ? bvis:back button visible");
System.err.println("? ? ? bdis:back button disable");
System.err.println("? ? ? hvis:home button visible");
System.err.println("? ? ? hdis:home button disable");
System.err.println("? ? ? rvis:recent button visible");
System.err.println("? ? ? rdis:recent button disable");
}
}
該部分源碼都是調(diào)用Android的API,之前一直犯難的是在如何獲取StatusBar相關(guān)對象少态,后來查看了cmds目錄下的其他文件城侧,發(fā)現(xiàn)基本上是通過調(diào)用Interface來獲取實(shí)例,其他都是標(biāo)準(zhǔn)的JAVA語言代碼彼妻。
sbstate文件內(nèi)容如下:
base=/system
export CLASSPATH=$base/framework/sbstate.jar
exec app_process $base/bin com.cmds.xinu.Sbstate $*
該部分內(nèi)容主要是設(shè)置CLASSPATH環(huán)境變量為我們編譯出來的JAR文件嫌佑,即指定了我們的程序位置,Android源碼編譯完后會放至/system/framework目錄下侨歉,接下來使用Linux命令下的exec命令來調(diào)用app_process命令執(zhí)行我們的JAVA程序歧强,其中app_process命令位于源碼目錄下的frameworks/base/cmds/app_process目錄下,其命令的使用方法如下:
Usage: app_process [java-options] cmd-dir start-class-name [options]
其中我們文件里的$base/bin對應(yīng)的是命令所在的目錄为肮,com.cmds.xinu.Sbstate為我們的JAVA代碼的入口類摊册,即main函數(shù)所在的類名,而$*是將命令行輸入的任何參數(shù)傳遞作為main函數(shù)的參數(shù)列表颊艳。
Android.mk文件內(nèi)容:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := sbstate
include $(BUILD_JAVA_LIBRARY)
include $(CLEAR_VARS)
ALL_PREBUILT += $(TARGET_OUT)/bin/sbstate
$(TARGET_OUT)/bin/sbstate : $(LOCAL_PATH)/sbstate | $(ACP)
$(transform-prebuilt-to-target)
其中文件是參考其他同目錄下的Android.mk文件茅特,其功能主要是將JAVA文件編譯成JAVA庫JAR文件,并把sbstate文件復(fù)制到目標(biāo)目錄的system/bin目錄下棋枕,我這邊測試時(shí)是手動(dòng)把sbstate文件復(fù)制到/system/bin目錄下白修,此時(shí)需要注意該文件的權(quán)限,不然會有Permission Deny之類的提示重斑。
由于我們放在源碼里編譯兵睛,如果直接這樣mm一下,是會出錯(cuò)的窥浪,我們還需要修改Android源碼的編譯配置祖很,涉及到如下文件:
1、build/core/legacy_prebuilts.mk
對應(yīng)于Android.mk里要用到的prebuilt功能漾脂,主要是把sbstate文件復(fù)制到/system/bin目錄下,不加的話會提示預(yù)編譯失敼歉濉笨鸡;
在文件中修改GRANDFATHERED_ALL_PREBUILT配置項(xiàng),添加上sbstate坦冠。
2形耗、build/core/user_tags.mk
對應(yīng)于Android.mk里要用到的編譯為JAR功能,在文件中修改GRANDFATHERED_USER_MODULES配置項(xiàng)辙浑,添加上sbstate激涤。
至此,整個(gè)編譯配置及源碼就實(shí)現(xiàn)好了例衍,接下來只需要mm一下昔期,復(fù)制或者燒錄一下已卸,就可以在命令行(串口或者ADB)下大膽的敲上sbstate命令,會有如下提示:
Usage:sbstate [sbvis|sbdis|bvis|bdis|hvis|hdis|rvis|rdis]
sbvis:statusbar visible
sbdis:statusbar disable
bvis:back button visible
bdis:back button disable
hvis:home button visible
hdis:home button disable
rvis:recent button visible
rdis:recent button disable
此時(shí)硼一,我們可以輸入如下形式的命令來執(zhí)行相應(yīng)的功能:
1累澡、顯示狀態(tài)欄:sbstate sbvis
2、隱藏狀態(tài)欄:sbstate sbdis
3般贼、顯示BACK按鈕圖標(biāo):sbstate bvis
4愧哟、隱藏BACK按鈕圖標(biāo):sbstate bdis
5、顯示HOME按鈕圖標(biāo):sbstate hvis
6哼蛆、隱藏HOME按鈕圖標(biāo):sbstate hdis
7蕊梧、顯示RECENT按鈕圖標(biāo):sbstate rvis
8、隱藏RECENT按鈕圖標(biāo):sbstate rdis
好了腮介,親手嘗試一下吧肥矢,見證狀態(tài)欄的風(fēng)起云涌,變幻莫測吧叠洗。