前言
???????在項(xiàng)目研發(fā)中,相信大家都遇到過給用戶增加頭像照片
的需求。
???????隨著手機(jī)版本的不斷更新,android 8、android 9、android 10、android 12、android 13、鴻蒙系統(tǒng)等等;遇到這個功能需求,大家肯定會想,“這還不好寫? 之前就已經(jīng)寫過了?!?/code> 把老項(xiàng)目跑了一遍之后發(fā)現(xiàn)無法運(yùn)行。要不大多數(shù)就會出現(xiàn)奔潰的情況!
???????這也就遇到常見的 高版本適配情況,以及針對不同版本該如何處理?

???????碰到這種情況也不要慌張,博主將為大家推出兩篇熱乎連載篇。從兩個不同開發(fā)場景下
,來給大家分享兩篇文章,來更加詳細(xì)的了解該如何去實(shí)現(xiàn)?【特此來記錄】
???????本篇將為大家詳細(xì)講解如何調(diào)用攝像頭拍照 & 選擇相冊,并裁剪圖片。
效果
實(shí)測android 8、android 9、android 11、android 13、鴻蒙系統(tǒng)均有效;
手機(jī)機(jī)型分別為OPPO、華為、VIVO手機(jī)。
對于效果演示,將單獨(dú)拿出兩個來舉例:
- VIVO android 13
- 華為 鴻蒙系統(tǒng)2.0.1
vivo | 華為 |
---|---|
![]() |
![]() |
功能
- 動態(tài)申請拍照,讀,寫權(quán)限
- 自定義彈出框
- 調(diào)用系統(tǒng)相機(jī)拍照
3.1 調(diào)用系統(tǒng)相機(jī)申請拍照權(quán)限回調(diào)
3.2 拍照完成回調(diào) - 自動獲取sdk權(quán)限
4.1 訪問相冊完成回調(diào)
具體實(shí)現(xiàn)
.gradle
配置文件:
AndroidManifest
文件:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.harry.takepicture.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
filepaths.xml
文件:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<paths>
<external-path
name="camera_photos"
path="" />
</paths>
<external-path name="rc_external_path" path="."/>
</paths>
/**
* @author 拉莫帥
* @date 2023/4/01
* @address
* @Desc TakePicture 上傳頭像
*/
public class MainActivity extends BaseActivity implements View.OnClickListener {
public static String[] permission = {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA};
private CircleImg img;
private View view;
private String BaseUrl = "";
private Uri newUri;
private File outputImage;
private Uri cropImageUri;
private File fileCropUri;//裁剪的照片
private Uri imageUri;//拍照所得到的圖像的保存路徑
private static final int OUTPUT_X = 295;
private static final int OUTPUT_Y = 413;
private static final int CODE_GALLERY_REQUEST = 0xa0;
private static final int CODE_CAMERA_REQUEST = 0xa1;
private static final int CODE_RESULT_REQUEST = 0xa2;
private static final int REQUESTCODE_CUTTING = 0xa3;
private static final int CAMERA_PERMISSIONS_REQUEST_CODE = 0x03;
private static final int STORAGE_PERMISSIONS_REQUEST_CODE = 0x04;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStatusBg(1);
AppUtils.requestPermission(permission);
img = findViewById(R.id.userinfo_iv_head);
img.setOnClickListener(this);
}
protected View addContentLayout() {
view = getLayoutInflater().inflate(R.layout.activity_main, contentLayout, false);
return view;
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.userinfo_iv_head:
select();
break;
case R.id.rl_head_camera:
takePhoto();
AppUtils.dismiss();
break;
case R.id.rl_head_photo:
autoObtainStoragePermission();
AppUtils.dismiss();
break;
case R.id.rl_head_cancel:
AppUtils.dismiss();
break;
}
}
private void select() {
AppUtils.selectPhoto(MainActivity.this, R.layout.dialog_head, R.layout.activity_main, this);
}
/**
* 拍照
*
* @param
*/
private void takePhoto() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
ToastUtils.showShort(this, "您已經(jīng)拒絕過一次");
}
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE}, CAMERA_PERMISSIONS_REQUEST_CODE);
} else {//有權(quán)限直接調(diào)用系統(tǒng)相機(jī)拍照
if (AppUtils.hasSdcard()) {
outputImage = new File(Environment.getExternalStorageDirectory().getPath(), System.currentTimeMillis() + ".jpg");
//通過FileProvider創(chuàng)建一個content類型的Uri
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
imageUri = FileProvider.getUriForFile(this, "com.harry.takepicture.provider", outputImage);
} else {
imageUri = Uri.fromFile(outputImage);
}
PhotoUtils.takePicture(this, imageUri, CODE_CAMERA_REQUEST);
} else {
ToastUtils.showShort(this, "設(shè)備沒有SD卡!");
}
}
}
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
//調(diào)用系統(tǒng)相機(jī)申請拍照權(quán)限回調(diào)
case CAMERA_PERMISSIONS_REQUEST_CODE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (AppUtils.hasSdcard()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
imageUri = FileProvider.getUriForFile(MainActivity.this, "com.harry.takepicture.provider", outputImage);
} else {
imageUri = Uri.fromFile(outputImage);
}
PhotoUtils.takePicture(this, imageUri, CODE_CAMERA_REQUEST);
} else {
ToastUtils.showShort(this, "設(shè)備沒有SD卡!");
}
} else {
ToastUtils.showShort(this, "請?jiān)试S打開相機(jī)?。?);
}
break;
}
}
}
/**
* 自動獲取sdk權(quán)限
*/
private void autoObtainStoragePermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSIONS_REQUEST_CODE);
} else {
PhotoUtils.openPic(this, CODE_GALLERY_REQUEST);
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
fileCropUri = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".jpg");
switch (requestCode) {
//拍照完成回調(diào)
case CODE_CAMERA_REQUEST:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(this, "com.harry.takepicture.provider", outputImage);
cropPhoto(contentUri);
} else {
imageUri = Uri.fromFile(outputImage);
cropPhoto(imageUri);
}
//訪問相冊完成回調(diào)
case CODE_GALLERY_REQUEST:
if (AppUtils.hasSdcard()) {
cropImageUri = Uri.fromFile(fileCropUri);
if (data == null) {
return;
} else {
newUri = getUri(data);
}
PhotoUtils.cropImageUri(this, newUri, cropImageUri, 1, 1, OUTPUT_X, OUTPUT_Y, CODE_RESULT_REQUEST);
} else {
ToastUtils.showShort(this, "設(shè)備沒有SD卡!");
}
break;
case REQUESTCODE_CUTTING:
if (data != null) {
setPicToView(data);
}
break;
case CODE_RESULT_REQUEST:
String a = cropImageUri.getPath();
Log.e("tb", "a---" + a);
Bitmap bitmap = PhotoUtils.getBitmapFromUri(cropImageUri, this);
if (bitmap != null) {
File file = new File(a);
Log.e("tb", "file--------------------------" + file);
BaseUrl = Base64Utils.getImageStr(file);
Log.e("tb", "BaseUrl--------------------------" + BaseUrl);
showImages(bitmap, a);
}
break;
default:
}
}
}
private void setPicToView(Intent picdata) {
Bundle extras = picdata.getExtras();
if (extras != null) {
// 取得SDCard圖片路徑做顯示
Bitmap photo = extras.getParcelable("data");
String saveFile = FileUtil.saveFile(this, "crop", photo);
if (photo != null) {
File file = new File(saveFile);
Log.e("tb", "file--------------------------" + file);
BaseUrl = Base64Utils.getImageStr(file);
Log.e("tb", "BaseUrl--------------------------" + BaseUrl);
showImages(photo, saveFile);
}
}
}
/**
* 裁剪
*
* @param uri
*/
private void cropPhoto(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 300);
intent.putExtra("outputY", 300);
intent.putExtra("return-data", true);
Log.e("tag", "intent====" + intent);
startActivityForResult(intent, REQUESTCODE_CUTTING);
}
/**
* 展示
*
* @param bitmap
* @param urlpath
*/
private void showImages(Bitmap bitmap, String urlpath) {
Drawable drawable = new BitmapDrawable(null, bitmap);
Log.e("tag", "urlPath====" + urlpath);
img.setImageDrawable(drawable);
}
/**
* 解決手機(jī)上獲取圖片路徑為null的情況
*
* @param intent
* @return
*/
public Uri getUri(android.content.Intent intent) {
Uri uri = intent.getData();
String type = intent.getType();
if (uri.getScheme().equals("file") && (type.contains("image/"))) {
String path = uri.getEncodedPath();
if (path != null) {
path = Uri.decode(path);
ContentResolver cr = this.getContentResolver();
StringBuffer buff = new StringBuffer();
buff.append("(").append(MediaStore.Images.ImageColumns.DATA).append("=")
.append("'" + path + "'").append(")");
Cursor cur = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.ImageColumns._ID},
buff.toString(), null, null);
int index = 0;
for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) {
index = cur.getColumnIndex(MediaStore.Images.ImageColumns._ID);
// set _id value
index = cur.getInt(index);
}
if (index == 0) {
// do nothing
} else {
Uri uri_temp = Uri
.parse("content://media/external/images/media/"
+ index);
if (uri_temp != null) {
uri = uri_temp;
}
}
}
}
return uri;
}
}
總結(jié)
???????到這里就結(jié)束了??吹竭@里,關(guān)于上傳頭像的具體流程也已經(jīng)清楚,最主要的代碼也已經(jīng)給大家粘貼了過來。
???????完整版源碼下載地址:Android + <調(diào)用相機(jī)拍照 & 選擇相冊> + 數(shù)碼相機(jī)文章來源:http://www.zghlxwxcb.cn/news/detail-427426.html
???????感興趣的小伙伴們,大家趕快去測試一下吧。文章來源地址http://www.zghlxwxcb.cn/news/detail-427426.html
到了這里,關(guān)于Android 拍照以及相冊中選擇(適配高版本)————上傳頭像并裁剪(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!