今天一天都在搞这个头像相关的android开发,不断的在网上查找资料,什么都不懂,然后就照抄。
就是一个什么问题呢,现在android打开一个相机不再简单的请求打开就行了,按照我今天查到的资料,就是说文件的URI不能在本APP之外被使用,所以需要进行一个转换,然后我随便找到了一种方法好像是直接获取到URI 的,然后拍摄成功了,但是晚上我不知道作了一些什么,突然就开始报错说SQLite有UNIQUE限制,我什么也不懂啊,也是一顿查,说是因为有一些SQLIte的列里面是不能允许有重复的东西的,所以我想说是不是我的图片的存储路径不能相同啊,我就该了一下,发现还是不幸,还是相同的错误,于是我寻求了另外一种方法。
通过FileProvider来临时提供一个URI供给本APP之外的应用使用。话不多说,下面直接上代码吧。其实刚开始这种方法我也不知道是怎么回事,说实话我现在也不知道这个是怎么回事,但是一顿摸索之后总算是弄出来了。
参考:https://blog.csdn.net/u011418943/article/details/77712662
1.选择是采用什么方式获得照片()
case R.id.camera:
Log.e("TAG","open camera to get a pic");
from_camera(FROM_CAMERA);
Log.e("TAG", "start camera");
break;
case R.id.photo:
Toast.makeText(MainActivity2.this, "choose a pic from photo", Toast.LENGTH_SHORT).show();
from_photo(FROM_PHOTO);
break;
2.开始处理了:
private void from_camera(int fromCamera) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//这里我在查看我保存头像的文件夹是不是已经存在了
//我选择的是保存在我手机的SD卡中,也就是ExternalStorage的,注意以下,因为后面会涉及到你的一些配置
if(!Profile_Dir.exists()){
Profile_Dir.mkdir();
}
//图片文件
File mTmpFile = new File(Profile_Dir, "/"+getName()+".png");
Uri uri ;
//检查这个版本的吧,就是这个东西搞得挺复杂的,不然不需要很麻烦的
if (Build.VERSION.SDK_INT >= 24){
//获得URI
uri = FileProvider.getUriForFile(MainActivity2.this,
"Advance", //这个可以随便取 ,但是要和到时候你的配置相对应(authorities)
mTmpFile);
}else{
uri = Uri.fromFile(mTmpFile);
}
Log.e("TAG", String.valueOf(uri));
//打开相机
intent.putExtra(MediaStore.EXTRA_OUTPUT,uri);
startActivityForResult(intent,fromCamera);
//处理
}
下面就把上面的相应配置说明:
首先是Manifest中注册provider(FileProvider):
<provider
android:name="androidx.core.content.FileProvider"
<--! 注意这个name不同的版本肯呢个有一些不同,我在这个上面也吃了一点苦,可以上网查现在是什么-->
android:authorities="Advance"
<--!这个authorites就是我上面说可以随便取的,我这里是是取的我自己的包名,记得要相同-->
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
<--! 其余的可以和我这个一样-->
android:resource="@xml/file_paths"/>相应地要在你的res文件家下面新建一个xml文件夹,然后在里面创建一个file_paths的文件
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="camera" path="APP头像"/>
</paths>
还记得我说我是把图片保存在我的SD卡里面吗?在这里就需要创建一个<external-path的标签,这个标签就是指明是Environment.getExternalStorage()这个路径,然后在里面的path写下你想要共享的SD卡中的文件夹,如果不写好像是共享所有的文件夹的,但是我觉得还是不要了,因为我不懈的话他报错了『呜呜呜总是报错』,那个name就没什么关系,只是一个虚拟的文件夹。
好了,就是这个我如果保存在SD卡是这个external-path标签,那么其他的相应的是:
<files-path /> = getFilesDir()
<cache-path /> = getCacheDir()
<external-path /> = Environment.getExternalStorageDirectory()
<external-files-path /> = Context#getExternalFilesDir(String) 或 Context.getExternalFilesDir(null)
<external-cache-path /> = Context.getExternalCacheDir()
<external-media-path /> = Context.getExternalMediaDirs()
https://www.cnblogs.com/kezhuang/p/8706988.html这是我从这个上面找到的,因为刚开始我杀也不懂嘛,然后使用的是这个上面的<files-path /> 标签,然后就报错了,哎呀我找不到那个是说什么了,大概就是说我的共享文件下面没有和我的图片文件下面的莫一个根目录相同的,这不很明显吗,我的图片在SD卡,然后file-path是getFileDir()的,根不久不是SD的,所以我该过来之后就好了!
3.之后就是拍摄之后的返回处理了:
else if (requestCode == FROM_CAMERA) {
//handle data from camera and set the background of your profile
//这个就是当时设置的那个文件的路径的,可以直接读取到从存储里面
File pic = new File(Profile_Dir,"/"+getName()+ ".png");
Log.e("TAG", "camera");
//这个是这个进行了一个裁减,我把代码贴在下面,是从网上找的,没有问题,我一试就可以
cropPhoto(Uri.fromFile(pic));
public void cropPhoto(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", 250);
intent.putExtra("outputY", 250);
intent.putExtra("return-data", true);
startActivityForResult(intent, CROP_PIC);
}
4.裁减之后把图片设置成头像,也要处理跳转回来的result
else if(requestCode==CROP_PIC){
//set the pic then
Bundle b=data.getExtras();
Bitmap head=b.getParcelable("data");
//设置头像
user_profile.setImageBitmap(head);
//这里是把这个头像保存起来,我也是保存在了SD卡中,替代了相加拍摄的那个照片
Bit2File(head);
}
public void Bit2File(Bitmap bitmap){
//照片路径(你要保存的)
File file=new File(Profile_Dir, "/"+getName()+".png");
try {
FileOutputStream out=new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
//上面是保存
//下面是发送一个广播告诉系统相册更新
Uri uri=Uri.fromFile(file);
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("TAG", "file_not found !");
} catch (IOException e) {
Log.e("TAG", "profile save fail!");
e.printStackTrace();
}
}
真的是这个搞了很久,什么也不懂嘛,就抄代码,然后很痛苦的是网上信息太多了,有些也已经不适合现在的版本了
我使用的是Vivo s10,有没有也在搞这个的伙伴啊。
android开发真的里面的东西太多了,我只能慢慢的走。
希望这个项目能取得一个好的结果。
对了,我把截图发一下:
完,好晚了。