`
quanminchaoren
  • 浏览: 926164 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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中定义的<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)中添加两行代码

    //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

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

分享到:
评论

相关推荐

    让你定制的Launcher成为系统中唯一的Launcher.txt

    ### 让你定制的Launcher成为系统中唯一的Launcher 在Android系统中,Launcher(启动器)是用户与系统交互的重要界面之一。它不仅负责显示应用程序图标、桌面小部件等元素,还承担着启动应用的重要职责。为了让...

    Android 4.0 Launcher2 源码 Eclipse版(已修改包名,不冲突系统桌面)

    在 Android 系统中,每个应用都有自己的唯一标识(包名),如果两个应用使用相同的包名,系统将无法区分它们,可能会导致运行时错误。 6. **Eclipse 版**: 提供的是 Eclipse 开发环境下的源码,这意味着开发者可以...

    一种加快定制android系统桌面快捷图标的方法.docx

    在Android系统中,用户通常需要通过应用程序列表选择应用并将其拖动到桌面创建快捷方式,这一过程在批量定制或频繁操作时效率较低。针对这一问题,本发明提供了一种有效加快定制Android系统桌面快捷图标的方法。 ...

    AnderWeb-android_packages_apps_Launcher-4458ee4.zip

    "Launcher"在Android系统中通常指的是桌面启动器,它是用户界面的核心部分,允许用户打开应用、管理屏幕快捷方式和小部件。4458ee4可能是该版本的标识符或Git提交哈希,用于追踪代码的特定版本。 在深入讨论之前,...

    AnderWeb-android_packages_apps_Launcher-4458ee4_Android.rar

    这里提到的"android_packages_apps_Launcher"表明这是Android系统中的一个应用包,专门用于启动器功能。 2. **启动器的定制**:自定义启动器通常允许用户自定义主屏幕的图标、布局、小部件、过渡效果等。它们可能还...

    给Android的应用换个图标(桌面快捷图标)sShortcut

    总的来说,更换Android应用图标涉及到Android系统的深度定制,需要对Android的组件、意图、权限管理有深入理解。同时,随着Android系统的不断更新,开发者需要持续关注并适应新的安全和隐私策略,以确保工具的兼容性...

    A83T Android快速移植指南

    以上内容概括了“A83T Android快速移植指南”中的关键知识点和技术细节,涵盖了从系统定制到模块配置、再到个性化设置的各个方面。这对于理解和操作基于A83T平台的Android设备具有重要的参考价值。

    安卓Android源码——隐藏安装包图标使用其他应用启动本应用.zip

    在安卓(Android)系统中,隐藏安装包的图标并使用其他应用启动本应用是一种常见的定制化需求,尤其在开发特定类型的App时,如系统服务或后台应用。这种做法可以让用户在主屏幕上看不到应用的图标,但依然可以通过...

    Android发送通知Notification

    在Android开发中,发送通知是将消息展示给用户的重要手段,尤其当应用在后台运行时。`Notification`类是Android SDK中的核心组件,用于在状态栏或者通知中心创建和管理通知。下面我们将深入探讨如何在Android应用中...

    创建快捷方式

    在Android系统中,创建应用快捷方式是为用户提供更便捷访问特定功能或Activity的方式。通过创建快捷方式,用户可以在主屏幕上直接点击图标,快速启动应用程序的某个特定页面,而无需每次都打开整个应用。以下是对这...

    自定义布局通知栏

    在Android开发中,自定义布局通知栏是一种常见且重要的功能,它允许开发者为用户提供更加个性化和交互式的体验。本文将详细讲解如何实现自定义布局的通知栏,并通过点击通知栏按钮来跳转到特定的Activity。 首先,...

    Kustom KLWP 3.38b903016.apk

    让Kustom成为有史以来最强大的动态壁纸制作者,让你的Android设备看起来独一无二!使用它令人敬畏的WYSIWYG(所见即所得)编辑器来创建您自己的设计并同时显示您需要的任何数据,并且还可以使用精彩的动画!如果您在...

    高仿小米电视luncher控件.rar

    在实际使用中,开发者需要具备一定的Android开发知识,包括Java或Kotlin编程、Android SDK、XML布局理解以及对Android系统服务和组件的了解。通过研究和修改这些代码,开发者可以定制自己的电视应用界面,或者改进...

    Android Notification通知解析

    本文将深入解析Android Notification的使用方法,帮助开发者理解如何创建、管理和控制这些通知。 首先,我们需要获取到系统的NotificationManager服务。这是管理所有通知的核心组件,可以通过调用`Context....

    android中创建通知栏Notification代码实例

    本文将详细介绍如何在Android中创建一个通知栏通知,并通过代码实例来解释各个步骤。 首先,我们需要获取`NotificationManager`的实例,它是管理所有通知的系统服务。可以通过`getSystemService`方法获取,传入`...

    Android中new Notification创建实例的最佳方法

    本文将详细介绍如何在Android中以最佳方式创建Notification实例。 在早期的Android版本中,创建Notification的方式如下: ```java Notification notification = new Notification(R.drawable.ic_launcher,"This is...

    Android中关于Notification及NotificationManger的详解

    在Android应用开发中,Notification和NotificationManager是两个关键组件,用于在系统状态栏显示非侵入性的用户提醒。本文将详细解析这两个组件的工作原理和使用方法。 首先,Notification是Android系统提供的一种...

    htc桌面天气实测可修改城市版

    1. **HTC 桌面环境**:HTC手机采用的定制化Android系统通常会有自家的桌面环境,这包括启动器(Launcher)、小部件和其他个性化设置。这些桌面环境通常会集成一些特色功能,比如天气显示。 2. **天气小部件**:天气...

Global site tag (gtag.js) - Google Analytics