1. 程式人生 > >android 拍照本本地選擇圖片上傳

android 拍照本本地選擇圖片上傳

好久沒有坐下來安安靜靜的寫部落格了 ,上一篇寫的是自定義相機 ,以前專案中用過一些第三方的庫 ,萬物歸終今天找個時間總結一下 ,做開發幾年了 。隨著android studio的運用,開源資源越來越多,越來越好用 ,但是使用第三方的開原始碼,越來越不爽 ,很多庫漸漸的丟下了 ,比如說EventBus ,剛開始的時候覺得好像神奇 ,用多了 。感覺程式碼不是很直觀 ,就慢慢不用了 ,還是覺得自己寫的回撥介面好用。

  好了,不說廢話了 ,一直以來開發平臺都是RK晶片 5.0系統的,有時候也做一些APK ,上次出現的androdi7.0的問題,今天整理下 。拍照,選中本地圖片,切割,老生常談,無論使用開源,還是自定義 ,現在發現還是android系統提供的好用,畢竟androi d都8.0了,越來越好用 。

 android7.0 ,拍照,選擇圖片,不能和以前一樣使用了 ,增加了許可權的管理 ,直接看程式碼 。 相對以前的使用區別還是挺明顯的

 0:先貼一個常量類,一會後邊要使用

public class AppConstant {
    /***
     * 拍照返回圖片的
     */
public static final String cameralSavePath = ApInfo.IMAGE_URL + "/camera.jpg";
    public static final String CACHE_IMAGE = ApInfo.IMAGE_URL + "/cache.jpg";
public static final String authorities = "com.mirrormobile.fileprovider"; public static final int CAMERA_IMAGE_BACK = 5612; public static final int CUT_IMAGE_BACK = 23456; public static final int IMAGE_CUT_BACK = 5617; /*** * 選擇本地相簿 */ public static final int LOCAL_FILE_BACK
= 56452; public static final String TAG_LOCALFILE_BACK = "TAG_LOCALFILE_BACK";}

1:res中新建 xml 資料夾,在xml中新建file_paths.xml

    patH後邊的路徑是包名

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
name="files_root"
path="Android/data/com.mirrormobile/" />
    <external-path
name="external_storage_root"
path="." />
</paths>

2:在清單檔案中註冊 :com.mirrormobile  是包名

      resource中是剛才新建的xml的路徑

<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mirrormobile.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
    <meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>

3:新建工具類 :   ImageCutUtil,用來拍照,本地選擇,切割圖片

   android 6.0 以後使用隱私的許可權,需要申請許可權,這裡我用的是HiPermission ,大家可以去github去看,使用還是挺方便的,這裡就只貼程式碼了 ,Buid.gradle中引用一下

//hipermission
compile 'me.weyye.hipermission:library:1.0.7'

    去請求相機許可權 ,通過後去呼叫系統

/***
 * 檢查相機許可權
 */
public void checkCameraPermission() {
    List<PermissionItem> permissions = new ArrayList<PermissionItem>();
permissions.add(
            new PermissionItem(Manifest.permission.CAMERA, "SD卡讀取許可權", R.drawable.permission_ic_phone));
HiPermission.create(context).title(context.getString(R.string.permission_cus_title)).permissions(
            permissions).msg(context.getString(R.string.permission_cus_msg)).animStyle(R.style.PermissionAnimModal).style(
            R.style.PermissionDefaultBlueStyle).checkMutiPermission(new PermissionCallback() {
        @Override
public void onClose() {
            Log.e("main", "====onClose====");
}

        @Override
public void onFinish() {
            try {
                takeCameraPhoto();
} catch (Exception e) {
                MyToastView.getInstance().Toast(context, e.toString());
Log.e("main", "====開啟相機異常====" + e.toString());
}
        }

        @Override
public void onDeny(String permission, int position) {
            Log.e("main", "====開啟相機異常====");
MyToastView.getInstance().Toast(context, "您拒絕了" + permission + "許可權,請手動開啟");
}

        @Override
public void onGuarantee(String permission, int position) {
            Log.e("main", "====onGuarantee====");
}
    });
}
/***
 * 拍照返回
 */
