65.9K
CodeProject 正在变化。 阅读更多。
Home

Hallo - flavored - World

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (5投票s)

2014年7月31日

CPOL

17分钟阅读

viewsIcon

19138

适用于Google和非Google Android开发的“Hello World”示例,带有不同的应用变体。

引言

本文是 Android 教程大赛第一轮第三篇文章的一部分
尽管我们只会开发一个“Hello World”Android 应用程序,但您将学会如何调整构建过程,使其输出不仅仅是一个文件。如果您有多个应用程序变体(或构建 -“风味”),这会非常方便。

背景

大多数人接触 Android 是因为购买了新手机或平板电脑。通常是“Google Android”设备。但大约两年前,第一个非谷歌商业版 Android 分叉发布了——Amazon FireOS。现在为 Android 开发会带来一点额外的复杂性,至少如果您想迈出这一步的话。但它也可能有好处:虽然一个应用程序可能在“Android Play 商店”上不成功(因为有大量的类似应用程序),但在其他市场上可能很成功。

第一批 FireOS 设备基于 Android 2.2.3。外观和感觉完全不同,并且已经替换了许多预装应用程序。没有 Google 地图,没有 Gmail 客户端,没有 Play 商店。亚马逊将自己的服务放在设备上:Amazon App Store,由 HERE 地图(也称为诺基亚地图)提供支持的地图,以及更多。

另一方面,黑莓仍然使用自己的操作系统,但他们将其与 Android 结合。除了原生开发的应用程序(用 C++ / QML 编写)之外,该设备还可以运行 Android 应用程序。

另一个值得一提的大玩家是诺基亚。借助 Nokia X,诺基亚也发布了一款基于 Android 的手机。

下方:诺基亚 Android、黑莓 10 附带 Android 运行时、Kindle Fire 附带 FireOS 和 Google Android

4 different forks of Android

我们可以在俄罗斯或中国等其他国家找到许多其他例子。

不幸的是,即使所有提到的公司声称 75% 的应用程序 100% 兼容,但这些 Android 平台之间存在一些不兼容的功能。

一些不兼容的功能是

  1. 映射
  2. 推送通知
  3. 应用内购买。

幸运的是,其中一些平台提供自己的解决方案,例如诺基亚/Kindle Fire 的 HERE 地图。而另一些,如黑莓,则不为 Android 应用程序提供任何地图解决方案。

虽然互联网上 99% 的教程(备受赞赏)都解释了“仅 Google-Android”的设置项目和运行 Hello World App 的方法,但本教程将重点介绍称为“构建类型”和“构建风味”的构建功能。要遵循本教程,我们需要理解一些基本概念。

Android 开发基础

APK

APK 文件是一个容器,将应用程序的所有部分保持在一起。该文件是开发过程的输出。
您可以使用任何“zip”工具打开 APK 文件并查看其内容。您将找到应用程序图标、清单、应用程序证书、库、其他资源(如图标/图像/原始文件(txt、db、png 等))以及 classes.dex 文件。最后一个文件实际上包含所有代码,并编译为 dex 格式。APK 是您必须上传到商店或发送给用户的​​文件,以便让您的应用程序可供公众使用。

清单

每个应用程序必须在根目录下有一个名为 AndroidManifest.xml 的文件。此文件描述了您应用程序的所有部分。在应用程序的安装过程中,操作系统只会注册在此文件中列出的组件。
您必须在此文件中定义应用程序的名称、应用程序的图标和包名:您在应用程序世界中的唯一标识符。但您的应用程序的组件(如 Activity、Service 和 Provider)也必须在此处列出。
您也必须在此处指定权限。如果您的应用程序需要访问互联网,您必须在此处提供此信息!

