参考:
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中直接引用

更多相关文章

  1. Android 之多点触摸 手势拉伸放大缩小图片 并在ImageView上画圆
  2. Android 背景图片重复平铺
  3. Android 实现缩小图片像素
  4. Android异步加载图片,并缓存到SD卡
  5. Android中屏幕密度和图片大小的关系分析
  6. android 动态向Gallery中添加图片及倒影&&3D效果
  7. Android动态权限管理
  8. Android图片堆叠效果实现
  9. android TextView和EditText中显示图片

随机推荐

  1. Android(安卓)Studio 配置使用GreenDao3.
  2. Android Q 下拉状态栏快捷开关解析
  3. 传智播客Android核心基础课程视频教程(收
  4. android studio编译错误 之 Cause: com/a
  5. Android 创建菜单栏
  6. relative相关属性
  7. android调用系统发短信界面功能
  8. ubuntu共享文件夹设置
  9. Drawable Mutations(Android(安卓)Drawab
  10. 【建议收藏】2020年中高级Android大厂面