如何在安卓设备上管理调试版和发布版?

27

我刚开始学习 Android 开发,现在准备发布我的第一个应用程序 :)

当我在手机上测试签名后的发布版本 apk 时,它拒绝安装,因为带有调试签名的调试版本已经安装了。

所以我必须卸载调试版本,但是这将删除所有我的数据库(并且也会删除我的朋友正在测试的数据库)。

是否有一种方法可以管理相同应用程序的调试版本和发布版本而不会丢失数据?


我也很感兴趣解决这个问题。然而,我相当确定除非更改包名称,否则这是不可能的。 :/ - Victor
6个回答

38

许多 Android 项目正在开始使用 gradle 构建系统(我们在开始使用 Android Studio 时就转换到它了)。幸运的是,gradle 让同时安装开发和发布版本变得非常简单,每个版本都有自己独立的数据。 Android 文档 对此进行了介绍,只需在您的调试构建类型中添加 applicationIdSuffix 即可:

android {
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
        }
    }
}

我对Gradle还不是很熟悉,但根据我目前所读的内容,我认为这应该是被接受的答案,因为它是最好的解决方案来回答OP的问题。 - Andre

4

我不知道有没有简单的方法来避免卸载/重新安装过程,所以你的选择包括...

  • 购买第二个设备进行测试(一些Android设备现在非常便宜,特别是在eBay上)
  • 使用模拟器进行测试

我也遇到了同样的问题,但这是可以预料的,因此我使用手机进行调试开发,使用平板进行生产测试。当我接近发布时,我会在两个设备和模拟器上测试生产版本。

对于你的测试人员,我建议你总是给他们发布版本,但你可以包含详细的日志来帮助解决问题。调试版本仅由你使用,发布版本由他们使用。如果你向测试人员提供发布版本,他们使用并积累数据,当他们升级到下一个版本时,数据可以被保留(或更新,如果你更改了架构)以迁移他们的数据。

我认为你的测试人员没有必要使用调试版本和发布版本。


这是因为我提供了一个调试菜单,其中包含一些高级操作,只有在应用程序使用调试签名时才可用。 - Geob-o-matic
在这种情况下,我建议您在构建中添加一个布尔标志,用于确定是否包含该菜单,并将其放入生产构建中。另一个选择是在UI中“隐藏”它,例如长按应用程序徽标,大多数人不会这样做,但如果您想让特定的人访问它,他们可以这样做。然后,在测试完成后,进行适当的生产发布并将其删除。 - Ollie C
3
我认为将调试版本发送给测试人员是个不好的主意,最好发送正式版。这样可以让他们获得更接近最终结果的体验,例如确保他们正在测试使用生产MapView密钥的版本。调试版本是给你自己用的,正式版是给测试人员和最终用户使用的。 - Ollie C

3
感谢 @Evan,你提供的解决方案完美解决了问题。
android {
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
        }
    }
}

在调试模式下向您的应用标题添加" (DEBUG)",请在Activity的onCreate中放置以下代码:
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
    //The .debug specified in gradle
    if (pInfo.packageName.equals("YOUR_PACKAGE_NAME_HERE.debug")) {
        setTitle(getTitle() + " (DEBUG)");
}

2

配置应用程序ID后缀

在您的应用程序build.gradle上进行以下配置,发布版本将使用 com.example.myapp applicationId,而调试版本将使用 com.example.myapp.debug

android {
    defaultConfig {
        applicationId "com.example.myapp"
        ...
    }
    ...
}
buildTypes {
  debug {
    applicationIdSuffix ".debug"
    ...
  }
  release {
    ...
  }
  ...
}

配置多个Firebase账户

如果您使用Firebase,您需要两个Firebase账户,一个用于生产环境,另一个用于开发环境。您需要为每个账户在其自己的变体源集上配置Google Services JSON:

  • 生产环境google-services.json位于发布源集:app/src/release/google-services.json
  • 开发环境google-services.json位于调试源集:app/src/debug/google-services.json

提供商权限

如果您在AndroidManifest.xml中定义了提供商,现在如果发布版和调试版都使用相同的提供商权限并且您在同一设备上安装了两个应用程序,则可能会出现冲突。为避免此问题,一个好的做法是将applicationId用作权限后缀。

<provider
   android:name="androidx.core.content.FileProvider"
   android:authorities="${applicationId}.fileprovider"
   android:exported="false"
   android:grantUriPermissions="true">
</provider>

为每个变体自定义图标

如果您要在同一设备上安装多个变体,一个好的主意是使用不同的应用程序图标,这样您就可以在启动器中识别它们。 您只需要设计一个调试应用程序图标并将其放置在src/debug/res/mipmap-xxhdpi-*

配置 FCM

现在您使用不同的 Firebase 帐户,如果您有一个 FCM(推送)服务器,您需要使用正确的凭据配置它。 当注册具有调试应用程序的设备时,FCM 服务器需要将注册令牌与调试构建类型关联。因此,在发送推送时,使用 Firebase 调试凭据的令牌。 因此,每次应用程序注册 FCM 令牌时,您需要将构建类型发送到 FCM 服务器。


以下文章提供有关此主题的更多信息:在同一设备上安装您的调试和发布变体


2

为什么要卸载应用程序?通常情况下,安装相同应用程序的新版本(通过包ID标识)会保留所有应用程序数据。

编辑:若要手动保留应用程序数据,请将其从/data/data/my.package.name/...复制到安全位置,然后在必要时进行恢复。


1
同一个应用程序将覆盖旧的应用程序,同时保留数据,但您不能安装具有相同包但不同签名的第二个应用程序,就像@Geobert一样。所以这就是发生的事情。 - Nanne
我没有改变包ID,但它无法安装。我已经卸载了调试版本,然后安装了发布版。当我尝试从Eclipse中以调试模式启动时,它会显示: - Geob-o-matic
[2011-02-10 18:11:24 - radis] 正在将radis.apk上传到设备“10006609c6cb” [2011-02-10 18:11:24 - radis] 安装radis.apk... [2011-02-10 18:11:25 - radis] 重新安装失败,原因是应用签名不同。 [2011-02-10 18:11:25 - radis] 您必须执行完整的卸载该应用程序。警告:这将删除应用程序数据! [2011-02-10 18:11:25 - radis] 请在shell中执行“adb uninstall fr.geobert.Radis”。 [2011-02-10 18:11:25 - radis] 启动已取消! - Geob-o-matic
1
我认为这是一个不好的解决方案 - 你应该将生产APK发送给你的测试人员和客户,否则他们可能会给出反馈,一切都很好,然后你发布生产版本并发现问题。你的测试人员应该测试尽可能接近最终发布版本的版本。 - Ollie C
1
我有点同意;在我的情况下,beta 版本是由生产密钥签名的,并且调试功能被很好地隐藏起来(通过一个输入字段中的秘籍代码激活)。只是回答问题。 - Seva Alekseyev
显示剩余5条评论

1
对我来说,我还需要添加:

<permission                                                                               
      android:name="${applicationId}.permission.C2D_MESSAGE"                                
      android:protectionLevel="signature" />                                                

<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" /> 

否则,两者将收到相同的C2D_MESSAGE权限,这将导致:
Failure [INSTALL_FAILED_DUPLICATE_PERMISSION perm=<your applicationId>.permission.C2D_MESSAGE pkg=<your applicationId>] 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接