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命令进行重新签名。
到此,结束
- React第三方组件2(状态管理之Refast的使用⑤LogicRender使用)
- 左右用R右手Python9——字符串合并与拆分
- hdu 1003 Max Sum(最大子窜和)
- React第三方组件2(状态管理之Refast的使用④中间件middleware使用)
- 高维分面应用——ggplot2分面气泡图饼图
- poj 1579 Function Run Fun
- React第三方组件2(状态管理之Refast的使用③扩展ctx)
- 财经小知识——CRS风暴与全球离岸金融中心
- The Triangle
- React第三方组件2(状态管理之Refast的使用②异步修改state)
- UVa Automatic Editing
- React第三方组件2(状态管理之Refast的使用①简单使用)
- uva Excuses, Excuses!
- React第三方组件5(状态管理之Redux的使用④TodoList下)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Python3 列表
- Mycat 核心配置详解
- Python字符串
- 初识 HBase
- Number对象
- Windows 技术篇-设置计划任务,每天自动关机
- Mycat 快速入门
- Python 技术篇-连接qq邮箱服务器,调用qq邮箱发送邮件实战演示,qq邮箱授权码开通方法
- 浅谈数据库集群方案
- SkyWalking - 实现微服务监控告警
- Actuator + Prometheus + Grafana搭建微服务监控平台
- Python 用smtplib库发邮件报错:[WinError 10061] 由于目标计算机积极拒绝,无法连接。解决办法
- python运算符
- Windows 技术篇-禁用windows更新服务,解决windows无法关闭更新问题,解决windows自己启用更新问题。
- 搭建 SkyWalking 服务(For ElasticSearch 7)