android 10.0拍照显示并上传服务器
16lz
2021-01-23
参考:
okhttp图片上传
Android 调用相机拍照,适配到Android 10
并在大佬的demo上增加了上传图片功能
10.0、9.0、8.0、6.0上试过了都能用。没试过 7.0
直接上代码:
MainActivity
package com.donkingliang.photograph;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import androidx.core.app.ActivityCompat;import androidx.core.content.ContextCompat;import androidx.core.content.FileProvider;import androidx.core.os.EnvironmentCompat;import okhttp3.MediaType;import okhttp3.MultipartBody;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;import okhttp3.Response;import android.Manifest;import android.app.Activity;import android.content.ContentValues;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.graphics.BitmapFactory;import android.net.Uri;import android.os.Build;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.util.Log;import android.view.View;import android.widget.ImageView;import android.widget.Toast;import org.json.JSONException;import org.json.JSONObject;import java.io.File;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Locale;public class MainActivity extends AppCompatActivity { private ImageView ivCamera; private ImageView ivPhoto; // 拍照的requestCode private static final int CAMERA_REQUEST_CODE = 0x00000010; // 申请相机权限的requestCode private static final int PERMISSION_CAMERA_REQUEST_CODE = 0x00000012; /** * 用于保存拍照图片的uri */ private Uri mCameraUri; /** * 用于保存图片的文件路径,Android 10以下使用图片路径访问图片 */ private String mCameraImagePath; /** * 是否是Android 10以上手机 */ private boolean isAndroidQ = Build.VERSION.SDK_INT >= 29; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ivCamera = findViewById(R.id.ivCamera); ivPhoto = findViewById(R.id.ivPhoto); ivCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { checkPermissionAndCamera(); } }); } /** * 检查权限并拍照。 * 调用相机前先检查权限。 */ private void checkPermissionAndCamera() { int hasCameraPermission = ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.CAMERA); if (hasCameraPermission == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, 100); } else if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //没有授权,编写申请权限代码 ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); } else if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //没有授权,编写申请权限代码 ActivityCompat.requestPermissions((Activity) MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 100); } else { //有权限,调起相机拍照。 openCamera(); } } else { //没有权限,申请权限。 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSION_CAMERA_REQUEST_CODE); } } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CAMERA_REQUEST_CODE) { if (resultCode == RESULT_OK) { final String uploadpath; if (isAndroidQ) { // Android 10 使用图片uri加载 ivPhoto.setImageURI(mCameraUri); uploadpath = Uri2PathUtil.getRealPathFromUri(MainActivity.this, mCameraUri); } else { // 使用图片路径加载 ivPhoto.setImageBitmap(BitmapFactory.decodeFile(mCameraImagePath)); uploadpath = mCameraImagePath; } // 6.0 8.0 9.0 适配了。。没试过7.0 new Thread(new Runnable() { @Override public void run() { try { uploadImage("http:。。。。。", uploadpath); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } } }).start(); } else { Toast.makeText(this, "取消", Toast.LENGTH_LONG).show(); } } } public String uploadImage(String url, String imagePath) throws IOException, JSONException { OkHttpClient okHttpClient = new OkHttpClient(); Log.d("imagePath", imagePath); File file = new File(imagePath); RequestBody image = RequestBody.create(MediaType.parse("image/png"), file); RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("path", "taskPlanApp") .addFormDataPart("attach", imagePath, image) .addFormDataPart("thumbnailWidth", "80") .addFormDataPart("thumbnailHeigth", "80") .build(); Request request = new Request.Builder() .url(url) .post(requestBody) .build(); Response response = okHttpClient.newCall(request).execute(); JSONObject jsonObject = new JSONObject(response.body().string()); /** * {"error":0,"message":null,"url":"\/file\/taskPlanApp\/200521\/44a037dc7570417cadb7296d0cf5e5ef.png"} * * */ Integer error = jsonObject.getInt("error"); String msg = jsonObject.getString("message"); if (error == 0) {// imgLoadUrl = jsonObject.getString("url"); } else {// Toast.makeText(ConfirmOldManInfo.this, msg, Toast.LENGTH_SHORT).show(); } return jsonObject.optString("image"); } /** * 处理权限申请的回调。 * * @param requestCode * @param permissions * @param grantResults */ @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == PERMISSION_CAMERA_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, 100); } else if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //没有授权,编写申请权限代码 ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); } else if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //没有授权,编写申请权限代码 ActivityCompat.requestPermissions((Activity) MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 100); } else { //有权限,调起相机拍照。 openCamera(); } } else { //拒绝权限,弹出提示框。 Toast.makeText(this, "拍照权限被拒绝", Toast.LENGTH_LONG).show(); } } } /** * 调起相机拍照 */ private void openCamera() { Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 判断是否有相机 if (captureIntent.resolveActivity(getPackageManager()) != null) { File photoFile = null; Uri photoUri = null; if (isAndroidQ) { // 适配android 10 photoUri = createImageUri(); } else { photoFile = new File(getExternalCacheDir(), "output_image.png"); // 对照片的更换设置 try { // 如果上一次的照片存在,就删除 if (photoFile.exists()) { photoFile.delete(); } // 创建一个新的文件 photoFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } if (photoFile != null) { mCameraImagePath = photoFile.getAbsolutePath(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //适配Android 7.0文件权限,通过FileProvider创建一个content类型的Uri photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile); } else { photoUri = Uri.fromFile(photoFile); } } } mCameraUri = photoUri; if (photoUri != null) { captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(captureIntent, CAMERA_REQUEST_CODE); } } } /** * 创建图片地址uri,用于保存拍照后的照片 Android 10以后使用这种方法 * * @return 图片的uri */ private Uri createImageUri() { String status = Environment.getExternalStorageState(); // 判断是否有SD卡,优先使用SD卡存储,当没有SD卡时使用手机存储 if (status.equals(Environment.MEDIA_MOUNTED)) { return getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues()); } else { return getContentResolver().insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, new ContentValues()); } }}
Uri2PathUtil 路径读取工具类
package com.donkingliang.photograph;import android.annotation.TargetApi;import android.content.ContentUris;import android.content.Context;import android.database.Cursor;import android.net.Uri;import android.os.Build;import android.os.Environment;import android.provider.DocumentsContract;import android.provider.MediaStore;import androidx.loader.content.CursorLoader;public class Uri2PathUtil { //复杂版处理 (适配多种API) public static String getRealPathFromUri(Context context, Uri uri) { int sdkVersion = Build.VERSION.SDK_INT; if (sdkVersion < 11) return getRealPathFromUri_BelowApi11(context, uri); if (sdkVersion < 19) return getRealPathFromUri_Api11To18(context, uri); else return getRealPathFromUri_AboveApi19(context, uri); } /** * 适配api19以上,根据uri获取图片的绝对路径 */ @TargetApi(Build.VERSION_CODES.KITKAT) private static String getRealPathFromUri_AboveApi19(Context context, Uri uri) { if (DocumentsContract.isDocumentUri(context, uri)) { if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } } else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(context, contentUri, null, null); } else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; Uri contentUri; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } else { contentUri = MediaStore.Files.getContentUri("external"); } final String selection = "_id=?"; final String[] selectionArgs = new String[]{split[1]}; return getDataColumn(context, contentUri, selection, selectionArgs); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { return getDataColumn(context, uri, null, null); } else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * 适配api11-api18,根据uri获取图片的绝对路径 */ private static String getRealPathFromUri_Api11To18(Context context, Uri uri) { String filePath = null; String[] projection = {MediaStore.Images.Media.DATA}; //这个有两个包不知道是哪个。。。。不过这个复杂版一般用不到 CursorLoader loader = new CursorLoader(context, uri, projection, null, null, null); Cursor cursor = loader.loadInBackground(); if (cursor != null) { cursor.moveToFirst(); filePath = cursor.getString(cursor.getColumnIndex(projection[0])); cursor.close(); } return filePath; } /** * 适配api11以下(不包括api11),根据uri获取图片的绝对路径 */ private static String getRealPathFromUri_BelowApi11(Context context, Uri uri) { String filePath = null; String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); if (cursor != null && cursor.moveToFirst()) { filePath = cursor.getString(cursor.getColumnIndex(projection[0])); cursor.close(); } return filePath; } /** * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @param selection (Optional) Filter used in the query. * @param selectionArgs (Optional) Selection arguments used in the query. * @return The value of the _data column, which is typically a file path. */ public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; String column = MediaStore.MediaColumns.DATA; String[] projection = {column}; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { int column_index = cursor.getColumnIndexOrThrow(column); return cursor.getString(column_index); } } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) cursor.close(); } return null; } /** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */ public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is MediaProvider. */ public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); }}
AndroidManifest
添加权限
注册provider
在res文件夹中新建xml文件:file_paths
<?xml version="1.0" encoding="utf-8"?>
在app的build.gradle中引用
implementation 'com.zhy:okhttputils:2.6.2'
然后我运行的时候报错
java.net.UnknownServiceException: CLEARTEXT communication ** not permitted by network security policy
解决办法
在xml文件夹中新建:network_security_config
<?xml version="1.0" encoding="utf-8"?>
在application中直接引用
更多相关文章
- Android 之多点触摸 手势拉伸放大缩小图片 并在ImageView上画圆
- Android 背景图片重复平铺
- Android 实现缩小图片像素
- Android异步加载图片,并缓存到SD卡
- Android中屏幕密度和图片大小的关系分析
- android 动态向Gallery中添加图片及倒影&&3D效果
- Android动态权限管理
- Android图片堆叠效果实现
- android TextView和EditText中显示图片