|
1. 背景
Environment.getExternalStorageDirectory()是Android 2.x时代的产物,那时Android主流设备只有很小的内置存储器,然后都会外置一张sd卡,那时这个方法返回的就是外置sd卡的根路径。
但随着Android进入4.x时代,大部分Android设备都已经内置一个较大存储卡,甚至不提供外置存储卡插槽了,此时Environment.getExternalStorageDirectory()返回的路径其实是由内置存储卡虚拟出来的一个目录,用户在这一目录下有全部权限。
按理说Android应该继续提供其他的方法来返回其他的外置存储卡的路径,但这一次Android却没有,因为Android系统开发者们发现之前直接允许程序任意访问sd卡的做法导致sd卡上垃圾文件的不可管理性,尤其在程序被卸载后,由于不知道那些文件是由这一程序创建的,所以无法关联删除,因此Android 4.0并不给程序开发者提供外置存储卡的路径,而是提供了诸如getExternalFilesDirs()和getExternalCacheDirs()这样的方法,直接给开发者提供一个限制内的存储文件的空间,这个空间是与程序关联的,因此在卸载程序时这两个目录下的文件也会被关联删除。
2.问题一
在AndroidManifest里写入了相机权限,读写权限,但华为手机调用Camera失败,无法写入手机内存等。
原因:Android系统从6.0版本开始增加了一种运行时权限,Camera正好属于运行时权限,这种权限的授权不像6.0以前的Android系统可以安装APP的时候就一次性授权。所以需要在代码里手动申请权限。某些程序在华为G9上一测试就崩掉的原因:程序在运行中请求camera.open()时实际上程序并未获得操作Camera的权限,所以camera.open()会一直打开失败。对于运行时权限不清楚的可以百度搜索Android6.0运行时权限。
问题二
华为G9手机Environment.getExternalStorageDirectory()得到的是什么?
答:从手机上自带的文件管理器来看,上面有两个存储位置,一个是内部存储,是华为G9内置的SD卡;一个是SanDisk SD 卡,这个是自己买的然后安装上去的。那么,用Environment.getExternalStorageDirectory()得到的是哪个内存里的路径呢?该方法得到的是/storage/emulated/0是内部存储,也就是华为G9内置的SD卡,当然这是我经过测试后得到的,如下图所示。
问题三
使用ContextCompat和ActivityCompat报错
原因:因为这两个是sdk19以上版本v4包新加的,所以要导入V4包,最好是导入最新的版本,步骤file->project structure->dependencies->右边“+”号然后添加v4包即可。
代码部分就只写最主要的吧,最底下有源码地址
MainActivity.java
public class MainActivity extends Activity {
public static final int TAKE_PHOTO = 1;
public static final int CROP_PHOTO = 2;
private static final String IMAGE_FILE_NAME = "head_image.jpg";// 头像文件
private static final int CODE_CAMERA_REQUEST = 0xa1;//拍照请求码
private static String[] PERMISSIONS_STORAGE = {
// Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,//写权限
Manifest.permission.CAMERA//照相权限
};
private Button btn;
private ImageView img;
private Uri imageUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.take_photo);
img = (ImageView) findViewById(R.id.picture);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//用intent调用相机
Intent intentFromCapture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//判断sd卡是否可用
if (SDCardUtils.isSDCardEnable()){
//ContentValues与HashMap类似,但ContentValues只能保存数据类型,不能保存对象类型
ContentValues values = new ContentValues();
//key-value形式
values.put(MediaStore.Images.Media.TITLE,IMAGE_FILE_NAME);
//EXTRA_OUTPUT用于存储所请求的图像或视频的解析Uri
imageUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),IMAGE_FILE_NAME));
intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
}
//
startActivityForResult(intentFromCapture,CODE_CAMERA_REQUEST);
}
});
//用于判断SDK版本是否大于23
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
//检查权限
int i = ContextCompat.checkSelfPermission(this,PERMISSIONS_STORAGE[0]);
//如果权限申请失败,则重新申请权限
if(i!= PackageManager.PERMISSION_GRANTED){
//重新申请权限函数
startRequestPermission();
Log.e("这里","权限请求成功");
}
}
}
/**
* 重新申请权限函数
*/
private void startRequestPermission(){
//321为请求码
ActivityCompat.requestPermissions(this,PERMISSIONS_STORAGE,321);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==CODE_CAMERA_REQUEST&&resultCode==RESULT_OK){
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
img.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
源码地址:http://download.csdn.net/detail/u013293125/9737050 |
|
|