最近在思索着Android命令行下可以执行C语言写的命令行程序(Android是基于Linux的,那么Linux支持的,在Android上也是支持的),那么Android上层基于JAVA的Dalvik虚拟机是否也可以让JAVA程序在命令行下执行,答案是肯定的,我们发现在Android源码目录下的frameworks/base/cmds/目录下有相应的程序,可将普通的JAVA程序打包成JAR,让其运行于Dalvik虚拟机上,而不是标准的JVM上。为了对其研究实践一番,编写了如下例子:

Android4.0状态栏控制命令:基于Android4.0.4系统,需要在源码环境下编译(即需要有Android源码和编译环境),实现功能有:

1、控制整个状态栏的显示、隐藏;

2、控制BACK、HOME、RECENT这三个按键的显示、隐藏;

首先,我们在Android源码目录下的frameworks/base/cmds目录下创建sbstate目录(StatusBarState),该目录下包含Android.mk、sbstate两文件和src目录,其中src目录下包含了整个JAVA包的层级目录及类源码,其路径结构为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");

}

}

该部分源码都是调用Android的API,之前一直犯难的是在如何获取StatusBar相关对象,后来查看了cmds目录下的其他文件,发现基本上是通过调用Interface来获取实例,其他都是标准的JAVA语言代码。

sbstate文件内容如下:

base=/system

export CLASSPATH=$base/framework/sbstate.jar

exec app_process $base/bin com.cmds.xinu.Sbstate $*

该部分内容主要是设置CLASSPATH环境变量为我们编译出来的JAR文件,即指定了我们的程序位置,Android源码编译完后会放至/system/framework目录下,接下来使用Linux命令下的exec命令来调用app_process命令执行我们的JAVA程序,其中app_process命令位于源码目录下的frameworks/base/cmds/app_process目录下,其命令的使用方法如下:

Usage: app_process [java-options] cmd-dir start-class-name [options]

其中我们文件里的$base/bin对应的是命令所在的目录,com.cmds.xinu.Sbstate为我们的JAVA代码的入口类,即main函数所在的类名,而$*是将命令行输入的任何参数传递作为main函数的参数列表。

Android.mk文件内容:

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文件复制到目标目录的system/bin目录下,我这边测试时是手动把sbstate文件复制到/system/bin目录下,此时需要注意该文件的权限,不然会有Permission Deny之类的提示。

由于我们放在源码里编译,如果直接这样mm一下,是会出错的,我们还需要修改Android源码的编译配置,涉及到如下文件:

1、build/core/legacy_prebuilts.mk

对应于Android.mk里要用到的prebuilt功能,主要是把sbstate文件复制到/system/bin目录下,不加的话会提示预编译失败;

在文件中修改GRANDFATHERED_ALL_PREBUILT配置项,添加上sbstate。

2、build/core/user_tags.mk

对应于Android.mk里要用到的编译为JAR功能,在文件中修改GRANDFATHERED_USER_MODULES配置项,添加上sbstate。

至此,整个编译配置及源码就实现好了,接下来只需要mm一下,复制或者烧录一下,就可以在命令行(串口或者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

此时,我们可以输入如下形式的命令来执行相应的功能:

1、显示状态栏:sbstate sbvis

2、隐藏状态栏:sbstate sbdis

3、显示BACK按钮图标:sbstate bvis

4、隐藏BACK按钮图标:sbstate bdis

5、显示HOME按钮图标:sbstate hvis

6、隐藏HOME按钮图标:sbstate hdis

7、显示RECENT按钮图标:sbstate rvis

8、隐藏RECENT按钮图标:sbstate rdis

好了,亲手尝试一下吧,见证状态栏的风起云涌,变幻莫测吧。

更多相关文章

  1. NPM 和webpack 的基础使用
  2. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  3. Android(安卓)项目在Eclipse中的目录结构
  4. android adb
  5. Android(安卓)系统log抓取,实现原理分析
  6. Android(安卓)NDK编程入门笔记
  7. android init进程说明
  8. Android(java)学习笔记135:Android中assets文件夹资源的访问
  9. Android程序结构

随机推荐

  1. 关于SQL的几道小题详解(sql进阶)
  2. 深入分析SQL Server 存储过程
  3. SQL函数substr使用简介
  4. SqlServer中查看当前Open的Cursor方法
  5. 介绍备份和还原MySQL数据的两种方法
  6. 调整SQLServer2000运行中数据库结构
  7. Select count(*)、Count(1)和Count(列)的
  8. SQL Server中将数据导出为XML和Json方法
  9. SQL Server中将查询结果转换为Json格式脚
  10. Sql Server中的DBCC命令详细介绍