示例

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.codeproject" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MyActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
  1. 第一个重要部分出现在第 3 行,package="com.example.codeproject"。这是我们唯一的标识符——包名。每个应用程序都需要一个唯一的包名。通常,您应该组合您的公司域名和您正在开发的​​产品。
    Codeproject 的示例可以是:com.codeproject.android
  2. 有关您的应用程序的所有内容都必须在 <application> 标签之间定义
    • 图标、应用名称、主题……应用程序标签的所有属性。
    • 您的所有 Activity、Service、Provider、Permissions 以及其他一些内容(如元数据)都必须包含在应用程序标签内。
  3. 最后但并非最不重要的是,第 10 行有一个 <activity> 标签。每个 Activity 都必须在 AndroidManifest 中定义。如果您尝试启动一个未在此处定义的 Activity:会抛出异常。
    • 在此示例的第 11 行中,Activity 的名称需要对于应用程序是唯一的,并在此处定义。名称是 MyActivity,名称前面的只是告诉构建脚本在包的根目录中查找文件。可以替换为 com.example.codeproject.MyActivity
    • 在第 13 行定义了此 Activity 的 intent 过滤器。我们将不详细介绍此主题:接下来的两行主要告诉操作系统
      • 此 Activity 的类别LAUNCHER,此 Activity 的操作MAIN。结合起来,这将使系统在启动器(=主屏幕)上放置一个图标,而此 Activity 是该图标的主要入口点。

Activity

Activity 代表 Android 应用程序的“表示层”。Activity 使用视图和片段来创建用户界面并与用户交互。Android 应用程序可以有多个 Activity,但它们也可以根本没有 Activity。后台服务或动态壁纸是两个可以没有自己的“表示层”的例子。但 Activity 实际上可以更多。每个 Activity 都可以被视为自己的“应用程序”,而与已安装的实际应用程序的其他 Activity 无关。

一个应用程序可以有两个 Activity 和两个主屏幕图标。每个图标都会打开一个 Activity。对于普通用户来说,他们似乎有两个应用程序,但是,当用户卸载其中一个时,这两个都会消失。一切之间的联系是 Application 类。每个应用程序都有一个 Application 类。

您不需要自己指定一个,但您可以。将这一行添加到 AndroidManifest.xml 中的应用程序标签中。

<application 
     android:name=".MainApplication" 
>

在将这一行添加到 Manifest 后,IDE(或者实际上是 IDE 背后的构建系统)现在将期望在根目录中有一个 MainApplication 类,该类扩展自 android.app.Application。您的应用程序的每个部分(Activity / Fragment / Service)都可以访问这个唯一的 Application 类。您的 Application 类是一个单例,因此所有部分都可以访问相同的 Application 实例。

片段

Fragment 通常是用户界面的一部分,可以放置在 Activity 中。也有可能将多个 Fragment 放置在一个 Activity 中。想象一个手机屏幕显示内容列表。按下一个列表项会更新视图并显示该项目的详细信息。想象一下平板电脑上的相同内容。您有更多的空间,可以并排放置两个 Fragment。

Gradle

Gradle 被用作新的 Android 构建系统。它将取代ant,后者曾用于构建应用程序。Eclipse IDE 中生成的新项目仍然使用 ant。Android Studio / IntelliJ 中生成的新项目使用 gradle。您应该避免在新项目中使用ant——可以说:Ant for Android 已被弃用。第一个库和 SDK 已经仅以 gradle 格式提供。Ant 将“不理解”这些 SDK / 库的结构。例如:最新的 Facebook Android SDK 仅适用于 gradle 类型构建。

开发人员通常不习惯去摆弄构建脚本。在所有 IDE 中,都有这个(通常是绿色的)神奇的“播放”按钮,它会为开发人员编译并运行所有内容。

然而,这个“播放”按钮总是在后台触发某种构建脚本——无论使用哪种 IDE。

构建脚本主要用于自动化构建过程和/或扩展构建过程。这些脚本被配置为获取代码和资源——编译代码,将所有内容放入容器,并提供“准备发货”的 APK、EXE 或其他任何脚本实际配置的输出。在 Android Studio 中,您可以完全控制构建脚本,也称为“gradle 文件”。

示例

apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "19.1.0"

    defaultConfig {
        applicationId "com.example.codeproject"
        minSdkVersion 14
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}
  1. apply plugin 将,您猜对了:应用 Android 插件。该插件可确保输出是 APK。它会验证您的应用程序是否具有 AndroidManifest.xml。它将您的 java 代码编译成 dex 格式……所有您不想(也不应该)去处理的魔法!
  2. android { … } 用于您的应用程序的自定义配置。包名、您要使用的构建工具、您要定位的 Android API、构建的版本号是多少……
  3. dependencies { ... } 用于将所有依赖项放在一起。默认值可确保所有库(仅 *.jar 文件)都被包含并在必要时进行编译。

