Android中应用调用系统权限

现在设备的安全性越来越受到重视,随之而来的便是开发中的各种不便,比如有普通权限,运行时权限,系统权限之分。对于运行时权限的添加可以参考

对于Android中各个权限的含义可以参考android/frameworks/base/core/res/AndroidManifest.xml中的释义

Android6.0蓝牙开发中获取附近低功耗蓝牙设备结果权限问题分析

而对于系统权限,却没有很好的解决方案,暂时只有一些特定的解决方案。

转载请注明出处,本文出自

海天之蓝

的博客

Android中应用调用系统权限

chapter one 系统应用添加系统权限

对于可以编译到源码里的apk添加系统权限很简单,就两步

一,在androidmanifest.xml文件中添加uid,即让应用跑在system进程中:android:sharduserid= “”

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.fang.zrf.networkdemo"
    android:sharedUserId="android.uid.system">

二,在该应用的mk文件中添加签名,即让该应用使用系统签名

LOCAL_CERTIFICATE := platform

其中platform对应的签名文件的位置为android/build/target/product/security  platform.pk8和platform.x509.pem

然后使用编译命令编译apk即可。

但如果没有mk的应用该怎么办呢?

其实也可以总结出来,让一个应用使用系统权限不外乎两步

第一就是uid改为system第二就是使用系统的签名,明白了这些之后我们就可以对应用使用系统权限了

chapter two 三方应用添加系统权限

第一步同上,添加Android:shareduserid属性

第二步,将打包好的apk使用系统签名重新签名打包。签名打包使用到一个Android源码中自带的一个工具叫做signapk,所在目录为Android/out/host/linux-x86/framework

使用cmd命令进行重新签名打包java -jar signapk.jar platform.x509.pem platform.pk8 old.apk new.apk

其中old.apk是打包好的apk,而new.apk是重新签名的apk。然后可以使用adb install -r new.apk将应用安装到手机上,此时即可获取系统权限。但有一个条件,既然用的是系统的签名,那首先就要保证你应用的系统签名和手机的系统签名一致,这个可能各大厂商会有所改动,所以不太能兼容。

chapter three DEMO实现

好了,说了这么多,来个demo看一看吧。demo所实现的功能有三个,

一是开启手机移动网络

二是关闭手机移动网络

三是获取手机移动网络

其实总结起来就是对手机移动网络的set和get两个功能而已。源码上对于set和get的方法属于hide的,不供三方应用使用,所以我们可以利用反射来调用到。

首先,先来看看需要什么权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>

其中MODIFY_PHONE_STATE为系统权限,所以我们只能是按chapter two所示的做法来做。先把代码完成了生成了apk再重新签名。

紧接着就是设置手机移动网络的 状态

public static void setMobileDataState(Context context, boolean enable){
        Class[] argsClass = new Class[1];
        argsClass[0] = boolean.class;//setmobiledataenable方法中要传入一个boolean类型的参数
        ConnectivityManager connMr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        try {
            Method method = connMr.getClass().getMethod("setMobileDataEnabled",argsClass);

            method.invoke(connMr,enable);
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(context,"set failure + e = " + e.getCause(),Toast.LENGTH_LONG).show();
        }
    }

然后是获取手机移动网络的状态

