Android 使用grade实现Android 项目debug版与release版共存

本文介绍如何通过Gradle配置使Android项目的debug版与release版在同一设备上共存,并解决包名冲突、权限重复等问题,同时提供动态打包so库的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Android 项目中,默认debug版与release版的包名相同,从而导致debug版与release版两者不能共存。为了方便开发,可以通过gradle实现让两者在一台手机上共存

原文地址:http://blog.csdn.net/lj402159806/article/details/54955431

配置app目录下的build.gradle文件

android {
    ......
    buildTypes {
    ......
        debug {
            //为debug版本的包名添加.debug后缀
            applicationIdSuffix ".debug"
            ......
        }
    }
}

在debug节点里添加这个配置后,debug版本的apk 包名会自动添加.debug后缀。比如原本包名为com.example.application的应用,debug包名为com.example.application.debug

权限重复的问题

如果项目中使用了第三方库,而在ManiFest中声明了权限,例如个推

<permission
    android:name="getui.permission.GetuiService.package_name"
    android:protectionLevel="normal"/>

android 5.0以上安装应用时会报duplicate permission exception,所以要保证debug和release安装包的permission name 不同,因此我们可以使用applicationId字段,使用方式如下。

<permission
    android:name="getui.permission.GetuiService.${applicationId}"
    android:protectionLevel="normal"/>

provider authorities

<provider
    android:name="com.igexin.download.DownloadProvider"
    android:authorities="downloads.package_name"
    android:exported="true"
    android:process=":pushservice"/>

同样也可以使用applicationId字段来替换

 android:authorities="downloads.${applicationId}"

使用manifestPlaceholders属性来替换

但是不是所有的属性都能使用applicationId来替换,比如融云这样的第三方库

可以看到如下data节点内的host=”package_name” 就不能使用applicationId字段来替换

<activity
            android:name=".activity.navigation.ConversationListActivity"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateHidden|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>

                <category android:name="android.intent.category.DEFAULT"/>

                <data
                    android:host="package_name"
                    android:pathPrefix="/conversationlist"
                    android:scheme="rong"/>
            </intent-filter>
        </activity>

因此我们可以用manifestPlaceholders属性, manifestPlaceholders顾名思义manifest占位符,上面说的饿${applicationId }就是grade自带的manifest占位符,当然我们也可以自定义manifest占位符

分别在release 和debug节点下添加manifestPlaceholders属性如下:

android {
    ......
    buildTypes {
    ......
     release {
            .......
            manifestPlaceholders = [
                    APP_NAME      : "@string/app_name",
                    APPLICATION_ID: "@string/application_id"
            ]
        }
        debug {
            //为debug版本的包名添加.debug后缀
            applicationIdSuffix ".debug"
            manifestPlaceholders = [
                    APP_NAME      : "@string/app_name_debug",
                    APPLICATION_ID: "@string/application_id_debug"
            ]
            ......
        }
    }
}

在项目的values/strings.xml文件里添加如下:

<string name="app_name">MyApplication</string>
    <string name="app_name_debug">MyApplicationDebug</string>
    <string name="application_id">com.example.myapplication</string>
    <string name="application_id_debug">com.example.myapplication.debug</string>

然后将data节点内的host=”package_name”替换为host=”${APPLICATION_ID}”

<activity
            android:name=".activity.navigation.ConversationListActivity"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateHidden|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>

                <category android:name="android.intent.category.DEFAULT"/>

                <data
                    android:host="${APPLICATION_ID}"
                    android:pathPrefix="/conversationlist"
                    android:scheme="rong"/>
            </intent-filter>
        </activity>

这样就能在打包release版本时包名使用release的包名,debug版本使用debug包名

app_name也同理,可以将android:label里的内容替换成manifestPlaceHolder变量,如下所示:

android:label="${APP_NAME}"

动态打包so包

apk的大小永远式开发者头疼的问题,而so包就是apk安装包体积过大的主要原因之一,因此很多开发者都会将一些用不到so包去除,以减小apk体积,比如x86的so包,但是如果你需要使用A n droid 官方提供的模拟器来测试你的应用的话,那x86的so包是必不可少,解决方案如下:

就是release版本打包时不包含x86的so包,减少正式版apk的体积,debug版本者包含x86的so包,方便在官方模拟器上测试。