$PATH 变量和命令行工具

本教程将大量使用终端。构建应用程序、设置模拟器和安装应用程序,所有这些都可以通过终端完成。为了更方便,我们需要将一些文件夹添加到系统的 $PATH 变量中。这使得一些命令 everywhere 可用(您不必在可执行文件的文件夹中才能使用它)。

我们应该将以下文件夹添加到 $PATH

  1. .../YOUR-ANDROID-SDK/platform-tools​
    • ​​adb 工具可以在此文件夹中找到。Android Device Bridge (adb) 负责与设备/模拟器的所有连接。我们将使用adb来安装我们的应用程序。
  2. .../YOUR-ANDROID-SDK/tools​
    • androidemulator 工具位于此文件夹中。
      • android 将用于创建模拟器映像
      • emulator 将运行模拟器映像
  3. .../YOUR-JAVA.SDK
    • keytooljarsigner 工具位于此文件夹中。
      • keytool 将用于创建证书。我们需要一个来签名我们的应用程序。
      • jarsigner 将使用证书来签名我们的应用程序。

项目设置

要开始,我们需要使用 Android Studio 创建一个空的 Android 项目。

  1. 启动 Android Studio。

  2. 点击窗口右侧的“New Project”(新建项目)。

  3. 输入项目名称(例如:MultiFlavors),并选择一个唯一的包名(例如 com.example.codeproject)。

  4. 保留所有默认设置。作为“Minimum SDK”(最低 SDK),我建议使用 API 14。

  5. 选择“Blank Activity”(空白 Activity)模板。

  6. 将您的 Activity 重命名为 MainActivity。这将是我们在应用程序中的入口点。

现在我们需要切换到终端并开始构建过程。选择 Android Studio 中的终端窗口并输入

./gradlew assemble

您应该会在终端窗口中看到大量输出。最重要的是

BUILD SUCCESSFUL 

作为构建的结果,我们将在 /app/builds/outputs/apk/ 文件夹中找到一些文件。

  1. app-debug.apk 文件
  2. app-release-unsigned.apk 文件
  3. app-debug-unaligned.apk

这些“未对齐”文件只是调试版本的未压缩版本。不需要,至少在本教程中不需要。我们已经可以​​将调试版本安装到设备/模拟器上。要安装发布版本,我们必须先对其进行签名。

但我们也可以在 IDE 中切换这两种构建类型。选择 Android Studio 左下角的“Build Variants”(构建变体)选项卡(左图)。通过在“app”(右图)旁选择“debug”或“release”来切换类型。但请记住:您无法立即从 IDE 安装发布版本。发布版本未签名,无法在设备/模拟器上安装未签名的 APK。调试版本使用调试密钥签名。

Build Variants

签名应用程序

所有 Android 应用程序都使用数字证书进行数字签名。您必须使用 Java SDK 附带的 jarsigner 工具。将此行输入到您的终端中。

keytool -genkey -v -keystore /Users/christoph.podkowik/my-new-release-key.keystore -alias chris -keyalg RSA -keysize 2048 -validity 10000

确保替换

  1. /Users/christoph.podkowik/my-new-release-key.keystore
    • 将其替换为您计算机上的现有路径。这就是证书将被创建的位置。
  2. -alias chris
    • 将其替换为您/您的公司的别名(例如 Codeproject)。

向导会问您一些问题,例如密码、您的姓名……

现在您可以在指定的​​位置找到您的证书。

应用程序签名可以通过多种方式完成

  1. 命令行/终端
  2. 构建过程的一部分/gradle
  3. 在 IDE 中

我建议避免第二种。您需要密码才能签名应用程序。并且您应该将构建脚本提交到 git 或任何其他源代码控制系统:两者的结合不是最好的主意。

最简单的方法是在终端中完成。您可以使用此命令执行此操作。

