安卓開發-拍照或相簿選擇頭像和執行時動態獲取許可權
專案中都會用到頭像設定,所以記錄一下
效果圖:
在android 6.0推出了執行時許可權,我們獲取使用者手機許可權就沒那麼方便了,先說說執行時許可權:
Permission,執行時許可權
授權許可權
*如果裝置執行的是Android 6(API Level 23)或更高,和應用程式的targetSdkVersion是23或更高,應用程式要求的許可權由使用者在執行時。使用者可以在任何時間撤銷許可權,所以在每次執行時應用程式需要檢查是否有許可權。
許可權可以分為危險許可權和正常許可權,還有特殊許可權、自定義許可權。 正常許可權(PROTECTION_NORMAL)對使用者的隱私或安全沒有大的風險的許可權在AndroidManifest.xml聲明裡,如果應用需要一個正常的許可權,在安裝的時候系統自動授予該許可權。在
\
危險許可權,需要使用時要檢查有沒有授權。如果沒有就彈個對話方塊詢問使用者授權。這類許可權被分組了,同一組的任何一個許可權被授權了,其他許可權也自動被授權。如下表:
比如你需要android.permission.READ_CONTACTS ,去讀聯絡人。這個許可權被使用者授權,然後你用到寫入通訊錄許可權permission:android.permission.WRITE_CONTACTS和permission:android.permission.GET_ACCOUNTS 時,就是授權過的,去申請就不會彈框。
然後如果使用者手機系統高於5.0以上也就是6.0或者7.0,那麼我們在清單檔案AndroidManifest中宣告的許可權就不好使了還需要程式碼獲取許可權
程式碼:
點選按鈕之後是個popuwindow彈窗
change.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { bottomPopupOption = new BottomPopupOption(MainActivity.this); bottomPopupOption.setItemText("拍照","相簿"); bottomPopupOption.showPopupWindow(); bottomPopupOption.setItemClickListener(newBottomPopupOption.onPopupWindowItemClickListener() { @Override public void onItemClick(int position) { bottomPopupOption.dismiss(); switch (position){ case 0: Toast.makeText(MainActivity.this,"拍照",Toast.LENGTH_SHORT).show(); choseHeadImageFromCameraCapture(); break; case 1: Toast.makeText(MainActivity.this,"相簿",Toast.LENGTH_SHORT).show(); choseHeadImageFromGallery(); break; } } }); } });
拍照方法
// 啟動手機相機拍攝照片作為頭像 private void choseHeadImageFromCameraCapture() { //6.0以上動態獲取許可權 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { //申請許可權,REQUEST_TAKE_PHOTO_PERMISSION是自定義的常量 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_TAKE_PHOTO_PERMISSION); } else { Intent intentFromCapture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 判斷儲存卡是否可用,儲存照片檔案 if (hasSdcard()) { intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT, Uri .fromFile(new File(Environment .getExternalStorageDirectory(), IMAGE_FILE_NAME))); } startActivityForResult(intentFromCapture, CODE_CAMERA_REQUEST); } }
相簿方法
// 從本地相簿選取圖片作為頭像 private void choseHeadImageFromGallery() { Intent intentFromGallery = new Intent(); // 設定檔案型別 intentFromGallery.setType("image/*"); intentFromGallery.setAction(Intent.ACTION_PICK); startActivityForResult(intentFromGallery, CODE_GALLERY_REQUEST); }activity回撥
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { // 使用者沒有進行有效的設定操作,返回 if (resultCode == RESULT_CANCELED) { // Toast.makeText(getApplication(), "取消", Toast.LENGTH_LONG).show(); return; } switch (requestCode) { case CODE_GALLERY_REQUEST: cropRawPhoto(intent.getData()); break; case CODE_CAMERA_REQUEST: if (hasSdcard()) { File tempFile = new File( Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME); cropRawPhoto(Uri.fromFile(tempFile)); } else { Toast.makeText(MainActivity.this,"沒有sd卡",Toast.LENGTH_SHORT).show(); } break; case CODE_RESULT_REQUEST: if (intent != null) { setImageToHeadView(intent); File file = new File( Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME); if (file.exists()&&!file.isDirectory()){ file.delete(); } } break; } super.onActivityResult(requestCode, resultCode, intent); }裁剪圖片
/** * 裁剪原始的圖片 */ public void cropRawPhoto(Uri uri) { 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", output_X); intent.putExtra("outputY", output_Y); intent.putExtra("return-data", true); startActivityForResult(intent, CODE_RESULT_REQUEST); } String url = "http://000.000.00.00:8080/ffd/dfdf/fgdfg.do";//測試地址需換自己的伺服器地址 /** * 提取儲存裁剪之後的圖片資料,並設定頭像部分的View */ private void setImageToHeadView(Intent intent) { Bundle extras = intent.getExtras(); if (extras != null) { photo = extras.getParcelable("data"); // photo = intent.getParcelableExtra("data"); circleImageView.setImageBitmap(photo); circleImageView2.setImageBitmap(photo); File nf = new File(Environment.getExternalStorageDirectory()+"/test"); nf.mkdir(); //在根目錄下面的ASk資料夾下 建立okkk.jpg檔案 File f = new File(Environment.getExternalStorageDirectory()+"/test", IMAGE_FILE_NAME); FileOutputStream out = null; try { //開啟輸出流 將圖片資料填入檔案中 out = new FileOutputStream(f); photo.compress(Bitmap.CompressFormat.PNG, 90, out); try { out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } File file = new File(HeadPortrait_PATH); if (!file.exists()){ Toast.makeText(MainActivity.this,"檔案不存在",Toast.LENGTH_SHORT).show(); } try { OkHttpUtils.post(url) .params("userid","") .params("file",file) .execute(new StringCallback() { @Override public void onSuccess(String s, okhttp3.Call call, Response response) { Toast.makeText(MainActivity.this,"上傳成功",Toast.LENGTH_SHORT).show(); } }); } catch (Exception e) { e.printStackTrace(); } } }還有執行時獲取許可權
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_TAKE_PHOTO_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //申請成功,可以拍照 choseHeadImageFromCameraCapture(); } else { Toast.makeText(MainActivity.this,"你拒絕了許可權,該功能不可用\n可在應用設定裡授權拍照哦",Toast.LENGTH_SHORT).show(); } return; } super.onRequestPermissionsResult(requestCode, permissions, grantResults); }
demo地址:
https://github.com/PangHaHa12138/MyUploadPhotodmo"