时间如梭,总在不经意间流逝。经常会想,毕业到现在我都干了些什么,该有什么样的追求?
运行时权限是 Android 6.0 (SDK 23)新特性,更好的保护了用户的隐私。
如果你build.gradle
文件中声明targetSdkVersion
为23及以上
:
defaultConfig {
applicationId "xxxx"//you applicationId
minSdkVersion 14
targetSdkVersion 23//23及以上
versionCode 1
versionName "1.0"
multiDexEnabled true
}
用到的隐私权限就要进行申请;反之小于23
,默认授予AndroidManifest.xml
中的所有申请权限。
注意: 需要用到的权限必须在 AndroidManifest.xml 文件中申明。
Google
将权限分为两类,一类是Normal Permissions
,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、获取wifi连接状态、访问网络等;另一类是Dangerous Permission
,一般是涉及到用户隐私的,需要用户进行授权,比如获取位置信息、读取sdcard、访问通讯录等。
Android 权限一览:
android.permission.EXPAND_STATUS_BAR允许一个程序扩展收缩在状态栏,android开发网提示应该是一个类似Windows Mobile中的托盘程序
android.permission.FACTORY_TEST作为一个工厂测试程序,运行在root用户
android.permission.FLASHLIGHT访问闪光灯,android开发网提示HTC Dream不包含闪光灯
android.permission.FORCE_BACK允许程序强行一个后退操作是否在顶层activities
android.permission.FOTA_UPDATE暂时不了解这是做什么使用的,android开发网分析可能是一个预留权限.
android.permission.GET_ACCOUNTS访问一个帐户列表在Accounts Service中
android.permission.GET_PACKAGE_SIZE允许一个程序获取任何package占用空间容量
android.permission.GET_TASKS允许一个程序获取信息有关当前或最近运行的任务,一个缩略的任务状态,是否活动等等
android.permission.HARDWARE_TEST允许访问硬件
android.permission.INJECT_EVENTS允许一个程序截获用户事件如按键、触摸、轨迹球等等到一个时间流,android开发网提醒算是hook技术吧
android.permission.INSTALL_PACKAGES允许一个程序安装packages
android.permission.INTERNAL_SYSTEM_WINDOW允许打开窗口使用系统用户界面
android.permission.ACCESS_CHECKIN_PROPERTIES允许读写访问“properties”表在checkin数据库中,改值可以修改上传。
android.permission.ACCESS_COARSE_LOCATION允许一个程序访问CellID或WiFi热点来获取粗略的位置
android.permission.ACCESS_FINE_LOCATION允许一个程序访问精良位置(如GPS)
android.permission.WRITE_CONTACTS允许程序写入但不读取用户联系人数据
android.permission.WRITE_GSERVICES允许程序修改Google服务地图
android.permission.WRITE_OWNER_DATA允许一个程序写入但不读取所有者数据
android.permission.WRITE_SETTINGS允许程序读取或写入系统设置
android.permission.WRITE_SMS允许程序写短信
android.permission.WRITE_SYNC_SETTINGS允许程序写入同步设置
android.permission.ACCESS_LOCATION_EXTRA_COMMANDS允许应用程序访问额外的位置提供命令
android.permission.ACCESS_MOCK_LOCATION允许程序创建模拟位置提供用于测试
android.permission.ACCESS_NETWORK_STATE允许程序访问有关GSM网络信息
android.permission.ACCESS_SURFACE_FLINGER允许程序使用SurfaceFlinger底层特性
android.permission.ACCESS_WIFI_STATE允许程序访问Wi-Fi网络状态信息
android.permission.ADD_SYSTEM_SERVICE允许程序发布系统级服务
android.permission.BATTERY_STATS允许程序更新手机电池统计信息
android.permission.BLUETOOTH允许程序连接到已配对的蓝牙设备
android.permission.BLUETOOTH_ADMIN允许程序发现和配对蓝牙设备
android.permission.BROADCAST_PACKAGE_REMOVED允许程序广播一个提示消息在一个应用程序包已经移除后
android.permission.BROADCAST_STICKY允许一个程序广播常用intents
android.permission.CALL_PHONE允许一个程序初始化一个电话拨号不需通过拨号用户界面需要用户确认
android.permission.DELETE_CACHE_FILES允许程序删除缓存文件
android.permission.DELETE_PACKAGES允许一个程序删除包
android.permission.DEVICE_POWER允许访问底层电源管理
android.permission.DIAGNOSTIC允许程序RW诊断资源
android.permission.DISABLE_KEYGUARD允许程序禁用键盘锁
android.permission.DUMP允许程序返回状态抓取信息从系统服务
android.permission.CALL_PRIVILEGED允许一个程序拨打任何号码,包含紧急号码无需通过拨号用户界面需要用户确认
android.permission.CAMERA请求访问使用照相设备
android.permission.CHANGE_COMPONENT_ENABLED_STATE允许一个程序是否改变一个组件或其他的启用或禁用
android.permission.CHANGE_CONFIGURATION允许一个程序修改当前设置,如本地化
android.permission.CHANGE_NETWORK_STATE允许程序改变网络连接状态
android.permission.CHANGE_WIFI_STATE允许程序改变Wi-Fi连接状态
android.permission.CLEAR_APP_CACHE允许一个程序清楚缓存从所有安装的程序在设备中
android.permission.CLEAR_APP_USER_DATA允许一个程序清除用户设置
android.permission.CONTROL_LOCATION_UPDATES允许启用禁止位置更新提示从无线模块
android.permission.REBOOT请求能够重新启动设备
android.permission.RECEIVE_BOOT_COMPLETED允许一个程序接收到ACTION_BOOT_COMPLETED广播在系统完成启动
android.permission.RECEIVE_MMS允许一个程序监控将收到MMS彩信,记录或处理
android.permission.RECEIVE_SMS允许程序监控一个将收到短信息,记录或处理
android.permission.RECEIVE_WAP_PUSH允许程序监控将收到WAP PUSH信息
android.permission.RECORD_AUDIO允许程序录制音频
android.permission.REORDER_TASKS允许程序改变Z轴排列任务
android.permission.RESTART_PACKAGES允许程序重新启动其他程序
android.permission.SEND_SMS允许程序发送SMS短信
android.permission.INTERNET允许程序打开网络套接字
android.permission.MANAGE_APP_TOKENS允许程序管理(创建、催后、 z-order默认向z轴推移)程序引用在窗口管理器中
android.permission.MASTER_CLEAR目前还没有明确的解释,android开发网分析可能是清除一切数据,类似硬格机
android.permission.MODIFY_AUDIO_SETTINGS允许程序修改全局音频设置
android.permission.MODIFY_PHONE_STATE允许修改话机状态,如电源,人机接口等
android.permission.MOUNT_UNMOUNT_FILESYSTEMS允许挂载和反挂载文件系统可移动存储
android.permission.PERSISTENT_ACTIVITY允许一个程序设置他的activities显示
android.permission.PROCESS_OUTGOING_CALLS允许程序监视、修改有关播出电话
android.permission.READ_CALENDAR允许程序读取用户日历数据
android.permission.READ_CONTACTS允许程序读取用户联系人数据
android.permission.READ_FRAME_BUFFER允许程序屏幕波或和更多常规的访问帧缓冲数据
android.permission.READ_INPUT_STATE允许程序返回当前按键状态
android.permission.READ_LOGS允许程序读取底层系统日志文件
android.permission.READ_OWNER_DATA允许程序读取所有者数据
android.permission.READ_SMS允许程序读取短信息
android.permission.READ_SYNC_SETTINGS允许程序读取同步设置
android.permission.READ_SYNC_STATS允许程序读取同步状态
android.permission.SET_ACTIVITY_WATCHER允许程序监控或控制activities已经启动全局系统中
android.permission.SET_ALWAYS_FINISH允许程序控制是否活动间接完成在处于后台时
android.permission.SET_ANIMATION_SCALE修改全局信息比例
android.permission.SET_DEBUG_APP配置一个程序用于调试
android.permission.SET_ORIENTATION允许底层访问设置屏幕方向和实际旋转
android.permission.SET_PREFERRED_APPLICATIONS允许一个程序修改列表参数
android.permission.SET_PROCESS_FOREGROUND允许程序当前运行程序强行到前台
android.permission.SET_PROCESS_LIMIT允许设置最大的运行进程数量
android.permission.SET_TIME_ZONE允许程序设置时间区域
android.permission.SET_WALLPAPER允许程序设置壁纸
android.permission.SET_WALLPAPER_HINTS允许程序设置壁纸hits
android.permission.SIGNAL_PERSISTENT_PROCESSES允许程序请求发送信号到所有显示的进程中
android.permission.STATUS_BAR允许程序打开、关闭或禁用状态栏及图标Allows an application toopen, close, or disable the status bar and its icons.
android.permission.SUBSCRIBED_FEEDS_READ允许一个程序访问订阅RSS Feed内容提供
android.permission.SUBSCRIBED_FEEDS_WRITE系统暂时保留改设置,android开发网认为未来版本会加入该功能。
android.permission.SYSTEM_ALERT_WINDOW允许一个程序打开窗口使用TYPE_SYSTEM_ALERT,显示在其他所有程序的顶层
android.permission.VIBRATE允许访问振动设备
android.permission.WAKE_LOCK允许使用PowerManager的 WakeLocks保持进程在休眠时从屏幕消失
android.permission.WRITE_APN_SETTINGS允许程序写入API设置
android.permission.WRITE_CALENDAR允许一个程序写入但不读取用户日历数据
其中的危险权限Dangerous Permissions
:
你也可以通过adb
命令进行权限查看:
adb shell pm list permissions
危险权限查看:
adb shell pm list permissions -d -g
dangerous permissions
是分组的,那么这么分组又会有什么影响呢?
如果你申请某个危险的权限,假设你的app
已经被用户授权了同一组的某个危险权限比如READ_CONTACTS
,那么WRITE_CONTACTS
和GET_ACCOUNTS
危险权限也同样被授权了,而不需要用户再次去申请。同样弹出的申请权限dialog
文本说明也是对整个权限组的说明,而不是单个权限。
在AndroidManifest.xml
文件下申明读的联系人权限:
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
如果targetSdkVersion
版本小于23,不需要进行权限的处理。
if (checkSelfPermission(requestPermission) != PackageManager.PERMISSION_GRANTED) {
//未被授权
} else {
//已授权
}
如果未被授权,则需要申明授权处理。
requestPermissions(final @NonNull Activity activity,
final @NonNull String[] permissions, final int requestCode)
第一个参数是 activity
第二个参数是申请授权的权限组
第三个参数是请求码(如果不理解可以参考startActivityForResult()
方法)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == PERMISSON_REQUESTCODE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 申请权限已经授权
} else {
// 申请权限未授权
}
}
}
参数grantResults
申请权限返回的状态信息。
这里还有一个方法需要说明一下:
public boolean shouldShowRequestPermissionRationale(String permission)
当用户第一次勾选了【禁止后不再询问】勾选框,并点击【禁止】按钮,第二次申请该权限返回true
的方法,一般给于用户提示缺少改权限。\n\n请点击\”设置\”-\”权限\”-打开所需权限进行处理。
打开设置代码:
private void startAppSettings() {
Intent intent = new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
在实际开发中可能会几个权限同时需要授权处理,如定位需要位置权限,访问 sdcard 。若单个申请则会显得很麻烦。所以我这里单独的提取了一个抽象类用于权限的处理,并把返回结果延迟到它的子类进行处理。对的,这里用了模板模式。具体看以下代码:
public abstract class CheckPermissionsActivity extends AppCompatActivity {
首先申明CheckPermissionsActivity
为抽象类。
public abstract void requestPermissionResult(boolean allowPermission);
申明抽象方法,并把allowPermission
是否授予权限设置为参数。
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == PERMISSON_REQUESTCODE) {
if (verifyPermissions(grantResults)) {
requestPermissionResult(true);
} else {
requestPermissionResult(false);
showMissingPermissionDialog();
}
}
}
最后我们在回调函数中传递参数给requestPermissionResult
抽象方法。下面我们来看看一个具体的例子。文章的最后已经附上了源码。
package com.github.permissondemo;
import android.Manifest;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
public class MainActivity extends CheckPermissionsActivity implements LoaderManager.LoaderCallbacks<Cursor> {
static final String[] PROJECTION = new String[]{ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME};
String mCurFilter;
static String TAG;
protected String[] needContactsPermissions = {
Manifest.permission.READ_CONTACTS
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TAG = getClass().getName();
requestPermission();
}
private void requestPermission() {
if (!mayRequestPermission(needContactsPermissions)) {
return;
}
initLoader();
}
@Override
public void requestPermissionResult(boolean allowPermission) {
if (allowPermission) {
initLoader();
}
}
private void initLoader() {
getLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
Uri baseUri;
if (mCurFilter != null) {
baseUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI
, Uri.encode(mCurFilter));
} else {
baseUri = ContactsContract.Contacts.CONTENT_URI;
}
String select = "((" + ContactsContract.Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+ ContactsContract.Contacts.DISPLAY_NAME + " != '' ))";
CursorLoader loader = new CursorLoader(MainActivity.this, baseUri,
PROJECTION, select, null, ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
return loader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if (cursor == null) {
return;
}
while (cursor.moveToNext()) {
String[] names = cursor.getColumnNames();
for (String str : names) {
String contacts = cursor.getString(cursor.getColumnIndex(str));
Log.e(TAG, "contacts=" + contacts);
}
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
}
若有什么疑问请留言。源码地址