jarsigner -verbose -keystore /Users/christoph.podkowik/my-new-release-key.keystore /Users/christoph.podkowik/app-release.apk chris -tsa http://tsa.safecreative.org/

确保替换

  1. /Users/christoph.podkowik/my-new-release-key.keystore
    • 使用您自己的证书
  2. /Users/christoph.podkowik/app-release.apk
    • 使用您要签名的 apk 的位置
  3. chris
    • 使用您的别名

输入密码后,文件应已签名。

部署应用程序

我们有两种可能性来测试我们的应用程序。

  1. 设置模拟器
  2. 连接真实设备

我们可以完全从命令行完成第一个。大多数人使用 AVD 管理器的向导,但在终端中完成它要快得多、容易得多。如果您想在远程计算机/云上的模拟器上运行自动化测试,了解这些命令也很有用。

命令

android list targets

将显示当前 PC / Mac 上安装的可用映像列表。这些映像在 Android Studio 的项目设置过程中已安装。

第一个已经符合我们的要求。要安装模拟器,我们只需输入

android create avd -n Emulator_4_2_2 -t 1

我们只使用两个参数

  1. -n 用于模拟器的名称
  2. -t 用于已安装映像的ID(我们决定使用 id:1)

模拟器仅需几秒钟即可准备就绪。

要启动模拟器,只需输入

emulator -avd Emulator_4_2_2

现在我们只需要在设备上安装我们的应用程序。

adb install /Users/podkowik/app-release.apk

此命令将安装已签名的应用程序。

我们现在可以通过点击那个绿色的 Android 图标来启动应用程序。

要测试真实设备上的应用程序,我们首先需要启用开发者选项。自 Android 4.2 起,此选项已隐藏。太多人使用了它们,并陷入了他们无法自行解决的​​情况。

要启用它们,只需按照以下步骤操作:

  1. 转到设置 → 系统 → 关于设备/手机/平板电脑
  2. 向下滚动到 Build Number(版本号)。
  3. 反复点击它。

要最终启用调试,请按照以下步骤操作:

  1. 转到设置 → 系统 →开发者选项
  2. 现在启用 USB 调试
  3. 允许当前设备的 USB 调试

用于将应用程序安装到模拟器的相同命令也可以用于将应用程序安装到真实设备。

adb install /Users/podkowik/app-release.apk

如果您连接了更多设备或模拟器仍在后台运行,您可以指定要使用的设备。此命令将列出所有可用设备。

adb devices

有了这些信息,您可以使用以下命令安装应用程序。只需将 emulator-5554 替换为列出的设备之一。

adb -s emulator-5554 install path/to/your/app.apk

这是大多数可用“Hello World”教程结束的地方。但在这个教程中,这是乐趣开始的地方!

风味资源

在本节中,我们将最终创建我们的构建风味。

让我们打开 build.gradle 文件。它位于app文件夹内。
我们将把风味添加到“buildTypes”条目正下方。

apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "19.1.0"

    defaultConfig {
        applicationId "com.example.codeproject"
        minSdkVersion 14
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors { 
         google { } 
         nokia { } 
         kindle { } 
         blackberry { } 
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}
我们应该“同步”项目以反映我们实际所做的更改。点击 Android Studio 工具栏中的这个小按钮。

建议每次编辑任何 .gradle 文件时都执行此步骤。

IDE 应该已经识别了我们的更改,并添加了风味。如果我们再次选择 Android Studio 左下角的“Build Variants”(构建变体)选项卡(“Build Variants”),我们应该会看到此更改的结果。

让我们再次运行构建脚本并检查生成的文件。

脚本生成了很多文件。但它们都在做同样的事情:显示“Hello World”。

为了理解操作风味的基本知识,我们将更改文本,基于使用哪个 apk。

  • 首先,我们必须创建与我们在 gradle 脚本中使用的名称完全相同的文件夹。
  • 其次,我们必须在其中每个文件夹中创建一个“res”文件夹!

Android Studio 会给其中一些文件夹一个略有不同的图标。这是 IDE 可视化“当前活动资源文件夹”的方式。如果您选择另一个构建变体,图标也会改变。主文件夹中的 res 文件夹将始终保持活动状态。

现在我们需要再做两步:

  1. 在每个“res”文件夹中创建一个“values”文件夹。
  2. 在每个文件夹中创建一个 strings.xml 文件。

每个 strings.xml 文件现在都将获得一个唯一的文本。这是 kindlefire strings.xml 文件的样子:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string name="hello_world">Hello kindlefire world!</string>
</resources>

而 google 文件夹中的 strings.xml 文件将如下所示:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello_world">Hello google world!</string>
</resources>

在我们应用程序的初始设置过程中,已经在主 res 文件夹中创建了一个 string.xml 文件。

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string name="app_name">MultiFlavors</string>
   <string name="hello_world">Hello world!</string>
   <string name="action_settings">Settings</string>
</resources>

我们在这里也能找到 <string name="hello_world">。只要我们在主文件和风味中使用相同的字符串名称,构建脚本就会替换它们。优先级始终是:风味将覆盖主资源!

这对所有资源都有效。您可以覆盖:

  • 字符串
  • 图标
  • 图像
  • 颜色
  • layouts
  • the AndroidManifest file
  • 资源文件
  • ...

代码和库的处理方式略有不同,但我们稍后会处理。首先,让我们安装我们的 APK 并比较结果。

vs

尽管我们已经达到了目标,但为了使本教程完整,我们还需要处理另外两个主题。

  1. 风味代码
  2. 风味库

风味代码

我们现在将编写几行(真实)代码。开始之前,我们需要创建一些文件夹和类文件!让我们在每个风味中创建一个“src”文件夹。在每个文件夹中,我们必须添加我们的包名,并且——这是个好习惯——添加一个 fragments 文件夹!在 fragments 文件夹中,我们终于可以创建一个 MapFragment.java 类。(请记住在每个风味中都这样做)。

使用向导创建 MapFragment。右键单击 fragments 文件夹,然后选择 New-> Fragment -> Fragment (Blank)。这将生成一些样板代码。

为了区分,我们将在每个风味中创建更多字符串。

将此行放入每个 string.xml 文件中(将“google”替换为风味的名称)。

<string name="hello_blank_fragment">Hello google fragment</string>

现在,打开位于 main/res/layouts 的 activity_main.xml 文件,并将其布局更改为:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    tools:ignore="MergeRootFrame" />

此布局现在只是一个空的容器!

切换到 MainActivity,并将此代码行添加到 onCreate 方法中。

if (savedInstanceState == null) 
{
    getFragmentManager().beginTransaction()
        .add(R.id.container, new MapFragment())
        .commit();
}

每次我们启动应用程序时,此代码都会将 MapFragment 添加到我们的容器中!
如果我们再次执行构建脚本(“./gradlew assemble”)并安装我们的 apk,我们会得到如下结果:

+

它主要做的事情与我们在风味资源部分已经做的事情相同,但这次不是因为资源被覆盖了。这次这些风味之间的代码完全不同。

风味库

在某些情况下,您可能需要在风味中使用不同的库。Nokia 的 Maps-SDK 以 jar 文件的形式提供,因此您需要将其添加到您的项目中。但此 SDK 不能在您的 Google 版本中使用。为了使您的 APK 文件大小尽可能小,您应该避免将其放入主项目中。在您要添加库的目标中创建一个名为“libs”的文件夹。将 map.jar 文件放入此文件夹。现在打开 build.gradle 文件并将此行添加到依赖项中。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    nokiaCompile files('src/nokia/libs/map.jar')
}

一旦我们点击“Sync Project”按钮,我们就可以在我们的 Nokia 风味中使用地图 sdk(仅在此!)。

关注点

本文在“Hello World”示例中介绍了构建自动化。构建自动化是专业开发中最重要​​的步骤之一(当然,除了开发本身)。Android Studio 和 gradle 提供了大量的可能性来自动化几乎所有内容,并使项目结构和代码本身更加清晰。

本文仅描述了风味的一种可能用例。另一种用例是免费版、专业版和应用内购买版风味。

历史

2014 年 7 月 27 日 初始版本
2014 年 7 月 31 日 修复了图像 URL

© . All rights reserved.