Android 如何将定制的Launcher成为系统中唯一的Launcher

简介: Android 如何将定制的Launcher成为系统中唯一的Launcher

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

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

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

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

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

   /**
     * This method is called from Zygote to initialize the system. This will cause the native
     * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that 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();
    }

从SystemServer的main函数开始启动各种服务。

首先启动init1,然后启动init2.

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

这里我们主要来关注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的时候是根据HOME的filter(在Manifest中定义的)来过滤。

然后根据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)中添加两行代码
    //lixinso:添加CATEGORY_HOME_FIRST
    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
    public static final String CATEGORY_HOME_FIRST = “android.intent.category.HOME_FIRST”;
3)修改和CATEGORY_HOME相关的所有的地方,都改成HOME_FIRST,主要是framework中的这几个地方:
    frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中
    //intent.addCategory(Intent.CATEGORY_HOME);
    改成intent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso:
    //if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
    改成if (r.intent.hasCategory(Intent.CATEGORY_HOME_FIRST)) { //lixinso: Intent.CATEGORY_HOME -> Intent.CATEGORY_HOME_FIRST
   frameworks/base/services/java/com/android/server/am/HistoryRecorder.java中
   // _intent.hasCategory(Intent.CATEGORY_HOME) &&
   改成 _intent.hasCategory(Intent.CATEGORY_HOME_FIRST) && //lixinso: Intent.CATEGORY_HOME->Intent.CATEGORY_HOME_FIRST
   frameworks/policies/base/mid/com/android/internal/policy/impl/MidWindowManager.java中
   //mHomeIntent.addCategory(Intent.CATEGORY_HOME);
   改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso
  frameworks/policies/base/mid/com/android/internal/policy/impl/RecentApplicationsDialog.java中
   //new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);
   改成 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso
  frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java中
   //mHomeIntent.addCategory(Intent.CATEGORY_HOME);
   改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso
  frameworks/policies/base/phone/com/android/internal/policy/impl/RecentApplicationsDialog.java中
   //ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);

  改成 ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso

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>
                                <action android:name=”android.intent.action.MAIN” />
                <category android:name=”android.intent.category.HOME_FIRST” />
                <category android:name=”android.intent.category.DEFAULT” />
                <category android:name=”android.intent.category.MONKEY” />
            </intent-filter>
        </activity>
    </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命令来编译部分的改动。

这里需要这样编译:

$ . build/envsetup.sh
$ mmm frameworks/base
$ mmm frameworks/base/services/java
$ mmm frameworks/policies/base/mid
$ mmm frameworks/policies/base/phone

7)

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

$ make snod

现在可以启动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设备的厂商很有用处。


相关文章
|
13天前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
39 15
Android 系统缓存扫描与清理方法分析
|
4天前
|
算法 JavaScript Android开发
|
7天前
|
安全 搜索推荐 Android开发
揭秘安卓与iOS系统的差异:技术深度对比
【10月更文挑战第27天】 本文深入探讨了安卓(Android)与iOS两大移动操作系统的技术特点和用户体验差异。通过对比两者的系统架构、应用生态、用户界面、安全性等方面,揭示了为何这两种系统能够在市场中各占一席之地,并为用户提供不同的选择。文章旨在为读者提供一个全面的视角,理解两种系统的优势与局限,从而更好地根据自己的需求做出选择。
20 2
|
15天前
|
安全 搜索推荐 Android开发
深入探索安卓与iOS系统的差异及其对用户体验的影响
在当今的智能手机市场中,安卓和iOS是两大主流操作系统。它们各自拥有独特的特性和优势,为用户提供了不同的使用体验。本文将深入探讨安卓与iOS系统之间的主要差异,包括它们的设计理念、用户界面、应用生态以及安全性等方面,并分析这些差异如何影响用户的使用体验。
|
15天前
|
安全 搜索推荐 Android开发
揭秘iOS与Android系统的差异:一场技术与哲学的较量
在当今数字化时代,智能手机操作系统的选择成为了用户个性化表达和技术偏好的重要标志。iOS和Android,作为市场上两大主流操作系统,它们之间的竞争不仅仅是技术的比拼,更是设计理念、用户体验和生态系统构建的全面较量。本文将深入探讨iOS与Android在系统架构、应用生态、用户界面及安全性等方面的本质区别,揭示这两种系统背后的哲学思想和市场策略,帮助读者更全面地理解两者的优劣,从而做出更适合自己的选择。
|
6天前
|
安全 搜索推荐 程序员
深入探索Android系统的碎片化问题及其解决方案
在移动操作系统的世界中,Android以其开放性和灵活性赢得了广泛的市场份额。然而,这种开放性也带来了一个众所周知的问题——系统碎片化。本文旨在探讨Android系统碎片化的现状、成因以及可能的解决方案,为开发者和用户提供一种全新的视角来理解这一现象。通过分析不同版本的Android系统分布、硬件多样性以及更新机制的影响,我们提出了一系列针对性的策略,旨在减少碎片化带来的影响,提升用户体验。
|
6天前
|
安全 Android开发 iOS开发
深入探索iOS与Android系统的差异性及优化策略
在当今数字化时代,移动操作系统的竞争尤为激烈,其中iOS和Android作为市场上的两大巨头,各自拥有庞大的用户基础和独特的技术特点。本文旨在通过对比分析iOS与Android的核心差异,探讨各自的优势与局限,并提出针对性的优化策略,以期为用户提供更优质的使用体验和为开发者提供有价值的参考。
|
8天前
|
安全 Android开发 iOS开发
安卓系统与iOS系统的比较####
【10月更文挑战第26天】 本文将深入探讨安卓(Android)和iOS这两大主流移动操作系统的各自特点、优势与不足。通过对比分析,帮助读者更好地理解两者在用户体验、应用生态、系统安全等方面的差异,从而为消费者在选择智能手机时提供参考依据。无论你是技术爱好者还是普通用户,这篇文章都将为你揭示两大系统背后的故事和技术细节。 ####
20 0
|
1月前
|
IDE Android开发 iOS开发
探索安卓与iOS系统的技术差异:开发者的视角
本文深入分析了安卓(Android)与苹果iOS两大移动操作系统在技术架构、开发环境、用户体验和市场策略方面的主要差异。通过对比这两种系统的不同特点,旨在为移动应用开发者提供有价值的见解,帮助他们在不同平台上做出更明智的开发决策。
|
1月前
|
Ubuntu Shell API
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a
Ubuntu 64系统编译android arm64-v8a 的openssl静态库libssl.a和libcrypto.a