社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
话说昨天的冰碴下得真心大,骑车回来的路上脸被打的生疼啊!清明小长假第一天,借这个时间把前两天想记录的一点内容补充上吧。
这篇文章主要记录调用系统相机或者从系统相册中选取照片然后上传头像,这是一个很平常的需求,网上的例子也很多,但是,(注意:前方高能预警!!!)我遇到了一个坑,选取的图片在预览框有时显示,有时不显示,这个怎么破!网上的例子找遍了都不行,后来经过反复测试,发现问题了,在跳转到更改头像页面的时候我先通过网络获取了一下之前的头像,然后展示出来。问题就出在这里,当之前没有头像的时候,这里先通过glide显示了一个error头像代替,然后各种选取头像在预览框就不显示了,但是如果之前有头像并成功显示了,那么现在再选取图片,预览框是可以显示的。这就很难搞了,不过最后还是找到了解决办法,这里先上一下其他的代码,不感兴趣的直接看文末的解决办法。
首先看一下布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize">
<include layout="@layout/custom_actionbar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:padding="10dp"
android:text="确定"
android:textColor="@color/btn_blue_normal"
android:layout_alignParentEnd="true"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:id="@+id/change_photo_tv_got" />
</RelativeLayout>
<ImageView
android:id="@+id/change_photo_iv_scan"
android:layout_width="match_parent"
android:layout_height="200dp"
android:src="@drawable/user_name"/>
<TextView
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider_list"/>
<Button
android:id="@+id/change_photo_camera"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="拍一张"
android:background="@drawable/btn_press_selector"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin"/>
<Button
android:id="@+id/change_photo_pic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="去相册"
android:background="@drawable/btn_press_selector"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin"/>
</LinearLayout>
然后,在oncreate()方法中加载之前的头像,我这里是提前获取了头像存在了application中的实体类currentUser中
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_change_photo);
ButterKnife.bind(this);
tvTitle.setText("更改头像");
tvGot.setVisibility(View.GONE);//先隐藏确定按钮,当有新头像输入时才显示
//先从application获取之前保存好的user实体类的photo路径,展示
Glide.with(this)
.load(TApplication.currentUser.getIvPhoto())
.into(ivPhoto);
}
下面是按钮的点击事件:
@OnClick({R.id.change_photo_camera, R.id.change_photo_pic, R.id.iv_title_back, R.id.change_photo_tv_got})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.change_photo_camera:
//调用系统相机,通过拍照获取图片
takePictureByCamera(this, GET_PICTURE_BY_CAMRA);
break;
case R.id.change_photo_pic:
//通过系统图库获取图片
takePictureByPic(this,GET_PICTURE_BY_PIC);
break;
case R.id.change_photo_tv_got:
//发起网络请求,将头像存入数据库
//成功后显示,并跳转界面
setPhoto(url, ivPhotoStr);
break;
}
}
通过相册获取图片:
private void takePictureByPic(Context context, int requestCode) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// 没有获得授权,申请授权
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
// 返回值:
//如果app之前请求过该权限,被用户拒绝, 这个方法就会返回true.
//如果用户之前拒绝权限的时候勾选了对话框中”Don’t ask again”的选项,那么这个方法会返回false.
//如果设备策略禁止应用拥有这条权限, 这个方法也返回false.
// 弹窗需要解释为何需要该权限,再次请求授权
Toast.makeText(this, "请授权!", Toast.LENGTH_LONG).show();
// 帮跳转到该应用的设置界面,让用户手动授权
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri1 = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri1);
startActivity(intent);
} else {
// 不需要解释为何需要该权限,直接请求授权
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STOORAGE_REQUEST_CODE);
}
} else {
// 已经获得授权,可以获取图片
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, requestCode);
}
}
通过相机获取图片的方法:
public void takePictureByCamera(Context context, int requestCode) {
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity) context,
new String[]{Manifest.permission.CAMERA},
TAKE_PHOTO_REQUEST_CODE);
} else {
Intent intent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE, null);
startActivityForResult(intent, requestCode);
}
}
然后是回调方法:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (requestCode == GET_PICTURE_BY_PIC) {//从图库选取的回调方法
Uri uri = data.getData();//content://media/external/images/media/72876
Bitmap bitmap1 = null;
if (uri != null) {
String path = getUriPath(uri);//上边获取的uri不是真实路径,通过此方法转换
try {
bitmap1 = BitmapFactory.decodeFile(path);
ivPhoto.setImageBitmap(bitmap1);//在预览框显示选择的图片,问题就在这里,有时候显示,有时候不显示
ivPhotoStr = bitmapToBase64(bitmap1);//往服务器上传照片,将照片转换成base64
tvGot.setVisibility(View.VISIBLE);
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (requestCode == GET_PICTURE_BY_CAMRA) {//通过相机选取的回调
Uri uri = data.getData();
if (uri == null) {
Bundle pBundle = data.getExtras(); //从intent对象中获取数据,
if (pBundle != null) {
Bitmap mBitmap = (Bitmap) pBundle.get("data"); //get bitmap
ivPhoto.setImageBitmap(mBitmap);//在预览框显示选择的图片,问题就在这里,有时候显示,有时候不显示
ivPhotoStr = bitmapToBase64(mBitmap);//往服务器上传照片,将照片转换成base64
tvGot.setVisibility(View.VISIBLE);
Log.i("", "onActivityResult: bitmap" + ivPhotoStr);
} else {
Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_LONG).show();
return;
}
} else {
ImageCompress.CompressOptions options = new ImageCompress.CompressOptions();
options.maxHeight = 200;
options.maxWidth = 200;
options.uri = data.getData();
ImageCompress imageCompress = new ImageCompress();
Bitmap mBitmap = imageCompress.compressFromUri(this, options);
if (mBitmap != null) {
ivPhoto.setImageBitmap(mBitmap);//在预览框显示选择的图片,问题就在这里,有时候显示,有时候不显示
ivPhotoStr = bitmapToBase64(mBitmap);//往服务器上传照片,将照片转换成base64
tvGot.setVisibility(View.VISIBLE);
Log.i("", "onActivityResult: ivPhotoStr" + ivPhotoStr);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
看一下getUriPath()方法:
private String getUriPath(Uri uri) {
String data = null;
if (null == uri)
return null;
final String scheme = uri.getScheme();
if (scheme == null)
data = uri.getPath();
else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
data = uri.getPath();
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
Cursor cursor = getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
if (null != cursor) {
if (cursor.moveToFirst()) {
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
if (index > -1) {
data = cursor.getString(index);
}
}
cursor.close();
}
}
return data;
}
然后把转换成base64 的方法也贴一下吧:
public static String bitmapToBase64(Bitmap bitmap) {
String result = null;
ByteArrayOutputStream baos = null;
try {
if (bitmap != null) {
baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
baos.flush();
baos.close();
byte[] bitmapBytes = baos.toByteArray();
result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (baos != null) {
baos.flush();
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
最后,将选择好的照片提交至服务器:
private void setPhoto(final String url, final String ivPhotoStr) {
new Thread(new Runnable() {
@Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new FormBody.Builder()
.add("_id", TApplication.currentUser.get_id())
.add("photo", ivPhotoStr)
.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String s = response.body().string();
Log.i("", "run: setPhoto" + s);
Message message = handler.obtainMessage();
message.what = 1;
message.obj = s;
handler.sendMessage(message);
} else {
Log.i("", "run: setPhoto" + response.body().string());
Message message = handler.obtainMessage();
message.what = 0;
handler.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
好了,代码很简单,但就是这个代码,出现了文章开头说的那个问题,经过反复测试,问题是解决了,如下:
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_change_photo);
ButterKnife.bind(this);
tvTitle.setText("更改头像");
tvGot.setVisibility(View.GONE);//先隐藏确定按钮,当有新头像输入时才显示
//这里是个大坑啊,写满了血泪史,
// 如果之前没有头像的话,这里就不用加载头像了,如果加载了会导致后边选择图片后不能预览,不在ivPhoto显示,具体原因不清楚
//在这里加入一个判断来显示之前的头像,如果之前有则显示
if (!TApplication.currentUser.getIvPhoto().equals(Path.KEY_MAIN_PHOTO_PATH)){
Glide.with(this)
.load(TApplication.currentUser.getIvPhoto())
.into(ivPhoto);
}else {
//之前没有头像,则这里不显示
}
}
问题是解决了,但是至于为什么,一直没有弄懂,如果有哪位大神明白,请留言告诉我,在此谢过了
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!