CarLauncher
路径
/packages/apps/Car/Launcher
main文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.car.carlauncher">
<!-- System permission to access the CarProjectionManager for projection status-->
<uses-permission android:name="android.car.permission.ACCESS_CAR_PROJECTION_STATUS"/>
<!-- System permission to host maps activity -->
<uses-permission android:name="android.permission.ACTIVITY_EMBEDDING"/>
<!-- Permission for the InCallController to bind the InCallService -->
<uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
<!-- System permission to send events to hosted maps activity -->
<uses-permission android:name="android.permission.INJECT_EVENTS"/>
<!-- System permission to use internal system windows -->
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
<!-- System permission to register TaskOrganizer -->
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"/>
<!-- System permission to bring hosted maps activity to front on main display -->
<uses-permission android:name="android.permission.REORDER_TASKS"/>
<!-- System permission to remove a task -->
<uses-permission android:name="android.permission.REMOVE_TASKS"/>
<!-- System permission to query users on device -->
<uses-permission android:name="android.permission.MANAGE_USERS"/>
<!-- System permission to control media playback of the active session -->
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
<!-- System permission to get app usage data -->
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
<!-- System permission to query all installed packages -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<!-- Permission to read contacts data. Needed to display contact name on dialer card -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!-- Permission for read-only access to phone state, namely the status of any ongoing calls -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<queries>
<intent>
<action android:name="android.media.browse.MediaBrowserService" />
</intent>
</queries>
<application
android:icon="@drawable/ic_launcher_home"
android:label="@string/app_title"
android:theme="@style/Theme.Launcher"
android:supportsRtl="true">
<!--Launcher 页面 -->
<activity
android:name=".CarLauncher"
android:configChanges="uiMode|mcc|mnc"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:resumeWhilePausing="true"
android:exported="true"
android:windowSoftInputMode="adjustPan">
<meta-data android:name="distractionOptimized" android:value="true"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<!--应用 页面 -->
<activity
android:name=".AppGridActivity"
android:launchMode="singleInstance"
android:exported="true"
android:theme="@style/Theme.Launcher.AppGridActivity">
<meta-data android:name="distractionOptimized" android:value="true"/>
<intent-filter>
<action android:name="com.android.car.carlauncher.ACTION_APP_GRID"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<!--电话服务 -->
<service android:name=".homescreen.audio.telecom.InCallServiceImpl"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:exported="true">
<!-- The home app does not display the in-call UI. This is handled by the
Dialer application.-->
<meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="false"/>
<meta-data android:name="android.telecom.IN_CALL_SERVICE_CAR_MODE_UI" android:value="false"/>
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
</service>
</application>
</manifest>
包结构
核心类
CarLauncher
启动见到的首页
car_launcher.xml
<?xml version="1.0" encoding="utf-8" ?>
<!--
~ Copyright (C) 2020 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:layoutDirection="ltr"
tools:context=".CarLauncher">
<!--> 天气区域</-->
<com.android.car.ui.FocusArea
android:id="@+id/top_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginRight="@dimen/main_screen_widget_margin"
android:layoutDirection="locale"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toLeftOf="@+id/bottom_card"
app:layout_constraintBottom_toTopOf="@+id/maps_card"/>
<!--> 音乐交互区域</-->
<com.android.car.ui.FocusArea
android:id="@+id/bottom_card"
android:layout_width="0dp"
android:layout_height="0dp"
android:layoutDirection="locale"
app:layout_constraintLeft_toRightOf="@+id/top_card"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@+id/maps_card"/>
<!--> 地图区域</-->
<androidx.cardview.widget.CardView
android:id="@+id/maps_card"
style="@style/CardViewStyle"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="@dimen/main_screen_widget_margin"
android:layoutDirection="locale"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bottom_card"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
启动页
AppGridActivity
应用列表页
AppLauncherUtils
获取所有APP的方法在该类里
launcherApps.getActivityList //获取所有车载配置信息
LauncherActivityInfo
getComponentName()//获取app MainActivity信息
getLabel() //获取app的name
getBadgedIcon()//获取app图标
UsageStatsManager
设备使用情况和统计信息
getAppStandbyBucket()和queryEventsForSelf()// 不要权限
//其他方法都需要权限 android.permission.PACKAGE_USAGE_STATS
注意事项
签名类型 certificate
用于指定apk的签名方式,如果不指定,默认使用testkey签名
区别
- testkey:普通APK,默认使用该签名。
- platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。
- shared:该APK需要和home/contacts进程共享数据。
- media:该APK是media/download系统中的一环。
点击事件
xml中使用 android:onClick="xxx" 这种会失败,需要使用findViewById ,再添加点击事件的形式
<SurfaceView
android:onClick="onclick"//这种方式编译不过去
android:id="@+id/surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent" />