定制替换Android桌面(home screen)

发表于304 天前编程开发评论数 1

替换Android桌面的相关问题:

1、想将home screen换成自己写的activity,该如何实现?

在你要设置为home screen的那个activityandroidManifest.xml中的<intent-filter>标签中加上这几句 <category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
运行后,重启模拟器会弹出一个选择进入哪个界面的对话框

2、怎样将系统默认的home screen删除?

重新编译launcher源码,去掉配置文件中的home属性和HOME属性。。
在自己的activity中加入这两个属性,然后重新烧系统。

以下是定制Android的完整思路和步骤:

如果你要定制一个Android系统,你想用你自己的Launcher(Home)作主界面来替换Android自己的Home,而且不希望用户安装的Launcher来替换掉你的Launcher.
我们可以通过修改Framework来实现这样的功能。

这里以Android2.1的源代码为例来实际说明。

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


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

1. /**

2. * This method is called from Zygote to initialize the system. This will cause the native

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

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

5. */

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

7.

8. public static void main(String[] args) {

9. if (SamplingProfilerIntegration.isEnabled()) {

10. SamplingProfilerIntegration.start();

11. timer = new Timer();

12. timer.schedule(new TimerTask() {

13. @Override

14. public void run() {

15. SamplingProfilerIntegration.writeSnapshot(“system_server”);

16. }

17. }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);

18. }

19.

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

21. // as efficient as possible with its memory usage.

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

23.

24. System.loadLibrary(“android_servers”);

25. init1(args);

26. }

27.

28. public static final void init2() {

29. Log.i(TAG, “Entered the Android system server!”);

30. Thread thr = new ServerThread();

31. thr.setName(“android.server.ServerThread”);

32. thr.start();

33. }

34. }

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

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

1. ActivityManagerService

2. EntropyService

3. PowerManagerService

4. TelephonyRegistry

5. PackageManagerService

6. AccountManagerService

7. BatteryService

8. HardwareService

9. Watchdog

10. SensorService

11. BluetoothService

12. StatusBarService

13. ClipboardService

14. InputMethodManagerService

15. NetStatService

16. ConnectivityService

17. AccessibilityManagerService

18. NotificationManagerService

19. MountService

20. DeviceStorageMonitorService

21. LocationManagerService

22. SearchManagerService

23. FallbackCheckinService

24. WallpaperManagerService

25. AudioService

26. BackupManagerService

27. AppWidgetService

这些大大小小的服务起来以后,开始
((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady()
systemReady后开始开始启动Launcher

在寻找Launcher的时候是根据HOMEfilter(在Manifest中定义的<category android:name=”android.intent.category.HOME” />)来过滤。
然后根据filter出来的HOME来启动,如果只有一个HOME,则启动这个HOME,如果用户自己装了HOME,那就会弹出来一个列表供用户选择。

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

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

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


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

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

1. //添加CATEGORY_HOME_FIRST

2. @SdkConstant(SdkConstantType.INTENT_CATEGORY)

3. public static final String CATEGORY_HOME_FIRST = “android.intent.category.HOME_FIRST”;

3)修改和CATEGORY_HOME相关的所有的地方,都改成HOME_FIRST,主要是framework中的这几个地方:

1. frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

2. //intent.addCategory(Intent.CATEGORY_HOME);

3. 改成intent.addCategory(Intent.CATEGORY_HOME_FIRST);

4. //if(r.intent.hasCategory(Intent.CATEGORY_HOME)){

5. 改成if (r.intent.hasCategory(Intent.CATEGORY_HOME_FIRST)){ //Intent.CATEGORY_HOME->Intent.CATEGORY_HOME_FIRST

6.

7. frameworks/base/services/java/com/android/server/am/HistoryRecorder.java

8. //_intent.hasCategory(Intent.CATEGORY_HOME)&&

9. 改成_intent.hasCategory(Intent.CATEGORY_HOME_FIRST)&& //Intent.CATEGORY_HOME->Intent.CATEGORY_HOME_FIRST

10.

11. frameworks/policies/base/mid/com/android/internal/policy/impl/MidWindowManager.java

12. //mHomeIntent.addCategory(Intent.CATEGORY_HOME);

13. 改成mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST);

14.

15. frameworks/policies/base/mid/com/android/internal/policy/impl/RecentApplicationsDialog.java

16. //newIntent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);

17. 改成 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0);

