声明:此文非本人原创,为整理网络资料加自己的一些注解所得。
http://www.jb51.net/article/128043.htm
权限问题:
一. 在Android M及更高版本中使用 Settings.System 抛出异常"You cannot keep your settings in the secure settings. " (7.0项目访客模式torch的状态码存在Settings.System中导致报停)
调用Settings.System.putStringForUser最终都是对数据库SettingsProvider进行操作。
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.Java
在M版本中,在Settings.System表中执行更新或者删除操作时,都要会调用函数warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk,该函数是M新增。当app尝试更新Settings.System的时候,会进行版本校验,如果targetSDK 小于等于Build.VERSION_CODES.LOLLIPOP_MR1,即低版本的apk时,给出warning,保证代码的兼容性。
而当tagetSDK大于Build.VERSION_CODES.LOLLIPOP_MR1,即M版本及更高的版本的时候,则会抛出异常,禁止apk写或者删除SettingsProvider数据库中的System表。
解决方案:
1. 如果对targetSDK没有要求,则将targetSDK降为Build.VERSION_CODES.LOLLIPOP_MR1以下,利用Android程序向前兼容性,规避问题,但是这样的方法并不是最优方案,有可能在后续版本中,Android甚至可能放弃兼容,直接抛出异常。
2. 放弃写Settings.System,改用Settings.Global保存共享数据。
二. 动态申请权限
系统权限分成两类:normal和dangerous两类:
Normal类的权限不会直接涉及到用户隐私风险。如果APP在Manifest文件中声明了Normal类的权限,系统会自动授予这些权限。
Dangerous类的权限可能会让APP涉及到用户机密的数据。如果APP在Manifest文件中声明了Normal类的权限,系统会自动授予这些权限。如果在Manifest文件中添加了Dangerous类的权限,用户必须明确的授予对应的权限后APP才具有这些权限。
危险权限,在android6.0中,属于动态权限管理,需要用户主动授权才能使用。一旦组内的某个权限被赋予了,那么这个组的其他权限也将自动被赋予。
private static final int PERMISSION_REQUEST_POWER_ON = 100; private static final int PERMISSION_REQUEST_CODE_SAVED_RECORDING = 101;
SoundRecorder开始按钮的点击事件
if (recordPermission()) {return;} else if (storagePermission()){return;}
startRecord();
public boolean recordPermission(){ int recordAudioPermission = checkSelfPermission(Manifest.permission.RECORD_AUDIO); List<String> mPermissionStrings = new ArrayList<String>(); boolean mRequest = false; if (recordAudioPermission != PackageManager.PERMISSION_GRANTED) { mPermissionStrings.add(Manifest.permission.RECORD_AUDIO); mRequest = true; } if (mRequest == true) { String[] mPermissionList = new String[mPermissionStrings.size()]; mPermissionList = mPermissionStrings.toArray(mPermissionList); requestPermissions(mPermissionList, PERMISSION_REQUEST_POWER_ON); return true; } return false; }
public boolean storagePermission(){ int readExtStorage = checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE); int writeExtStorage = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); List<String> mPermissionStrings = new ArrayList<String>(); boolean mRequest = false; if (readExtStorage != PackageManager.PERMISSION_GRANTED) { mPermissionStrings.add(Manifest.permission.READ_EXTERNAL_STORAGE); mRequest = true; } if (writeExtStorage != PackageManager.PERMISSION_GRANTED) { mPermissionStrings.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); mRequest = true; } if (mRequest == true) { String[] mPermissionList = new String[mPermissionStrings.size()]; mPermissionList = mPermissionStrings.toArray(mPermissionList); requestPermissions(mPermissionList, PERMISSION_REQUEST_CODE_SAVED_RECORDING); return true; } return false; }判断用户是否确认了权限
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { boolean granted = true; boolean mShowPermission = true; if (permissions.length <= 0 || grantResults.length <= 0) { Log.d(TAG, "permission length not sufficient"); showToast(getString(R.string.missing_required_permission)); return; } if (requestCode == PERMISSION_REQUEST_POWER_ON) { granted = (grantResults[0] == PackageManager.PERMISSION_GRANTED); if (!granted) { mShowPermission = shouldShowRequestPermissionRationale(permissions[0]); } Log.i(TAG, "<onRequestPermissionsResult> Record audio soundrecorder granted" + granted); if (granted == true) { storagePermission(); } else if (!mShowPermission) { showToast(getString(R.string.missing_required_permission)); } }else if (requestCode == PERMISSION_REQUEST_CODE_SAVED_RECORDING){ for (int counter = 0; counter < permissions.length; counter++) { boolean permissionGranted = false; permissionGranted = (grantResults[counter] == PackageManager.PERMISSION_GRANTED); granted = granted && permissionGranted; if (!permissionGranted) { mShowPermission = mShowPermission && shouldShowRequestPermissionRationale( permissions[counter]); } } Log.i(TAG, "<onRequestPermissionsResult> savefile soundrecorder granted" + granted); if (granted == true) { startRecord(); } else if (!mShowPermission) { showToast(getString(R.string.missing_required_permission)); } } }
文件存储
权限:
<uses-permission android:name="android.permission.INTERNET" /> <!-- 往SDCard写入数据权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 在SDCard中创建与删除文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
内置存储
try { String fileInnerName = "/inner/img"; //目录名 // 内置存储文件目录 File fileDir = new File(this.getFilesDir(), fileInnerName); // /data/data/*****/inner/img //内置存储缓存目录 File fileCache = new File(this.getCacheDir(), fileInnerName); // /data/data/*****/cache/inner/img if (!fileDir.exists()) { boolean isInner = fileDir.mkdirs(); System.out.println(isInner); } if (!fileCache.exists()) { boolean isInner = fileCache.mkdirs(); System.out.println(isInner); } Log.i(" wqtest ", fileDir.getAbsolutePath() + " " + fileCache.getAbsolutePath()); mPathView.save(fileCache.getAbsolutePath() + File.separator + System.currentTimeMillis() + "wq.jpg", true, 10); mPathView.save(fileDir.getAbsolutePath() + File.separator + System.currentTimeMillis() + "wq.jpg", true, 10); // setResult(100); } catch (IOException e) { e.printStackTrace(); }
外部私有目录 (context.getExternalCacheDir())
String fileOutName = "/AutDir/fileOut";
if (!isExternalStorageWritable()) {
return;
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
File fileOut = new File(getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES) + fileOutName); //
/storage/emulated/0/Android/data/com.android.imageloaderstorage/files/Pictures/AutDir/fileOut
boolean flag = fileOut.mkdirs();
Log.i("FileFragment", fileOut.getAbsolutePath());
}
//缓存目录
File fileOutCache = new File(getActivity().getExternalCacheDir() + fileOutName); //
/storage/emulated/0/Android/data/com.android.imageloaderstorage/cache/AutDir/fileOut
Boolean isInner = fileOutCache.mkdirs();
Log.i("FileFragment", " 路径 " + fileOutCache.getAbsolutePath());
外部公共目录
protected void createOutPublicDir() {
if (!isExternalStorageWritable()) {
return;
}
File filePublic = new File(Environment.getExternalStorageDirectory() + fileOutPublicName); // /storage/emulated/0/AutPublic/outDir
if (!filePublic.exists()) {
filePublic.mkdirs();
}
}
int checkSelfPermission(String permission)
用来检测应用是否已经具有权限void requestPermissions(String[] permissions, int requestCode)
进行请求单个或多个权限void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
请求权限结果回调
checkSelfPermission(String permission) 方法返回值有两个:
- PERMISSION_DENIED = -1:代表当前检查的权限没有被授权
- PERMISSION_GRANTED = 0;代表当前的检查的权限已经被授权
requestPermissions(String[] permissions, int requestCode)
参数一:要请求的权限组 权限2请求码
onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
请求的回调。
参数3对应 对应permissions的权限请求结果(PERMISSION_GRANTED或者PERMISSION_DENIED)