如何为Android插桩测试授予权限?解决SMS读取权限拒绝问题
嘿,我来帮你搞定这个插桩测试的权限问题~
问题核心与解决方案
你的测试抛出SecurityException,主要是两个关键问题没处理好:上下文获取错误 + 插桩测试的危险权限授权逻辑缺失,下面一步步拆解:
1. 当前测试代码的致命问题
你用了InstrumentationRegistry.getContext(),这个方法拿到的是测试应用自身的Context,而不是你开发的短信读取应用的Context。READ_SMS权限是授予给你的目标应用的,测试应用本身并没有这个权限,所以不管怎么检查权限,都会失败,读取短信自然会被系统拒绝。
2. 必须补充的关键步骤
步骤一:切换到目标应用的Context
把获取Context的代码替换成:
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
这个Context属于你开发的短信应用,对应的权限状态才是正确的。
步骤二:自动授予危险权限(API 23+)
Android 6.0及以上的危险权限(比如READ_SMS)需要动态授权,但插桩测试里没法手动点击权限弹窗,所以要借助AndroidX Test提供的GrantPermissionRule来自动授予权限。
在测试类里添加这个Rule:
@Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_SMS);
(如果你的测试依赖里没有AndroidX Test相关库,需要确保在build.gradle里引入,一般新建插桩测试项目时会自动配置)
步骤三:确认目标应用已声明权限
在你开发的短信应用的AndroidManifest.xml里,必须明确声明权限:
<uses-permission android:name="android.permission.READ_SMS" />
3. 修改后的完整测试代码
import androidx.test.ext.junit.rules.GrantPermissionRule; import androidx.test.ext.junit.runners.AndroidJUnit4; import android.Manifest; import android.content.Context; import androidx.test.platform.app.InstrumentationRegistry; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.assertEquals; @RunWith(AndroidJUnit4.class) public class SmsFetcherTest { @Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_SMS); @Test public void fetchTenSms() throws Exception { // 获取被测应用的Context Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); // 现在可以正常检查权限(可选) // assertTrue(ContextCompat.checkSelfPermission(appContext, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED); List<Sms> tenSms = new SmsFetcher(appContext) .limit(10) .get(); assertEquals(10, tenSms.size()); } }
额外提醒
- 如果测试设备是API 22及以下,危险权限是安装时自动授予的,只要Manifest声明了就没问题,但为了兼容高版本,还是加上
GrantPermissionRule更稳妥。 - 测试时要确保设备里至少有10条短信,不然最后的断言会失败哦~
内容的提问来源于stack exchange,提问作者rsanath