public void takeCameraPhoto() {
    try {
        FileUtils.creatFileNotExciet();
File file = new File(AppConstant.cameralSavePath);
        if (file.exists()) {
            file.delete();
}
        file.createNewFile();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {  //7.0執行該方法
Uri imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, file);
Intent intent = new Intent();
//新增這一句表示對目標應用臨時授權該Uri所代表的檔案
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//設定Action為拍照
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//將拍取的照片儲存到指定URI
context.startActivityForResult(intent, AppConstant.CAMERA_IMAGE_BACK);
} else {  //7.0以下手機系統執行這個方法
Intent getPhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = Uri.fromFile(file);
getPhoto.putExtra(MediaStore.EXTRA_OUTPUT, uri);//根據uri儲存照片
getPhoto.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//儲存照片的質量
context.startActivityForResult(getPhoto, AppConstant.CAMERA_IMAGE_BACK);//啟動相機拍照
}
    } catch (Exception e) {
        MyToastView.getInstance().Toast(context, e.toString());
}
}
    拍照的時候,判斷一下當前的系統版本,7.0以前使用的url .7.0以後是使用FileProvider來訪問本地圖片

    選擇本地的圖片 ,同理,需要分系統來操作

    接下來就是圖片切割了 ,7.0的使用方法相比以前的要稍微複雜一點,但是系統的切割用著舒服 ,簡單的呼叫,如果覺得介面不好看,那就智慧自己去想辦法了 ,去引用第三方 ,或者自己寫  ,註釋比較清楚,不解釋了

/***
 * 裁切圖片
 * @param inputUrl
*     裁切圖片的url
 * @param outputUrl
* 儲存的圖片的url
 */
public void cutImage(String inputUrl, String outputUrl) {
    try {
        File file_out = new File(outputUrl);
        if (file_out.exists()) {
            file_out.delete();
}
        file_out.createNewFile();
cropPicture(inputUrl, outputUrl);
} catch (Exception e) {
        Log.e(TAG, "====裁切圖片異常=--" + e.toString());
MyToastView.getInstance().Toast(context, e.toString());
}
}

/**
 * 呼叫系統剪裁功能
 */
public void cropPicture(String inputUrl, String output) {
    File fileinput = new File(inputUrl);
Uri imageUri;
Uri outputUri;
Intent intent = new Intent("com.android.camera.action.CROP");
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, fileinput);
outputUri = Uri.fromFile(new File(output));
} else {
        imageUri = Uri.fromFile(fileinput);
outputUri = Uri.fromFile(new File(output));
}
    intent.setDataAndType(imageUri, "image/*");
intent.putExtra("crop", "true");
//設定寬高比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 2);
//設定裁剪圖片寬高
    // intent.putExtra("outputX", 300);
    // intent.putExtra("outputY", 300);
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
context.startActivityForResult(intent, AppConstant.IMAGE_CUT_BACK);
}

   介面呼叫初始化這個工具類 ,然後直接呼叫許可權的方法就可以了,我們看一下OnActivityForResult()這個方法