public static boolean getMobileDataState(Context context){

        ConnectivityManager connMr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        Class[] argsclass = null;//get时不需要传入参数,所以直接传入一个null的数组即可
        try {
            Method method = connMr.getClass().getDeclaredMethod("getMobileDataEnabled",argsclass);
            return (boolean)method.invoke(connMr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

接下来就是界面设计的方法的调用了,

先来看看界面实现效果

public class MainActivity extends Activity implements View.OnClickListener{


    private TextView mOpenNet;
    private TextView mCloseNet;
    private TextView mGetNetState;
    private TextView mNetState;

    private boolean isOpenState;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initData();
    }


    /**
     * 初始化view
     */
    private void initView(){
        mOpenNet = (TextView) findViewById(R.id.open_network);
        mCloseNet = (TextView) findViewById(R.id.close_network);
        mGetNetState = (TextView) findViewById(R.id.get_state);
        mNetState = (TextView) findViewById(R.id.network_state);
        setClickListener(mOpenNet,mCloseNet,mGetNetState);
    }


    /**
     * 初始化数据
     */
    private void initData(){
        updateView();

    }

    /**
     * 设置view的点击事件
     * @param views
     */
    private void setClickListener(View...views){

        for (View view:views) {
            if (view != null){
                view.setOnClickListener(this);
            }
        }

    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.open_network:
                NetManager.setMobileDataState(getApplicationContext(),true);
                updateView();
                break;
            case R.id.close_network:
                NetManager.setMobileDataState(getApplicationContext(),false);
                updateView();
                break;
            case R.id.get_state:
                updateView();
                break;
            default:
                break;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        updateView();
    }

    private void updateView(){
        isOpenState = NetManager.getMobileDataState(getApplicationContext());
        String str = isOpenState ? "true" : "false";
        if (str.equals(mNetState.getText().toString())){
            return;
        }
        mNetState.setText(str);
        setTvEnable(!isOpenState,isOpenState);
    }

    private void setTvEnable(boolean setEnable,boolean closeEnable){
        mOpenNet.setEnabled(setEnable);
        mCloseNet.setEnabled(closeEnable);
    }
}

代码完成后,在outputs目录下找到apk文件使用cmd命令进行重新签名。

到此,结束

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android研究院

Android组件化专题 - 路由框架进阶模块间的业务通信

上一篇文章,讲解了路由框架实现的原理,并实现了基本的路由框架 页面路由的跳转 Android组件化专题 - 路由框架原理。

15720
来自专栏Android先生

(新瓶旧酒)谷歌官方MVP项目学习--浅入源码

项目的目的是通过展示各种架构app的不同方式来帮助开发者解决架构问题。项目中通过不同的架构概念及方式实现了功能相同的app。你可以用示例来当做参考,或是干脆拿来...

13610
来自专栏分享达人秀

Activity初入门,创建和配置如此简单

Activity是Android应用的重要组成单元之一,也是Android应用最常见的组件之一。前面看到的示例通常都只包含一个Activity或一个Ap...

22650
来自专栏懒人开发

BottomNavigationView简单使用

之前见过类似这个库, 是带ripple效果的 不记得具体地址了,和这个类似 https://github.com/Ashok-Varma/BottomNav...

10930
来自专栏Android源码框架分析

SharePreference原理及跨进程数据共享的问题

SharedPreferences是Android提供的数据持久化的一种手段,适合单进程、小批量的数据存储与访问。为什么这么说呢?因为SharedPrefere...

19460
来自专栏Android先生

Android小技巧: 这里涵盖了所有实现 “一键退出 App” 的方法

即 需要2个步骤 才可 完成 一键退出 App 需求。下面,我将根据这两个步骤进行功能实现讲解。

8820
来自专栏学海无涯

Android开发之DownloadManager的使用

Android 开发中,经常有从服务器下载数据的需求出现,尤其是在线更新App的情形。其基本思路是根据本地的App版本号和服务器的版本号进行比较,如果服务器版本...

42670
来自专栏分享达人秀

ListView列表数据源——Adapter

在上一节一起了解了ListView的简单使用,那么本节继续来学习与ListView有着千丝万缕的Adapter。 一、了解MVC模式 在开始学习...

442100
来自专栏QQ音乐技术团队的专栏

[Android] Toast问题深度剖析(一)

伴随着我们开发的深入,Toast 的问题也逐渐暴露出来。本文章就将解释 Toast 这些问题产生的具体原因。

2.3K150
来自专栏青玉伏案

Android开发之Activity的生命周期以及加载模式

本篇博客就来好好的搞一下Activity的生命周期,如果搞过iOS的小伙伴的话,Activity的生命周期和iOS中ViewController的生命周期非常类...

21570

扫码关注云+社区

领取腾讯云代金券