IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 千里马android framework开发解决Accessing hidden method限制,让应用访问隐藏方法(需要可以修改系统源码方案) -> 正文阅读

[移动开发]千里马android framework开发解决Accessing hidden method限制,让应用访问隐藏方法(需要可以修改系统源码方案)

hi,粉丝朋友们大家好!
今天来给大家分享一下,就是经常大家会做安卓系统开发工作问到一个问题,那就是我如果framework代码中增加了一个方法啥的,但是我又不想公开给第三方应用知道,只想让我系统的应用知道,那该怎么办呢?其实这个时候经常就会用到一个hidden的标签,来代表这个方法是隐藏方法,隐藏方法就是给系统内部用的,意味着第三方app就无法使用。这个其实也很常见,自从android p开始android系统就开始对访问hidden的限制越来越严格,虽然我们网络上有各种奇葩招来逃避不允许调用hidden api,这个第三方应用奇葩方法调用hidden不是我们重点。

我们重点当然是我们做android系统的,我们系统源码都可以随意改,根本不需要那种第三方应用使用的奇葩方法来逃避hidden api(毕竟这个属于野路子,google可能下一个版本就改变了,野路子无效了),所以该方案仅仅适用于你可以修改源码情况下,可以对第三方应用,系统应用都可以访问hidden api
也可以关注看看我的b站视频,获取更多课程可以b站直接私聊我要优惠群:422901085: https://www.bilibili.com/video/BV1TS4y1e7De/
千里马android framework所有实战资料

1、看看系统中接口是怎么定义成了hidden如下:

我们以ActivityManager的类为例子
frameworks/base/core/java/android/app/ActivityManager.java

