/* * 第一步:新建檔案 res/xml/file_paths.xml <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path path="." name="camera_photos" /> </paths> * 第二步:AndroidManifest.xml檔案的application標籤中插入下邊 <provider android:name="androidx.core.content.FileProvider" android:authorities="com.lrogzin.memo.fileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> * 第三步:在你需要的地方呼叫startCamera() * 第四步:在你的onActivityResult()中加入: * * */ public class UseSysCameraUtil { public static final int CAMERA_CODE = 110; public static Uri takePictureUri;//拍照圖片uri private static Uri cropPictureTempUri;//裁剪圖片uri private static File takePictureFile;//拍照圖片File public static void startCamera(Activity activity, String displayName) { takePictureUri = createImagePathUri(activity, displayName); if (takePictureUri != null) { Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); i.putExtra(MediaStore.EXTRA_OUTPUT, takePictureUri);//輸出路徑(拍照後的儲存路徑) activity.startActivityForResult(i, CAMERA_CODE); } else { Toast.makeText(activity, "開啟相機失敗", Toast.LENGTH_LONG).show(); } } public static Uri createImagePathUri(Activity activity, String displayName) { //適配 Android=Q Android=7 API=29 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { //圖片名稱 //String displayName = String.valueOf(System.currentTimeMillis()); //String displayName = "head"; ContentValues values = new ContentValues(2); values.put(MediaStore.Images.Media.DISPLAY_NAME, displayName); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); //SD 卡是否可用,可用則用 SD 卡,否則用內部儲存 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { takePictureUri = activity.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } else { takePictureUri = activity.getContentResolver().insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); } } else { String pathName = new StringBuffer().append(FileUtils.getExtPicturesPath()).append(File.separator) .append(System.currentTimeMillis()).append(".jpg").toString(); takePictureFile = new File(pathName); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //解決Android 7.0 拍照出現FileUriExposedException的問題 String authority = activity.getPackageName() + ".fileProvider"; takePictureUri = FileProvider.getUriForFile(activity, authority, takePictureFile); } else { takePictureUri = Uri.fromFile(takePictureFile); } } return takePictureUri; } public static void onCameraRes(int requestCode, int resultCode, Activity activity) { try { if (requestCode == CAMERA_CODE && resultCode == activity.RESULT_OK) { Bitmap headBitmap = BitmapFactory.decodeStream(activity.getContentResolver().openInputStream(takePictureUri)); //mainAvatar.setImageBitmap(headBitmap); } } catch (Exception e) { //throw new RuntimeException(e); e.printStackTrace(); } } public static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); //質量壓縮方法,這裡100表示不壓縮,把壓縮後的資料存放到baos中 image.compress(Bitmap.CompressFormat.JPEG, 100, baos); int options = 100; //迴圈判斷如果壓縮後圖片是否大於100kb,大於繼續壓縮 while (baos.toByteArray().length / 1024 > 100) { baos.reset();//重置baos即清空baos //第一個引數 :圖片格式 ,第二個引數: 圖片質量,100為最高,0為最差 ,第三個引數:儲存壓縮後的資料的流 image.compress(Bitmap.CompressFormat.JPEG, options, baos); //這裡壓縮options,把壓縮後的資料存放到baos中 //每次都減少10 options -= 10; if (options <= 0) break; } //把壓縮後的資料baos存放到ByteArrayInputStream中 ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray()); //把ByteArrayInputStream資料生成圖片 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null); return bitmap; } static int CROP_CODE = 3; //呼叫系統的裁剪功能的實現 /* * onActivityResult() * case CROP_CODE: //裁剪返回的 if (data != null) { Bundle extras = data.getExtras(); headBitmap = extras.getParcelable("data"); if (headBitmap != null) { mainAvatar.setImageBitmap(headBitmap);// 用ImageView顯示出來 dialogAvatar.setImageBitmap(headBitmap); } } */ public static void cropPhoto(Uri uri, Activity activity) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); // aspectX aspectY 是寬高的比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); // outputX outputY 是裁剪圖片寬高 intent.putExtra("outputX", 150); intent.putExtra("outputY", 150); intent.putExtra("return-data", true); activity.startActivityForResult(intent, CROP_CODE); } int PERMISSIONS_REQUEST_CAMERA = 1111; // 請求相機許可權 private void requestCameraPermission(Activity activity) { if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, PERMISSIONS_REQUEST_CAMERA); } else { //goCamera(); //jumpToTakePhoto(); //startCamera(); } } /*@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSIONS_REQUEST_CAMERA) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 許可權被授予,執行拍照操作 //goCamera(); //jumpToTakePhoto(); startCamera(); } else { // 許可權被拒絕 Toast.makeText(activity, "Camera permission is required to take a photo.", Toast.LENGTH_SHORT).show(); } } }*/ /** * 獲取圖片路徑 * * @param context Context * @param uri 圖片 Uri * @return 圖片路徑 */ public static String getImagePath(Context context, Uri uri) { Cursor cursor = null; try { String[] proj = {MediaStore.Images.Media.DATA}; cursor = context.getContentResolver().query(uri, proj, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String s = cursor.getString(column_index); return s; } finally { if (cursor != null) { cursor.close(); } } } /** * 獲取圖片 Uri * * @param context Context * @param path 圖片路徑 * @return 圖片 Uri */ public static Uri getImageUri(Context context, String path) { Cursor cursor = context.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.Media._ID}, MediaStore.Images.Media.DATA + "=? ", new String[]{path}, null); if (cursor != null && cursor.moveToFirst()) { int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID)); Uri baseUri = Uri.parse("content://media/external/images/media"); return Uri.withAppendedPath(baseUri, "" + id); } else { if (new File(path).exists()) { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DATA, path); return context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } else { return null; } } } }
public final class FileUtils { /** * 得到SD卡根目錄,SD卡不可用則獲取內部儲存的根目錄 */ public static File getRootPath() { File path = null; if (sdCardIsAvailable()) { path = Environment.getExternalStorageDirectory(); //SD卡根目錄 /storage/emulated/0 } else { path = Environment.getDataDirectory();//內部儲存的根目錄 /data } return path; } /** * 獲取圖片目錄 * * @return 圖片目錄(/storage/emulated/0/Pictures) */ public static File getExtPicturesPath() { File extPicturesPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); if (!extPicturesPath.exists()) { extPicturesPath.mkdir(); } return extPicturesPath; } /** * 獲取快取圖片的目錄 * * @param context Context * @return 快取圖片的目錄 */ public static String getImageCacheDir(Context context) { String cachePath; if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { cachePath = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getPath(); } else { cachePath = context.getCacheDir().getPath(); } return cachePath; } /** * 刪除快取圖片目錄中的全部圖片 * * @param context */ public static void deleteAllCacheImage(Context context) { String cacheImagePath = getImageCacheDir(context); File cacheImageDir = new File(cacheImagePath); File[] files = cacheImageDir.listFiles(); if (files != null) { for (File file : files) { if (file.isFile()) { file.delete(); } } } } /** * SD卡是否可用 */ public static boolean sdCardIsAvailable() { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { File sd = new File(Environment.getExternalStorageDirectory().getPath()); return sd.canWrite(); } else return false; } /** * 判斷目錄是否存在,不存在則判斷是否建立成功 * * @param dirPath 檔案路徑 * @return {@code true}: 存在或建立成功<br>{@code false}: 不存在或建立失敗 */ public static boolean createOrExistsDir(String dirPath) { return createOrExistsDir(getFileByPath(dirPath)); } /** * 判斷目錄是否存在,不存在則判斷是否建立成功 * * @param file 檔案 * @return {@code true}: 存在或建立成功<br>{@code false}: 不存在或建立失敗 */ public static boolean createOrExistsDir(File file) { // 如果存在,是目錄則返回true,是檔案則返回false,不存在則返回是否建立成功 return file != null && (file.exists() ? file.isDirectory() : file.mkdirs()); } /** * 根據檔案路徑獲取檔案 * * @param filePath 檔案路徑 * @return 檔案 */ public static File getFileByPath(String filePath) { return isSpace(filePath) ? null : new File(filePath); } /** * 判斷字串是否為 null 或全為空白字元 * * @param s * @return */ private static boolean isSpace(final String s) { if (s == null) return true; for (int i = 0, len = s.length(); i < len; ++i) { if (!Character.isWhitespace(s.charAt(i))) { return false; } } return true; } }