String updatePath = "";
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == AppConstant.CAMERA_IMAGE_BACK) { //拍照返回的資料
imageCutUtil.cutImage(AppConstant.cameralSavePath, AppConstant.CACHE_IMAGE);
} else if (requestCode == AppConstant.LOCAL_FILE_BACK) {
        String filePath = data.getStringExtra(AppConstant.TAG_LOCALFILE_BACK);
imageCutUtil.cutImage(filePath, AppConstant.CACHE_IMAGE);
} else if (requestCode == AppConstant.IMAGE_CUT_BACK) {  //切割之後返回的資料
Bitmap bitmap = BitmapFactory.decodeFile(AppConstant.CACHE_IMAGE);
iv_show_image.setImageBitmap(bitmap);
updatePath = AppConstant.CACHE_IMAGE;
}
}

    選擇本地也就簡單了,結合上邊的程式碼 ,處理起來比較簡單,檢查許可權,開啟本地相簿

 public void checkSdImagePermiss() {
        List<PermissionItem> permissions = new ArrayList<PermissionItem>();
permissions.add(new PermissionItem(Manifest.permission.READ_EXTERNAL_STORAGE, "SD卡讀取許可權", R.drawable.permission_ic_phone));
permissions.add(new PermissionItem(Manifest.permission.WRITE_EXTERNAL_STORAGE, "SD卡讀取許可權", R.drawable.permission_ic_phone));
HiPermission.create(context).title(context.getString(R.string.permission_cus_title)).permissions(
                permissions).msg(context.getString(R.string.permission_cus_msg)).animStyle(R.style.PermissionAnimModal).style(
                R.style.PermissionDefaultBlueStyle).checkMutiPermission(new PermissionCallback() {
            @Override
public void onClose() {
                Log.i(TAG, "使用者拒絕我們的許可權");
}

            @Override
public void onFinish() {
                try {
                    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
context.startActivityForResult(intent, AppConstant.LOCAL_FILE_BACK);
//                    Intent intent = new Intent(context, LoImgChooiceActivity.class);
//                    context.startActivityForResult(intent, AppConstant.LOCAL_FILE_BACK);
} catch (Exception e) {
                    Log.e("main", "====開啟相機異常====" + e.toString());
}
            }

      介面的onActivityForResult(),接受到資料,直接吧資料丟給Util去處理

    String updatePath = "";
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == AppConstant.CAMERA_IMAGE_BACK) { //拍照返回的資料
imageCutUtil.cutImage(AppConstant.cameralSavePath, AppConstant.CACHE_IMAGE);
} else if (requestCode == AppConstant.LOCAL_FILE_BACK) {  //本地圖片選擇
imageCutUtil.cutImageLocal(data);
//            String filePath = data.getStringExtra(AppConstant.TAG_LOCALFILE_BACK);
//            imageCutUtil.cutImage(filePath, AppConstant.CACHE_IMAGE);
} else if (requestCode == AppConstant.IMAGE_CUT_BACK) {  //切割之後返回的資料
Bitmap bitmap = BitmapFactory.decodeFile(AppConstant.CACHE_IMAGE);
iv_show_image.setImageBitmap(bitmap);
updatePath = AppConstant.CACHE_IMAGE;
}
    }
/***
 * 本地圖片選擇器
 * @param data
*/
public void cutImageLocal(Intent data) {
    Uri imageUri = data.getData();
String url_out = AppConstant.CACHE_IMAGE;
File file_out = new File(AppConstant.CACHE_IMAGE);
    if (file_out.exists()) {
        file_out.delete();
}
    Uri outputUri = Uri.fromFile(new File(url_out));
cutImage(imageUri, outputUri);
}
   直接獲取圖片的URI ,然後直接去裁切 。下面貼上全部程式碼 ;
package com.mirror.mobile.util.image;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.util.Log;
import com.cdl.dialog.toast.MyToastView;
import com.mirror.mobile.test.LoImgChooiceActivity;
import com.mirror.mobile.util.FileUtils;
import com.mirror.mobile.util.updatepic.AppConstant;
import com.mirrormobile.R;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import me.weyye.hipermission.HiPermission;
import me.weyye.hipermission.PermissionCallback;
import me.weyye.hipermission.PermissionItem;
/***
 * 圖片裁剪工具類
 */
public class ImageCutUtil {
    Activity context;
    private static final String TAG = "MAIN";
    public ImageCutUtil(Activity context) {
        this.context = context;
}


    //===============================================================================================================================
/***
     * 本地圖片選擇器
     * @param data
*/
public void cutImageLocal(Intent data) {
        Uri imageUri = data.getData();
String url_out = AppConstant.CACHE_IMAGE;
File file_out = new File(AppConstant.CACHE_IMAGE);
        if (file_out.exists()) {
            file_out.delete();
}
        Uri outputUri = Uri.fromFile(new File(url_out));
cutImage(imageUri, outputUri);
}

    //============================================================================================================================================
public void cutImage(String inputUrl, String output) {
        try {
            File file_out = new File(output);
            if (file_out.exists()) {
                file_out.delete();
}
            file_out.createNewFile();
File fileinput = new File(inputUrl);
Uri imageUri;
Uri outputUri;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, fileinput);
outputUri = Uri.fromFile(new File(output));
} else {
                imageUri = Uri.fromFile(fileinput);
outputUri = Uri.fromFile(new File(output));
}
            cutImage(imageUri, outputUri);
} catch (Exception e) {
        }
    }

    public void cutImage(Uri imageUri, Uri outputUri) {
        try {
            Intent intent = new Intent("com.android.camera.action.CROP");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
            intent.setDataAndType(imageUri, "image/*");
intent.putExtra("crop", "true");
//設定寬高比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 2);
intent.putExtra("scale", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
context.startActivityForResult(intent, AppConstant.IMAGE_CUT_BACK);
} catch (Exception e) {
        }
    }


//    public void cutImage(String inputUrl, String output) {
//        try {
//            File file_out = new File(output);
//            if (file_out.exists()) {
//                file_out.delete();
//            }
//            file_out.createNewFile();
//            File fileinput = new File(inputUrl);
//            Uri imageUri;
//            Uri outputUri;
//            Intent intent = new Intent("com.android.camera.action.CROP");
//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//                imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, fileinput);
//                outputUri = Uri.fromFile(new File(output));
//            } else {
//                imageUri = Uri.fromFile(fileinput);
//                outputUri = Uri.fromFile(new File(output));
//            }
//            intent.setDataAndType(imageUri, "image/*");
//            intent.putExtra("crop", "true");
//            //設定寬高比例
//            intent.putExtra("aspectX", 1);
//            intent.putExtra("aspectY", 2);
//            //設定裁剪圖片寬高
//            // intent.putExtra("outputX", 300);
//            // intent.putExtra("outputY", 300);
//            intent.putExtra("scale", true);
//            intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
//            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
//            intent.putExtra("noFaceDetection", true);
//            context.startActivityForResult(intent, AppConstant.IMAGE_CUT_BACK);
//        } catch (Exception e) {
//        }
//    }
public void checkSdImagePermiss() {
        List<PermissionItem> permissions = new ArrayList<PermissionItem>();
permissions.add(new PermissionItem(Manifest.permission.READ_EXTERNAL_STORAGE, "SD卡讀取許可權", R.drawable.permission_ic_phone));
permissions.add(new PermissionItem(Manifest.permission.WRITE_EXTERNAL_STORAGE, "SD卡讀取許可權", R.drawable.permission_ic_phone));
HiPermission.create(context).title(context.getString(R.string.permission_cus_title)).permissions(
                permissions).msg(context.getString(R.string.permission_cus_msg)).animStyle(R.style.PermissionAnimModal).style(
                R.style.PermissionDefaultBlueStyle).checkMutiPermission(new PermissionCallback() {
            @Override
public void onClose() {
                Log.i(TAG, "使用者拒絕我們的許可權");
}

            @Override
public void onFinish() {
                try {
                    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
context.startActivityForResult(intent, AppConstant.LOCAL_FILE_BACK);
//                    Intent intent = new Intent(context, LoImgChooiceActivity.class);
//                    context.startActivityForResult(intent, AppConstant.LOCAL_FILE_BACK);
} catch (Exception e) {
                    Log.e("main", "====開啟相機異常====" + e.toString());
}
            }

            @Override
public void onDeny(String permission, int position) {
                MyToastView.getInstance().Toast(context, "您拒絕了" + permission + "許可權,請手動開啟");
Log.i(TAG, "使用者禁止了許可權" + permission);
}

            @Override
public void onGuarantee(String permission, int position) {
                Log.i(TAG, "onGuarantee");
}
        });
}

    /***
     * 檢查相機許可權
     */
public void checkCameraPermission() {
        List<PermissionItem> permissions = new ArrayList<PermissionItem>();
permissions.add(
                new PermissionItem(Manifest.permission.CAMERA, "SD卡讀取許可權", R.drawable.permission_ic_phone));
HiPermission.create(context).title(context.getString(R.string.permission_cus_title)).permissions(
                permissions).msg(context.getString(R.string.permission_cus_msg)).animStyle(R.style.PermissionAnimModal).style(
                R.style.PermissionDefaultBlueStyle).checkMutiPermission(new PermissionCallback() {
            @Override
public void onClose() {
                Log.e("main", "====onClose====");
}

            @Override
public void onFinish() {
                try {
                    takeCameraPhoto();
} catch (Exception e) {
                    MyToastView.getInstance().Toast(context, e.toString());
Log.e("main", "====開啟相機異常====" + e.toString());
}
            }

            @Override
public void onDeny(String permission, int position) {
                Log.e("main", "====開啟相機異常====");
MyToastView.getInstance().Toast(context, "您拒絕了" + permission + "許可權,請手動開啟");
}

            @Override
public void onGuarantee(String permission, int position) {
                Log.e("main", "====onGuarantee====");
}
        });
}

    /***
     * 拍照返回
     */
public void takeCameraPhoto() {
        try {
            FileUtils.creatFileNotExciet();
File file = new File(AppConstant.cameralSavePath);
            if (file.exists()) {
                file.delete();
}
            file.createNewFile();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {  //7.0執行該方法
Uri imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, file);
Intent intent = new Intent();
//新增這一句表示對目標應用臨時授權該Uri所代表的檔案
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//設定Action為拍照
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//將拍取的照片儲存到指定URI
context.startActivityForResult(intent, AppConstant.CAMERA_IMAGE_BACK);
} else {  //7.0以下手機系統執行這個方法
Intent getPhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = Uri.fromFile(file);
getPhoto.putExtra(MediaStore.EXTRA_OUTPUT, uri);//根據uri儲存照片
getPhoto.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//儲存照片的質量
context.startActivityForResult(getPhoto, AppConstant.CAMERA_IMAGE_BACK);//啟動相機拍照
}
        } catch (Exception e) {
            MyToastView.getInstance().Toast(context, e.toString());
}
    }

}

  介面拍照 ,獲取相簿程式碼

@Override
public void clickFirst() { //拍照
imageCutUtil.checkCameraPermission();
}

@Override
public void clickSecond() {   //本地取圖片
imageCutUtil.checkSdImagePermiss();
}
    String updatePath = "";
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == AppConstant.CAMERA_IMAGE_BACK) { //拍照返回的資料
imageCutUtil.cutImage(AppConstant.cameralSavePath, AppConstant.CACHE_IMAGE);
} else if (requestCode == AppConstant.LOCAL_FILE_BACK) {  //本地圖片選擇
imageCutUtil.cutImageLocal(data);
//            String filePath = data.getStringExtra(AppConstant.TAG_LOCALFILE_BACK);
//            imageCutUtil.cutImage(filePath, AppConstant.CACHE_IMAGE);
} else if (requestCode == AppConstant.IMAGE_CUT_BACK) {  //切割之後返回的資料
Bitmap bitmap = BitmapFactory.decodeFile(AppConstant.CACHE_IMAGE);
iv_show_image.setImageBitmap(bitmap);
updatePath = AppConstant.CACHE_IMAGE;
}
    }