关注嵌入式安卓物联网行业及人才培养,每日更新,欢迎订阅及留言讨论~~~

作者:倪键树,嵌入式安卓物联网讲师。



让你自己编写的AndroidLauncher成为系统中第一个启动应用程序,也是唯一的Launcher


如果你要定制一个Android系统,你想用你自己的Launcher(Home)作主界面来替换Android自带的Home,而且不希望用户安装的Launcher来替换掉你的Launcher,应该如何来实现呢?

我们可以通过修改Framework层来实现这样的功能。


1)首先了解一下Android的启动过程。

Android系统的启动先从Zygote开始启动,然后......(中间的过程就不说了).....一直到了SystemServer(framework)这个地方,看到这段代码:


/**

* This method is called from Zygote to initialize the system. This willcause the native

* services (SurfaceFlinger, AudioFlinger, etc..) to be started. Afterthat it will call back

* up into init2() to start the Android services.

*/

native public static void init1(String[] args);


public static void main(String[] args) {

if (SamplingProfilerIntegration.isEnabled()) {

SamplingProfilerIntegration.start();

timer = new Timer();

timer.schedule(new TimerTask() {

@Override

public void run() {

SamplingProfilerIntegration.writeSnapshot("system_server");

}

}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);

}


// The system server has to run all of the time, so it needs to be

// as efficient as possible with its memory usage.

VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);


System.loadLibrary("android_servers");

init1(args);

}


public static final void init2() {

Log.i(TAG, "Entered the Android system server!");

Thread thr = new ServerThread();

thr.setName("android.server.ServerThread");

thr.start();

}

}


SystemServermain函数开始启动各种服务:

首先启动init1,然后启动init2.从上面的注释可以看到:init1这个方法时被Zygote调用来初始化系统的,init1会启动native的服务如SurfaceFlinger,AudioFlinger等等,这些工作做完以后会回调init2来启动Androidservice


这里我们主要来关注init2的过程。init2中启动ServerThread线程,ServerThread中启动了一系列的服务,比如这些:


ActivityManagerService

EntropyService

PowerManagerService

TelephonyRegistry

PackageManagerService

AccountManagerService

BatteryService

HardwareService

Watchdog

SensorService

BluetoothService

StatusBarService

ClipboardService

InputMethodManagerService

NetStatService

ConnectivityService

AccessibilityManagerService

NotificationManagerService

MountService

DeviceStorageMonitorService

LocationManagerService

SearchManagerService

FallbackCheckinService

WallpaperManagerService

AudioService

BackupManagerService

AppWidgetService


这些大大小小的服务起来以后,开始

((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady()

systemReady后开始开始启动Launcher在寻找Launcher的时候是根据HOMEfilter(在Manifest中定义的<categoryandroid:name="android.intent.category.HOME" />)来过滤。

然后根据filter出来的HOME来启动,如果只有一个HOME,则启动这个HOME,如果用户自己装了HOME,那就会弹出来一个列表供用户选择。


我们现在希望从这里弹出我们自己定制的Launcher,同时也不希望弹出选择HOME的界面,我们不希望用户修改我们的home,比如我们的home上放了好多广告,以及强制安装的程序,不希望用户把它干掉。


我们可以通过这样来实现:


2) 定义一个私有的filter选项,然后用这个选项来过滤HOME.

一般情况下我们使用Manifest中定义的<categoryandroid:name="android.intent.category.HOME"来过滤的,我们现在增加一个私有的HOME_FIRST过滤。


Intent.java(frameworks/base/core/java/android/content/Intent.java)中添加两行代码


//lixinso:添加CATEGORY_FS_HOME

@SdkConstant(SdkConstantType.INTENT_CATEGORY)

public static final String CATEGORY_FS_HOME= "android.intent.category.FS_HOME";


3)修改和CATEGORY_HOME相关的所有的地方,都改成CATEGORY_FS_HOME,主要是framework中的这几个地方:使用grep命令查找要修改的地方:


grep CATEGORY_HOME -l * -R


102331449.png

102344831.png

将上述文件中CATEGORY_HOME相关的所有的地方,都改成CATEGORY_FS_HOME

4) 写一个自己的Launcher.

可以参考android sample中的Launcher,或者android源代码中的 /packages/apps/Launcher 来写。

Launcher中标记其是不是Launcher的最关键的代码时Manifest中的filter:android:name="android.intent.category.HOME"

现在我们定义了自己的filter,那么,我们在我们自己写的Launcher中将Manifest改为:

<application android:process="android.process.acore3"android:icon="@drawable/icon"android:label="@string/app_name">

<activity android:name=".FirstAppActivity"

android:label="@string/app_name">

<intent-filter>

<actionandroid:name="android.intent.action.MAIN" />

<categoryandroid:name="android.intent.category. FS_HOME" />

<categoryandroid:name="android.intent.category.DEFAULT" />

<category android:name="android.intent.category.MONKEY"/>

</intent-filter>

</activity>

</application>


然后将编译好的apk放到方式fs100_root/system/app目录下。


5)Android自带的Launcher删除掉

包括源代码(packages/apps/Launcher)apk(/out/target/product/generic/system/app/Launcher.apk)


6) 重新编译Android

做完这些工作,就可以重新编译Android了,我们可以编译修改过的几个相关的包,可以用mmm命令来编译部分的改动。这里需要这样编译:


$ source build/envsetup.sh

$ lunch

$ mmm frameworks/base

$ mmm frameworks/base/services/java

$ mmm frameworks/policies/base/mid

$ mmm frameworks/policies/base/phone



重新启动开发板,从开发板上就可以看到启动的Launcher是我们自己的Launcher,不会出现默认的Launcher了,也不会出现选择界面。


9)我们再验证一下,如果用户装上了一个其他的Launcher(Home)会怎么样。

从网上找一个一般的Launcher或者自己写一个一般的Launcher装上去,重新启动,不会出现选择界面。

HOME键也不会出来两个HOME来选择。



这样我们就牢牢控制了用户的桌面。

只有我们自己定制的HOME才能装上。这对于定制Android设备的厂商很有用处。




更多相关文章

  1. android 自定义menu及 Error parsing XML: no element found问题
  2. android XML动画初步解析(activity界面之间跳转demo)
  3. Android中自定义控件的步骤
  4. Android Studio多个用户界面的程序设计(一)
  5. Android UI设计之自定义TextView属性,实现带边框效果的TextView

随机推荐

  1. android中进行https连接的方式(源码)
  2. Android(安卓)Intent 总结
  3. android 自动弹出软件盘
  4. 《android ScrollView嵌套RecycleView滑
  5. android调用系统邮件发送图片文本
  6. android实现屏幕全屏
  7. 使用internal(com.android.internal)和hidd
  8. android ImageButton显示本地图片
  9. Android 图像系列: 将本地图片加载到Draw
  10. android 读取json数据(遍历JSONObject和JS