18.

19. frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java

20. //mHomeIntent.addCategory(Intent.CATEGORY_HOME);

21. 改成mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST);

22.

23. frameworks/policies/base/phone/com/android/internal/policy/impl/RecentApplicationsDialog.java

24. //ResolveInfohomeInfo=pm.resolveActivity(newIntent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);

25. 改成ResolveInfohomeInfo=pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0);

4) 写一个自己的Launcher.


可以参考android sample中的Launcher,或者android源代码中的 /packages/apps/Launcher 来写。
Launcher中标记其是不是Launcher的最关键的代码时Manifest中的filter:android:name=”android.intent.category.HOME”
现在我们定义了自己的filter,那么,我们在我们自己写的Launcher中将Manifest改为:

1. <applicationandroid:process=”android.process.acore3″android:icon=”@drawable/icon”android:label=”@string /app_name”>

2. <activityandroid:name=”.FirstAppActivity”

3. android:label=”@string /app_name”>

4. <intent-filter>

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

6. <categoryandroid:name=”android.intent.category.HOME_FIRST”/>

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

8. <categoryandroid:name=”android.intent.category.MONKEY”/>

9. </intent-filter>

10. </activity>

11. </application>

然后将编译好的apk放到/out/target/product/generic/system/app目录下。

5)Android自带的Launcher删除掉,

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

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

1. $.build/envsetup.sh

2. $mmmframeworks/base

3. $mmmframeworks/base/services/java

4. $mmmframeworks/policies/base/mid

5. $mmmframeworks/policies/base/phone

7)编译完成后重新生成img文件。

1. $makesnod

现在可以启动Android模拟器来看效果了。
首先设置环境变量:
$ export ANDROID_PRODUCT_OUT= ./out/target/product/generic
然后切换到
$ cd ./out/host/linux-x86/bin
运行
$ ./emulator

这样我们启动的模拟器里面用的image就是我们刚才编译好的自己定制的东西了。
从模拟器上可以看到启动的Launcher是我们自己的Launcher,不会出现默认的Launcher了,也不会出现选择界面。

9)

我们再验证一下,如果用户装上了一个其他的Launcher(Home)会怎么样。
从网上找一个一般的Launcher或者自己写一个一般的Launcher装上去,重新启动,不会出现选择界面。
HOME键也不会出来两个HOME来选择。

这样我们就牢牢控制了用户的桌面。
只有我们自己定制的HOME才能装上。 这对于定制Android设备的厂商很有用处。

更多相关文章

  1. 解决使用Android(安卓)emulator(模拟器)无法上网的现象
  2. android之蓝牙开发续(自动配对)
  3. android 运用取消默认的window preview
  4. 破解Xamarin
  5. Android(安卓)设置 横屏 竖屏
  6. Android(安卓)ui utils-简单实用的Android界面工具
  7. Android开发系列之搭建开发环境
  8. 绕过身份检测,破解Android(安卓)SU
  9. Android(安卓)判断App运行在模拟器还是真机上的最终解决方案

随机推荐

  1. VUE:购物车页面:全选按钮 & 代码练习
  2. APICloud可视化开发初体验
  3. APP可视化开发,一键生成专业级源码,以APICl
  4. 苹果ios开发的基础语言介绍
  5. 苹果iOS开发语言用什么?
  6. 微信小程序通过code获取openid
  7. 如何学习画画?零基础学画画的步骤
  8. 人体躯干怎么画?动漫人体躯干画法
  9. WSL 2 的安装过程(以及介绍)
  10. 使用APICloud AVM多端框架开发课程表功能