android {
    ......
    buildTypes {
    ......
     release {
            .......
            //设置release版本只包含armeabi和armeabi-v7a的so包
            ndk {
                abiFilters "armeabi", "armeabi-v7a"
            }
        }
        debug {
            ......
            //设置debug版本包含x86的so文件
            ndk {
                abiFilters "armeabi", "armeabi-v7a", "x86"
            }
        }
    }
}
<think>好的,用户的问题是关于系统不支持降级的原因及解决方案。首先,我需要理解“系统不支持降级”具体指的是什么。根据提供的引用内容,可能涉及数据库降级、应用部署时的OOM问题,以及缓存相关的降级策略。 首先查看引用[1],提到Android数据库降级的操作注意事项,比如GreenDao的处理方式。这可能意味着在数据库本管理中,降级需要特殊处理,否则系统可能不支持自动降级。常见原因可能是数据结构变更导致无法回退,或者缺乏降级脚本。 引用[2]讨论OOM问题,其中提到应用重新部署时如果没有重启JVM,可能导致加载多份类信息,需要重启解决。这可能系统降级有关,比如在本回退时,旧本代码现有运行环境不兼容,需要重启服务才能生效,否则系统可能拒绝降级。 引用[3]涉及缓存击穿、穿透、雪崩的解决方案,其中提到熔断降级机制。这里降级指系统在高压下关闭非核心功能,保障核心运行。如果系统本身不支持这种降级,可能缺乏熔断策略或配置不当。 接下来需要整理可能的原因:1.数据库本降级缺少迁移脚本;2.应用本回退时未正确清理缓存或重启服务;3.系统未实现熔断降级机制;4.依赖服务或组件不兼容旧本。 解决方案部分:针对数据库问题,需提供降级脚本;应用部署方面,确保重启并清理缓存;设计熔断机制,配置降级策略;检查依赖兼容性,使用本管理工具。 还需要考虑用户的实际场景,比如是移动应用、后端服务还是分布式系统,但根据引用内容,可能涉及Android服务器端。需要综合各因素给出建议,同时引导用户提供更多细节以便更精准的解答。</think>### 系统不支持降级的原因及解决方案 #### **1. 数据库降级限制** - **原因**:数据库降级需要明确的逆向迁移脚本支持。若系统未提供降级脚本(如GreenDao未定义`onDowngrade`方法),直接降级可能导致数据结构本不匹配,引发数据损坏或崩溃[^1]。 - **解决方案**: - 手动编写降级逻辑:在数据库管理类中实现降级逻辑,例如回退表结构或清理冲突字段。 - 备份恢复:降级前备份数据,卸载应用后重新安装旧本并恢复数据。 - 示例代码(Android GreenDao): ```java DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, "db_name") { @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 自定义降级逻辑,如删除新增的表 db.execSQL("DROP TABLE IF EXISTS new_table"); } }; ``` #### **2. 应用本回退冲突** - **原因**:应用降级时,若未重启服务或清理缓存,可能导致新旧本代码共存(如类加载冲突),触发OOM或功能异常[^2]。 - **解决方案**: - 强制重启服务:降级后重启JVM或容器,确保完全加载旧本代码。 - 清理缓存:删除临时文件、持久化缓存及无效的类加载信息。 #### **3. 系统熔断降级机制缺失** - **原因**:高并发场景下,若未设计熔断降级策略(如限流、服务降级),系统可能因资源耗尽拒绝请求,表现为“不支持降级”[^3]。 - **解决方案**: - 引入熔断框架:使用Hystrix、Sentinel等工具,配置超时熔断降级回退方法。 - 核心服务隔离:通过线程池隔离或信号量保护核心功能,非核心功能自动降级。 - 示例配置(Sentinel): ```java // 定义降级规则 DegradeRule rule = new DegradeRule("critical_service") .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) .setCount(5) // 触发熔断的异常数 .setTimeWindow(30); // 熔断时间窗口(秒) ``` #### **4. 依赖组件本不兼容** - **原因**:降级后的系统本可能依赖低本库或服务接口,若其他组件未同步降级,会导致调用失败。 - **解决方案**: - 本锁定:使用Maven/Gradle等工具固定依赖本。 - 灰度发布:分批降级,逐步验证依赖兼容性。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值