Android

Unity 开发之 Android 必要的基础知识(二)

2022-08-17 #Unity#Android

本文迁移自旧站,保留当时的学习记录;涉及版本与实践结论的内容会在后续复查中逐步更新。

AndroidManifest清单文件(一)

官方文档

概念

清单文件用于向 Android 构建工具、Android 操作系统和 Google Play 描述应用的基本信息

划重点,清单文件需声明以下内容:

  • 声明包名、icon、SDK等等应用信息: 应用的软件包名称,其通常与代码的命名空间相匹配。 构建项目时,Android 构建工具会使用此信息来确定代码实体的位置。 打包应用时,构建工具会使用 Gradle 构建文件中的应用 ID 来替换此值,而此 ID 则用作系统和 Google Play 上的唯一应用标识符。

  • 注册四大组件: 应用的组件,包括所有 Activity、Service、Broadcast reciver和Content provider。 每个组件都必须定义基本属性,例如其 Kotlin 或 Java 类的名称。 清单文件还能声明一些功能,例如其所能处理的设备配置,以及描述组件如何启动的 Intent 过滤器。

  • 申请必要的权限: 应用为访问系统或其他应用的受保护部分所需的权限。 如果其他应用想要访问此应用的内容,则清单文件还会声明其必须拥有的权限。

  • 应用需要的硬件和软件功能: 这些功能会影响哪些设备能够从 Google Play 安装应用

标签

官方文档 对于在应用中创建的每个应用组件,您必须在清单文件中声明相应的 XML 元素:

  • 用于 ```Activity``` 的每个子类。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    - ```<service>``` 用于 ```Service``` 的每个子类。
    - ```<receiver>``` 用于 ```BroadcastReceiver``` 的每个子类。
    - ```<provider>``` 用于 ```ContentProvider``` 的每个子类。

    **如果您创建此类组件的任何子类,但未在清单文件中对其进行声明,则系统便无法启动该子类。**

    这是一份从unity导出的Android工程中的清单文件

    ```xml
    <?xml version="1.0" encoding="utf-8"?>
    <!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools">
    <application android:isGame="true">
    <uses-library
    android:name="org.apache.http.legacy"
    android:required="false" />
    <activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector" android:screenOrientation="sensorPortrait" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:resizeableActivity="false" android:hardwareAccelerated="false" android:exported="true">
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
    <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
    </intent-filter>
    <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
    <meta-data android:name="android.notch_support" android:value="true" />
    </activity>
    <meta-data android:name="unity.splash-mode" android:value="0" />
    <meta-data android:name="unity.splash-enable" android:value="True" />
    <meta-data android:name="unity.allow-resizable-window" android:value="False" />
    <meta-data android:name="notch.config" android:value="portrait|landscape" />
    <meta-data android:name="unity.build-id" android:value="20d9d69c-7bcf-4746-ac6b-9dff6c6c7753" />
    <!-- Google Play Services -->
    <meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />

    <!--添加Google AdMob App ID-->
    <!--官方测试APPID,正式上线更换-->
    <meta-data
    android:name="com.google.android.gms.ads.APPLICATION_ID"
    android:value="xxxxxxxxxxxxxxxxxxxxxx"/>
    <!--AppLovin -->
    <!--添加您的Applovin SDK Key-->
    <meta-data
    android:name="applovin.sdk.key"
    android:value="xxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
    </application>
    <uses-feature android:glEsVersion="0x00020000" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" android:required="false" />
    <uses-feature android:name="android.hardware.location" android:required="false" />
    <uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
    <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
    <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
    </manifest>

applicaltion标签

二级标签,配置项目级的参数,如 debuggable、enabled、description 和 allowClearUserData,或者为组件属性设置全局默认值,且组件可以再自己的标签内定义覆盖,比如icon、label等。

一般情况下不需要更改

咱们也可以自定义一个 MyApplication 类继承自 Application 类来在应用启动时做些业务,然后在清单中applicaltion标签下设置 android:name=.MyApplication属性来告诉系统用自定义的application类启动

包含于:

1
<manifest>

可包含:

1
2
3
4
5
6
7
8
9
<activity>
<activity-alias>
<meta-data>
<service>
<receiver>
<profileable>
<provider>
<uses-library>
<uses-native-library>

activity标签

如果是由Unity导出,默认只会有一个UnityPlayerActivity作为启动Activity,咱们游戏的主要业务都会在这个activity中

但是通常会定义一个SplashActivity作为启动的Activity,用于在进入到游戏业务前做一些业务,比如第三方sdk的初始化,权限申请,原生androidAPI调用之类的工作,然后再跳转到UnityPlayerActivity

UnityPlayerActivity这个类是不建议修改的,但是某些业务游戏要在UnityPlayerActivity生命周期中添加业务代码,尤其是第三方sdk的业务,这个时候就需要定义一个MainActivity继承自UnityPlayerActivity,然后在MainActivity中重写生命周期方法,添加自己的业务代码,同时别忘了在清单中注册MainActivity


<activity> 包含于 <application>

可包含
1
2
3
4
5
6


```xml
<intent-filter>
<meta-data>
<layout>

以上面清单中的activity标签为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<activity
android:name="com.unity3d.player.UnityPlayerActivity"
android:theme="@style/UnityThemeSelector"
android:screenOrientation="sensorPortrait"
android:launchMode="singleTask"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density"
android:resizeableActivity="false"
android:hardwareAccelerated="false"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="android.notch_support" android:value="true" />
</activity>
属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