//源码获取 qq群:422901085
    /** @hide */   这里的 
    public static int checkUidPermission(String permission, int uid) {
        try {
            return AppGlobals.getPackageManager()
                    .checkUidPermission(permission, uid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

/** @hide */ 这个标签最为关键,表示这个方法是个隐藏方法不会出现在sdk中,也不会出现编译报错要make update-api

2、那么系统应用app怎么访问这个framework的hidden接口呢?

其实这个hidden接口访问有2中方式
1、反射方法,这种最简单直接调用地方写成反射就可以,但是代码可读性差一点

                    ClassLoader loader = MainActivity.this.getClassLoader();//得到当前类的classLoader
                    Class<?> clz;

                    clz = Class.forName("android.app.ActivityManager"); //加载类
                   @SuppressLint("SoonBlockedPrivateApi") Method m = clz.getDeclaredMethod("checkUidPermission", String.class, int.class); //获取方法


                    int permisson = (Integer) m.invoke(clz, "android.permission.INJECT_EVENTS",1000);  //反射调用,static方法调用时,不必得到对象示例

2、制作一个包装接口jar包,jar是有系统源码编译的,可以访问hidden接口,具体如下:

//源码获取 qq群:422901085
package com.android.third.call;

import android.app.ActivityManager;

public class ThirdInterface {
    public ThirdInterface() {
    }

    public static int callHiddenFun() {
        return ActivityManager.checkUidPermission("android.permission.INJECT_EVENTS", 1000);
    }
}


注意哦,这里我们需要android源码环境编译哦,编译成一个jar,对应的mk
在这里插入图片描述

# 源码获取 qq群:422901085
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := thirdinterface
LOCAL_MODULE_STEM := thirdinterface
LOCAL_DEX_PREOPT := false
include $(BUILD_STATIC_JAVA_LIBRARY)

然后 :make thirdinterface 就可以获取对应的jar包
路径大概如下:
out/target/product/gemini/obj/JAVA_LIBRARIES/thirdinterface_intermediates/javalib.jar
然后需要使用这个jar包的app进行拷贝这个javalib.jar到工程中的lib路径:
在这里插入图片描述
导入后就可以源码中调用了:

         int permisson =  ThirdInterface.callHiddenFun();

调用起来就真的非常简单,可读性还是要比反射好很多

3、调用成功就能执行成功么?

这个其实在以前android还没有对hidden api的执行做限制时候,确实调用编译通过了就代表执行也也可以成功,但是从android 9以后,发现调用都会出现以下错误logcat打印:
2021-11-28 08:23:55.695 26050-26050/com.example.anrdemo W/example.anrdem: Accessing hidden method Landroid/app/ActivityManager;->checkUidPermission(Ljava/lang/String;I)I (greylist-max-o, linking, denied)

如果看到了Accessing hidden method ,那基本就是代表你其实一切都ok,就是被系统拦截不让你调用了,这里就不用怀疑什么方法写错了,反射写错了,如果没有这个打印要么你就执行成功,要么就是方法写错

4、系统解决hidden api调用

那么系统层面桌面解决让访问调用的hidden api呢?这个其实我们系统层面早就考虑到了需要给一些应用让其可以访问hidden,具体代码可以看这里:
base/core/java/android/content/pm/ApplicationInfo.java
在这里插入图片描述
这里其实就有一个isAllowedToUseHiddenApis方法,这个非常关键,分别对代码进行注释讲解:

    private boolean isAllowedToUseHiddenApis() {
        if (isSignedWithPlatformKey()) { //如果app platform签名直接就可以调用hidden api
            return true;
        } else if (isSystemApp() || isUpdatedSystemApp()) { //如果没有platform签名,但是属于system/app,那么就会根据白名单进行过滤是否可以
            return usesNonSdkApi() || isPackageWhitelistedForHiddenApis();
        } else {
            //return false;原来第三方是直接返回false
           return isPackageWhitelistedForHiddenApis();
           //这里改成第三方应用也可以根据这个白名单来
        }
    }

那么这个白名单在哪呢?
源码在
~/xiaomi5/frameworks/base/data/etc/hiddenapi-package-whitelist.xml
手机上在:
/system/etc/sysconfig/
看目前内容:

<?xml version="1.0" encoding="utf-8"?>

<config>
  <hidden-api-whitelisted-app package="com.example.anrdemo" /> <!--这里就是我们增加的第三方应用package Name-->
  <hidden-api-whitelisted-app package="android.ext.services" />
  <hidden-api-whitelisted-app package="com.android.apps.tag" />
  <hidden-api-whitelisted-app package="com.android.basicsmsreceiver" />
  <hidden-api-whitelisted-app package="com.android.bookmarkprovider" />
  <hidden-api-whitelisted-app package="com.android.calllogbackup" />
  <hidden-api-whitelisted-app package="com.android.camera" />
  <hidden-api-whitelisted-app package="com.android.car.dialer" />
  <hidden-api-whitelisted-app package="com.android.car.messenger" />
  <hidden-api-whitelisted-app package="com.android.car.overview" />
  <hidden-api-whitelisted-app package="com.android.car.stream" />
  <hidden-api-whitelisted-app package="com.android.companiondevicemanager" />
  <hidden-api-whitelisted-app package="com.android.dreams.basic" />
  <hidden-api-whitelisted-app package="com.android.gallery" />
  <hidden-api-whitelisted-app package="com.android.launcher3" />
  <hidden-api-whitelisted-app package="com.android.mtp" />
  <hidden-api-whitelisted-app package="com.android.musicfx" />
  <hidden-api-whitelisted-app package="com.android.permissioncontroller" />
  <hidden-api-whitelisted-app package="com.android.printservice.recommendation" />
  <hidden-api-whitelisted-app package="com.android.printspooler" />
  <hidden-api-whitelisted-app package="com.android.providers.blockednumber" />
  <hidden-api-whitelisted-app package="com.android.providers.calendar" />
  <hidden-api-whitelisted-app package="com.android.providers.contacts" />
  <hidden-api-whitelisted-app package="com.android.providers.downloads" />
  <hidden-api-whitelisted-app package="com.android.providers.downloads.ui" />
  <hidden-api-whitelisted-app package="com.android.providers.media" />
  <hidden-api-whitelisted-app package="com.android.providers.tv" />
  <hidden-api-whitelisted-app package="com.android.providers.userdictionary" />
  <hidden-api-whitelisted-app package="com.android.smspush" />
  <hidden-api-whitelisted-app package="com.android.spare_parts" />
  <hidden-api-whitelisted-app package="com.android.statementservice" />
  <hidden-api-whitelisted-app package="com.android.storagemanager" />
  <hidden-api-whitelisted-app package="com.android.systemui.plugins" />
  <hidden-api-whitelisted-app package="com.android.terminal" />
  <hidden-api-whitelisted-app package="com.android.wallpaper" />
  <hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" />
</config>

其实很容易看懂,这下面的名单都可以进行hidden api,我们要增加啥应用只需要加上包名如:

当然这里如果android原生只支持system app,大家有疑问system app难道不应该是platform签名么?那么签名不就直接返回么?其实还真的不是,其实很多系统应用也不一定系统签名哈,有media,啥的签名故就靠这个白名单了。
我们前面对ApplicationInfo进行了修改就可以进行第三方应用包名也写入了。
然后进行编译后,我们第三方应用就可以正常执行hidden api通过了:
在这里插入图片描述
正常打印了:
2021-11-28 10:04:40.740 29000-29000/com.example.anrdemo I/test: PackageManager.PERMISSION_GRANTED == permisson true

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-29 12:16:33  更:2022-04-29 12:17:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 23:21:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码