Android 7.0 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更。本文重点介绍您应该了解并在开发应用时加以考虑的一些主要变更。
Android 7.0都有哪些变化呢,我们作为开发者需要注意什么呢。下面一一讲解常用的几个变化。
<1> 共享文件(访问系统相机)
(1) 简介
对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。
要在应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类。如需了解有关权限和共享文件的详细信息,请参阅共享文件。
(2) 代码
【1】清单文件
<provider android:name="androidx.core.content.FileProvider" androidx包 android:name="android.support.v4.content.FileProvider" v4包 android:authorities="com.example.test.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepath" /> </provider><!-- 相机权限 --> <uses-permission android:name="android.permission.CAMERA"/> <!--读写存储卡权限--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.PERMISSIONS_STORAGE"/>
【2】 项目配置
<?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="external_files" path="."/> </paths>
【3】 相关代码
package com.wjn.viewlistdemo.activity.fragment; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.provider.MediaStore; import android.support.annotation.Nullable; import android.support.v4.content.FileProvider; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.text.format.DateFormat; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.wjn.viewlistdemo.R; import java.io.File; import java.util.Calendar; import java.util.Locale; public class MyActivity extends AppCompatActivity { public static final int REQUEST_CODE_TAKE_PHOTO = 1; public static String PICTURTemporary_Path = "ViewListDemo/Temporary/";//图片临时文件 private String filePath; private TextView textView; private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); initView(); } /** * 初始化各种View */ private void initView() { textView = findViewById(R.id.activity_my_textview); imageView = findViewById(R.id.activity_my_imageview); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { takePhoto(); } }); } /** * 手机拍照 */ public void takePhoto() { if (isSdCardExist()) { Uri photoURI = null; Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getPackageManager()) != null) { //创建一个File String name = String.valueOf(System.currentTimeMillis()); filePath = createAvatarPathPicture(name); File photoFile = new File(filePath); Log.d("MyActivity", "name----:" + name); Log.d("MyActivity", "filePath----:" + filePath); if (photoFile != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //如果是7.0及以上的系统使用FileProvider的方式创建一个Uri photoURI = FileProvider.getUriForFile(MyActivity.this, "com.wjn.viewlistdemo.fileprovider", photoFile); takePictureIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); takePictureIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } else { //7.0以下使用这种方式创建一个Uri photoURI = Uri.fromFile(photoFile); } //将Uri传递给系统相机 takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); startActivityForResult(takePictureIntent, REQUEST_CODE_TAKE_PHOTO); } } } else { Toast.makeText(MyActivity.this, "内存卡不可用", Toast.LENGTH_LONG).show(); } } /** * 内存卡是否可用 */ private boolean isSdCardExist() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } /** * 获取sd卡根路径 */ private String getTheRootDirectory() { String result = ""; if (isSdCardExist()) { result = Environment.getExternalStorageDirectory() + "/"; } return result; } /** * 保存图片的文件夹 */ private String createAvatarPathPicture(String userName) { String dir = getTheRootDirectory() + PICTURTemporary_Path; File destDir = new File(dir); if (!destDir.exists()) { destDir.mkdirs(); } File file; if (userName != null) { file = new File(dir, userName + ".png"); } else { file = new File(dir, new DateFormat().format("yyyy_MMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".png"); } return file.getAbsolutePath(); } /** * onActivityResult */ @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_TAKE_PHOTO && resultCode == RESULT_OK) { if (!TextUtils.isEmpty(filePath)) { File file = new File(filePath); Uri uri = Uri.fromFile(file); String path = uri.getPath(); if (!TextUtils.isEmpty(path)) { Bitmap bitmap = BitmapFactory.decodeFile(path); imageView.setImageBitmap(bitmap); Log.d("MyActivity", "设置Bitmap"); } } } } }
注意:一般相机获取的图片上传服务器成功后,要把临时存储的图片删除,这样对于用户想的好接受。
附:权限相关:https://blog.csdn.net/weixin_37730482/article/details/71158257
附:官网:https://developer.android.google.cn/about/versions/nougat