调用Android原生@SystemApi、@Hide方法和解决混淆问题

1.关于@SystemApi和@Hide方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1NoJ2Ka2-1615188609645)(https://upload-images.jianshu.io/upload_images/13838098-9e5be0ee94f529c5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

如上图所示,PackageManager.getPermissionFlags()方法是被@SystemApi注解修饰过的方法,@SystemApi 只允许system app 调用或者用反射方法调用, 反射方法实例:

this.mPackageManager = context.getPackageManager();
try {
    Method method = mPackageManager.getClass(). getMethod("getPermissionFlags");
    method.invoke(mPackageManager, permName, packageName, user);
} catch (NoSuchMethodException e) {
	e.printStackTrace();
}

需要注意的是非 system app 用反射方法调用SystemApi,即使编译通过, 实际运行是还会遇到permission check。例如getPermissionFlags就需要GRANT_RUNTIME_PERMISSIONS,REVOKE_RUNTIME_PERMISSIONS,GET_RUNTIME_PERMISSIONS中的任意一个,如果应用没有申请这其中的任意一个权限,运行是也会报错。申请了以上三个中任意一个权限,就需要有系统签名。归根究底,要调用系统API就必须要系统签名,否则即使编译成功了,运行时也会报错。

2.源码编译模块

在使用mk文件编译的时候,会有LOCAL_PRIVATE_PLATFORM_APISLOCAL_SDK_VERSION参数选择,在mk文件中声明这两个参数的时候是互斥的,意思是只能声明其中一个

  • LOCAL_PRIVATE_PLATFORM_APIS设置之后,如果模块中有用到系统api,会使用sdk的hide的api来编译。
  • LOCAL_SDK_VERSION设置之后,编译的应用不能访问hide的api,会报找不到该方法错误。
//报错内容
pdk/apps/Permission/src/com/xh/permission/server/CarPermissionManagerService.java:269: error: cannot find symbol
     int flags = this.mPackageManager.getPermissionFlags(permissionInfo.name, packageInfo.packageName, Process.myUserHandle());
                         ^
  	symbol:   method getPermissionFlags(String,String,UserHandle)
 	location: variable mPackageManager of type PackageManager

编译找不到方法.png

3.调用原生api总结

# 可以调用系统的api,但是需要给apk系统签名
# LOCAL_CERTIFICATE := platform
LOCAL_PRIVATE_PLATFORM_APIS := true

# 编译时忽略系统隐藏类(@hide)
LOCAL_SDK_VERSION := current

4.编译混淆问题

在编译过程中如果遇到如下图编译报错,或者如下提示:

  1. If there are unresolved references to class members in program classes, your compiled class files are most likely inconsistent. Possibly, some class file didn’t get recompiled properly, or some class file was left behind after its source file was removed. Try removing all compiled class files and rebuilding your project.
  2. If there are unresolved references to class members in library classes, your compiled class files are inconsistent with the libraries. You may need to recompile the class files, or otherwise upgrade the libraries to consistent versions.

未配置混淆文件报错.png

就可以归纳为代码混淆配置问题

5.解决办法

源码编译时会用ProGuard混淆器做代码混淆、优化,过程中可能会删除掉个别类里的个别方法。

处理代码混淆问题有两个方法:

  • 在mk文件里加上一句:LOCAL_PROGUARD_ENABLED := disabled,禁用混淆器。
  • 在mk文件里加上一句:LOCAL_PROGUARD_FLAG_FILES := proguard.flags,然后创建一个配置文件"proguard.flags",配置部分类/方法/属性禁止混淆。(可以参照源码环境下的Settings里写法)
######################以下是原生设置的混淆文件#######################
###########还有很多其他规则,这里不详细列举,度娘一下,你就知道##########
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

# Keep all Fragments in this package, which are used by reflection.
-keep public class com.android.settings.** extends android.app.Fragment

# Keep all preference controllers needed by slice and DashboardFragment.
-keep class * extends com.android.settings.core.BasePreferenceController {
    *;
}

-keep class * extends com.android.settings.core.TogglePreferenceController {
    *;
}

# We want to keep methods in Activity that could be used in the XML attribute onClick.
-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
    public void *(android.view.MenuItem);
}

# Keep setters in Views so that animations can still work.
-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);

    void set*(***);
    *** get*();
}

# Keep classes that may be inflated from XML.
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int, int);
}

# Keep annotated classes or class members.
-keep @android.support.annotation.Keep class *
-keepclassmembers class * {
    @android.support.annotation.Keep *;
}

# Keep specific fields used via reflection.
-keepclassmembers class * {
    public static ** SEARCH_INDEX_DATA_PROVIDER;
    public static ** SUMMARY_PROVIDER_FACTORY;
}
-keep class android.support.v4.app.CoreComponentFactory

6.编译成功

最后模块编译成功之后会提示如下结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u2mqBIx0-1615188609651)(https://upload-images.jianshu.io/upload_images/13838098-accf096c4234d491.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值