这里有一大堆配置项,按官方说法,这个属性列出了 Activity 将自行处理的配置变更。在运行时发生配置变更时,默认情况下会关闭 activity 并将其重启,但使用该属性声明配置将阻止 activity 重启。相反,Activity 会保持运行状态,并且系统会调用其 onConfigurationChanged() 方法。

以下是该属性的有效值,若要配置多个则用 “ \| ” 分割

| 值 | 说明 |
|--------------|------------------------------------|
|density | 显示密度发生变更 - 用户可能已指定不同的显示比例,或者有不同的显示现处于活跃状态。在 API 级别 24 中引入|
|fontScale | 字体缩放系数发生变更 - 用户已选择新的全局字号。|
|keyboard | 键盘类型发生变更 - 例如,用户插入外置键盘。|
|keyboardHidden|键盘无障碍功能发生变更 - 例如,用户显示硬键盘。|
|layoutDirection|布局方向发生变更 - 例如,自从左至右 (LTR) 更改为从右至左 (RTL)。在 API 级别 17 中引入。|
|locale|语言区域发生变更 - 用户已为文本选择新的显示语言。|
|mcc|IMSI 移动设备国家/地区代码 (MCC) 发生变更 - 检测到 SIM 并更新 MCC。|
|mnc|IMSI 移动设备网络代码 (MNC) 发生变更 - 检测到 SIM 并更新 MNC。|
|navigation|导航类型(轨迹球/方向键)发生变更。(这种情况通常不会发生。)|
|orientation|屏幕方向发生变更 - 用户旋转设备。 ( **注意:如果应用面向 Android 3.2(API 级别 13)或更高版本的系统,则还应声明 "screenSize" 和 "screenLayout" 配置,因为当设备在纵向模式与横向模式之间切换时,该配置也会发生变更。** ) |
|screenLayout|屏幕布局发生变更 - 现处于活跃状态的可能是其他显示模式。|
|screenSize| 当前可用屏幕尺寸发生变更。该值表示目前可用尺寸相对于当前宽高比的变更,当用户在横向模式与纵向模式之间切换时,它便会发生变更。在 API 级别 13 中引入。|
|smallestScreenSize|物理屏幕尺寸发生变更。该值表示与方向无关的尺寸变更,因此它只有在实际物理屏幕尺寸发生变更(如切换到外部显示器)时才会变化。对此配置所作变更对应 smallestWidth 配置的变化。 在 API 级别 13 中引入。|
|touchscreen|触摸屏发生变更。(这种情况通常不会发生。)|
|uiMode|界面模式发生变更 - 用户已将设备置于桌面或车载基座,或者夜间模式发生变更。如需了解有关不同界面模式的更多信息,请参阅 UiModeManager。在 API 级别 8 中引入。|


``` android:exported ``` 属性

此元素设置 Activity 是否可由其他应用的组件启动
- 如果设为“true”,那么 Activity 可由任何应用访问,并且可通过其确切类名称启动。
- 果设为“false”,则 Activity 只能由同一应用的组件、使用同一用户 ID 的不同应用或具有特权的系统组件启动。 没有 intent 过滤器时,这是默认值。

***如果应用中的 Activity 包含 intent 过滤器,请将此元素设置为“true”,以允许其他应用启动该 Activity。例如,假设 Activity 是应用的主要 Activity,并且包含 category“android.intent.category.LAUNCHER”。***

``` android:launchMode ``` 属性

启动模式,有机会另起一篇,对于Unity导出,没特殊情况,使用默认的 ``` singleTask ``` 即可

还有很多属性,详情可参考 [官方文档](https://developer.android.com/guide/topics/manifest/activity-element)

### intent-filter 标签

必须包含 ```<action>```

可包含 ```<category> <data>```

一般包含于四大组件的标签中,指定 Activity、服务或广播接收器可以响应的 intent 类型。Intent 过滤器声明其父组件的功能 - Activity 或服务可执行哪些操作,以及接收器可处理哪些类型的广播。它让组件可以接收所通告类型的 Intent,同时过滤掉对组件没有意义的 Intent。

过滤器的大部分内容由它的 ```<action>、<category>``` 和 ```<data>``` 子元素进行描述。

简单的开发只需要了解 ```<action android:name="android.intent.action.MAIN" />``` 和 ```<category android:name="android.intent.category.LAUNCHER" />```

```<action android:name="android.intent.action.MAIN" />``` 指定了程序的启动Activity,

```<category android:name="android.intent.category.LAUNCHER" />``` 决定了是否会在程序列表里面显示,也就是会不会出现在手机桌面上,声明了这个属性就会在桌面上出现图标,多个Activity的 ``` <intent-filter>``` 声明了这个 ```category``` 就会在桌面显示多个图标

### meta-data标签


```xml
<meta-data
android:name="mymeta-Data"
android:resource="resource specification"
android:value="string" />

元数据标签,可以包含于任意组件标签且可以有任意数量

主要作用就是存储信息,整个应用都可以访问,有点类似配置表,最常见是就是在接入第三方sdk时会要求加入 meta-data 标签记录 APPKEY

那怎么读取呢

1
2
3
ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
Bundle bundle = ai.metaData;
String myApiKey = bundle.getString("mymeta-Data");
评论
分享