[BugFix]个人中心头像问题修复

This commit is contained in:
wushaocheng
2023-04-14 17:51:53 +08:00
parent 486da1d028
commit 3e29eb1c32
8 changed files with 1010 additions and 574 deletions

View File

@@ -250,6 +250,8 @@ dependencies {
implementation 'com.github.mmin18:realtimeblurview:1.2.1'
implementation 'com.qiyukf.unicorn:unicorn:8.2.0'
implementation 'com.github.yalantis:ucrop:2.2.7'
}
repositories {

View File

@@ -1324,6 +1324,13 @@
</intent-filter>
</activity>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:configChanges="screenSize|orientation|keyboardHidden|mcc|mnc|locale|touchscreen|screenLayout|keyboard|navigation|fontScale|uiMode|smallestScreenSize|layoutDirection"
android:exported="false"
android:screenOrientation="portrait"
android:theme="@style/AppThemeUCrop" />
</application>
</manifest>

View File

@@ -0,0 +1,163 @@
package com.nnbc123.app.common.util;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Point;
import android.net.Uri;
import com.nnbc123.app.application.XChatApplication;
import com.nnbc123.core.utils.Logger;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by wushaocheng
* Date: 2022/11/17
*/
public class BitmapUtil {
private static final String TAG = "BitmapUtil";
public static Bitmap decodeSampledBitmapFromFileDescriptor(FileDescriptor fd, int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
BitmapFactory.decodeFileDescriptor(fd, null, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFileDescriptor(fd, null, options);
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
if (reqWidth == 0 || reqHeight == 0) {
return 1;
}
final int height = options.outHeight;
final int width = options.outWidth;
Logger.info(TAG, "origin, w= " + width + " h=" + height);
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
Logger.info(TAG, "sampleSize:" + inSampleSize);
return inSampleSize;
}
public static Bitmap setImgSize(Bitmap bm, float newWidth, float newHeight) {
if (bm == null) {
Logger.error(TAG, "bitmap is null.");
return null;
}
// 获得图片的宽高.
int width = bm.getWidth();
int height = bm.getHeight();
// 计算缩放比例.
float scaleWidth = newWidth / width;
float scaleHeight = newHeight / height;
// 取得想要缩放的matrix参数.
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的图片.
return Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
}
public static Point getImageSize(String imgPath) {
Point point = new Point();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imgPath, options);
point.x = options.outWidth;
point.y = options.outHeight;
return point;
}
/**
* 获取sd卡上的bitmap的大小
* 不加载进内存
*/
public static long getSdBitmapSize(Uri imageUri) {
return getSdBitmapSize(imageUri, null);
}
/**
* androidQ 以上使用path拿不到图片信息换成Uri
*
* @param imageUri
* @param inPreferredConfig
* @return
*/
private static long getSdBitmapSize(Uri imageUri, Bitmap.Config inPreferredConfig) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
if (inPreferredConfig != null) {
options.inPreferredConfig = inPreferredConfig;
}
try {
InputStream stream = XChatApplication.gContext.getContentResolver().openInputStream(imageUri);
BitmapFactory.decodeStream(stream, null, options);
switch (options.inPreferredConfig) {
case ALPHA_8:
return options.outWidth * options.outHeight;
case RGB_565:
case ARGB_4444:
return options.outWidth * options.outHeight * 2;
case RGBA_F16:
return options.outWidth * options.outHeight * 8;
case ARGB_8888:
default:
return options.outWidth * options.outHeight * 4;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return 0;
}
}
public static Bitmap convertBitmap(Bitmap bitmap) {
if (bitmap == null) {
return null;
}
float density = XChatApplication.gContext.getResources().getDisplayMetrics().density;
return BitmapUtil.setImgSize(bitmap, bitmap.getWidth() * density / 3.0f, bitmap.getHeight() * density / 3.0f);
}
public static int caculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
if (width > reqWidth || height > reqHeight) {
int widthRadio = Math.round(width * 1.0f / reqWidth);
int heightRadio = Math.round(height * 1.0f / reqHeight);
inSampleSize = Math.max(widthRadio, heightRadio);
}
return inSampleSize;
}
public static byte[] inputStream2ByteArr(InputStream inputStream) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len = 0;
while ( (len = inputStream.read(buff)) != -1) {
outputStream.write(buff, 0, len);
}
inputStream.close();
outputStream.close();
return outputStream.toByteArray();
}
}

View File

@@ -1,435 +1,563 @@
package com.nnbc123.app.ui.user;
package com.nnbc123.app.ui.user
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.fourmob.datetimepicker.date.DatePickerDialog;
import com.nnbc123.app.takephoto.model.TResult;
import com.netease.nim.uikit.StatusBarUtil;
import com.netease.nim.uikit.common.util.sys.TimeUtil;
import com.sleepbot.datetimepicker.time.RadialPickerLayout;
import com.sleepbot.datetimepicker.time.TimePickerDialog;
import com.trello.rxlifecycle3.android.ActivityEvent;
import com.nnbc123.app.ErbanTakePhotoActivity;
import com.nnbc123.app.R;
import com.nnbc123.app.UIHelper;
import com.nnbc123.app.audio.RecordingVoiceActivity;
import com.nnbc123.app.base.BaseActivity;
import com.nnbc123.app.common.permission.PermissionActivity;
import com.nnbc123.app.ui.login.ModifyInfoActivity;
import com.nnbc123.app.ui.utils.ImageLoadUtils;
import com.nnbc123.app.ui.widget.ButtonItem;
import com.nnbc123.app.utils.RegexUtil;
import com.nnbc123.core.auth.AuthModel;
import com.nnbc123.core.file.FileModel;
import com.nnbc123.core.user.UserModel;
import com.nnbc123.core.user.bean.UserInfo;
import com.nnbc123.core.user.bean.UserPhoto;
import com.nnbc123.library.utils.TimeUtils;
import com.nnbc123.library.utils.log.MLog;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
import io.reactivex.Completable;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.Disposable;
import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.text.TextUtils
import android.view.View
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.fourmob.datetimepicker.date.DatePickerDialog
import com.hjq.toast.ToastUtils
import com.netease.nim.uikit.StatusBarUtil
import com.netease.nim.uikit.common.util.sys.TimeUtil
import com.nnbc123.app.R
import com.nnbc123.app.UIHelper
import com.nnbc123.app.application.XChatApplication
import com.nnbc123.app.audio.RecordingVoiceActivity
import com.nnbc123.app.base.BaseViewBindingActivity
import com.nnbc123.app.common.util.BitmapUtil
import com.nnbc123.app.databinding.ActivityUserInfoModifyBinding
import com.nnbc123.app.ui.login.ModifyInfoActivity
import com.nnbc123.app.ui.user.UserPhotoAdapter.ImageClickListener
import com.nnbc123.app.ui.utils.ImageLoadUtils
import com.nnbc123.app.ui.widget.dialog.CommonTipDialog
import com.nnbc123.app.utils.RegexUtil
import com.nnbc123.core.auth.AuthModel
import com.nnbc123.core.file.FileModel
import com.nnbc123.core.user.UserModel
import com.nnbc123.core.user.bean.UserInfo
import com.nnbc123.core.user.bean.UserPhoto
import com.nnbc123.core.utils.Logger
import com.nnbc123.library.common.file.FileHelper
import com.nnbc123.library.common.photo.PhotoProviderNew
import com.nnbc123.library.common.util.PhotoCompressCallback
import com.nnbc123.library.common.util.PhotoCompressUtil
import com.nnbc123.library.easypermisssion.EasyPermissions
import com.nnbc123.library.utils.TimeUtils
import com.sleepbot.datetimepicker.time.RadialPickerLayout
import com.sleepbot.datetimepicker.time.TimePickerDialog
import com.trello.rxlifecycle3.android.ActivityEvent
import com.yalantis.ucrop.UCrop
import io.reactivex.Completable
import io.reactivex.SingleObserver
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.Job
import java.io.FileNotFoundException
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
/**
* @author zhouxiangfeng
*/
public class UserInfoModifyActivity extends BaseActivity
implements View.OnClickListener, TimePickerDialog.OnTimeSetListener,
DatePickerDialog.OnDateSetListener, UserPhotoAdapter.ImageClickListener,
ErbanTakePhotoActivity.TakePhotoCallBack {
class UserInfoModifyActivity : BaseViewBindingActivity<ActivityUserInfoModifyBinding>(),
View.OnClickListener,
TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener, ImageClickListener,
EasyPermissions.PermissionCallbacks {
private var datePickerDialog: DatePickerDialog? = null
private var mUserInfo: UserInfo? = null
private var userId: Long = 0
private var showAvatarAuditing = false
private static final String TAG = "UserInfoModifyActivity";
private var mUri: Uri? = null
private var mJob: Job? = null
private ImageView civAvatar;
private DatePickerDialog datePickerDialog;
private TextView tvBirth;
private TextView tvNick;
private TextView tvDesc;
private UserInfo mUserInfo;
private long userId;
private TextView tvNoVoice;
private String audioFileUrl;
private RecyclerView photosRecyclerView;
private var isAvatar = false
private boolean showAvatarAuditing;
private ImageView ivAvatarAuditiong;
private var audioFileUrl: String? = null
companion object {
private const val TAG = "UserInfoModifyActivity"
private const val PERMISSION_CODE_STORAGE = 12
private const val REQUEST_CODE_STORAGE = 42
private const val REQUEST_CODE_OPEN_PHOTO_PROVIDER = 111 // 从相册中选择
private const val MAX_BITMAP_SIZE = 100 * 1024 * 1024 // 剪切的图片最大为100 MB
private const val MIN_HEAD_PHOTO_SIZE = 20 * 1024 // 剪切的图片最小为20kb
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_info_modify);
initWhiteTitleBar(getString(R.string.label_title_modify_info));
findViews();
init();
onSetListener();
userId = getIntent().getLongExtra("userId", 0);
UserModel.get().getUserInfo(userId).subscribe(userInfoUpdateObserver);
//头像压缩后的大小不能超过大小 200KB
private const val IMAGE_MOST_COMPRESS_SIZE = 200
}
@Override
public void click(int position, UserPhoto userPhoto, boolean isOwner) {
if (userPhoto != null) {
UserModifyPhotosActivity.startForResult(UserInfoModifyActivity.this, userId, Method.PHOTO);
}
override fun init() {
initWhiteTitleBar(getString(R.string.label_title_modify_info))
findViews()
initView()
userId = intent.getLongExtra("userId", 0)
}
private void onSetListener() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
UserModel.get().getUserInfo(userId).subscribe(userInfoUpdateObserver)
PhotoCompressUtil.clearCompressCache()
}
private void initData(UserInfo userInfo) {
override fun click(position: Int, userPhoto: UserPhoto, isOwner: Boolean) {
UserModifyPhotosActivity.startForResult(
this@UserInfoModifyActivity,
userId,
Method.PHOTO
)
}
private fun initData(userInfo: UserInfo?) {
if (null != userInfo) {
audioFileUrl = userInfo.getUserVoice();
ImageLoadUtils.loadAvatar(this, !TextUtils.isEmpty(userInfo.getNewAvatar()) ? userInfo.getNewAvatar() : userInfo.getAvatar(), civAvatar);
ivAvatarAuditiong.setVisibility(userInfo.isReview() ? View.VISIBLE : View.GONE);
String birth = TimeUtil.getDateTimeString(userInfo.getBirth(), "yyyy-MM-dd");
tvBirth.setText(birth);
tvNick.setText(RegexUtil.getPrintableString(userInfo.getNick()));
setTvDesc(userInfo.getUserDesc());
boolean hasVoice = userInfo.getVoiceDura() > 0;
tvNoVoice.setVisibility(hasVoice ? View.GONE : View.VISIBLE);
UserPhotoAdapter adapter = new UserPhotoAdapter(userInfo.getPrivatePhoto(), 1, userInfo.getUid());
adapter.setSmall(true);
adapter.setImageClickListener(this);
photosRecyclerView.setAdapter(adapter);
if (userInfo.getPrivatePhoto() != null && userInfo.getPrivatePhoto().size() > 0) {
photosRecyclerView.setVisibility(View.VISIBLE);
audioFileUrl = userInfo.userVoice
ImageLoadUtils.loadAvatar(
this,
if (!TextUtils.isEmpty(userInfo.newAvatar)) userInfo.newAvatar else userInfo.avatar,
binding.civAvatar
)
binding.ivAvatarAuditing.visibility =
if (userInfo.isReview) View.VISIBLE else View.GONE
val birth = TimeUtil.getDateTimeString(userInfo.birth, "yyyy-MM-dd")
binding.tvBirth.text = birth
binding.tvNick.text = RegexUtil.getPrintableString(userInfo.nick)
setTvDesc(userInfo.userDesc)
val hasVoice = userInfo.voiceDura > 0
binding.tvNoVoice.visibility = if (hasVoice) View.GONE else View.VISIBLE
val adapter = UserPhotoAdapter(userInfo.privatePhoto, 1, userInfo.uid)
adapter.setSmall(true)
adapter.setImageClickListener(this)
binding.rvPhotos.adapter = adapter
if (userInfo.privatePhoto != null && userInfo.privatePhoto.size > 0) {
binding.rvPhotos.visibility = View.VISIBLE
} else {
photosRecyclerView.setVisibility(View.GONE);
binding.rvPhotos.visibility = View.GONE
}
}
}
private void findViews() {
civAvatar = findViewById(R.id.civ_avatar);
tvBirth = findViewById(R.id.tv_birth);
tvNick = findViewById(R.id.tv_nick);
tvDesc = findViewById(R.id.tv_desc);
tvNoVoice = findViewById(R.id.tv_no_voice);
photosRecyclerView = findViewById(R.id.rv_photos);
findViewById(R.id.layout_avatar).setOnClickListener(this);
tvBirth.setOnClickListener(this);
findViewById(R.id.tv_nick).setOnClickListener(this);
findViewById(R.id.layout_desc).setOnClickListener(this);
findViewById(R.id.iv_desc_more).setOnClickListener(this);
findViewById(R.id.layout_photos).setOnClickListener(this);
findViewById(R.id.rl_audio_record).setOnClickListener(this);
LinearLayoutManager mLayoutManager =
new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true);
photosRecyclerView.setLayoutManager(mLayoutManager);
ivAvatarAuditiong = findViewById(R.id.iv_avatar_auditing);
private fun findViews() {
binding.layoutAvatar.setOnClickListener(this)
binding.tvBirth.setOnClickListener(this)
binding.tvNick.setOnClickListener(this)
binding.layoutDesc.setOnClickListener(this)
binding.ivDescMore.setOnClickListener(this)
binding.layoutPhotos.setOnClickListener(this)
binding.rlAudioRecord.setOnClickListener(this)
val mLayoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true)
binding.rvPhotos.layoutManager = mLayoutManager
}
private void setTvDesc(String desc) {
tvDesc.setText(TextUtils.isEmpty(desc) ? getString(R.string.label_hint_desc_setting) : desc);
private fun setTvDesc(desc: String?) {
binding.tvDesc.text =
if (TextUtils.isEmpty(desc)) getString(R.string.label_hint_desc_setting) else desc
}
private void init() {
Calendar calendar = Calendar.getInstance();
datePickerDialog = DatePickerDialog.newInstance(this, calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), true);
private fun initView() {
val calendar = Calendar.getInstance()
datePickerDialog = DatePickerDialog.newInstance(
this, calendar[Calendar.YEAR],
calendar[Calendar.MONTH], calendar[Calendar.DAY_OF_MONTH], true
)
}
@Override
public void onDateSet(DatePickerDialog datePickerDialog, int year, int month, int day) {
String monthStr;
if ((month + 1) < 10) {
monthStr = "0" + (month + 1);
override fun onDateSet(datePickerDialog: DatePickerDialog, year: Int, month: Int, day: Int) {
val monthStr: String = if (month + 1 < 10) {
"0" + (month + 1)
} else {
monthStr = String.valueOf(month + 1);
(month + 1).toString()
}
String dayStr;
if ((day) < 10) {
dayStr = "0" + (day);
val dayStr: String = if (day < 10) {
"0$day"
} else {
dayStr = String.valueOf(day);
day.toString()
}
String birth = String.valueOf(year) + "-" + monthStr + "-" + dayStr;
UserInfo user = new UserInfo();
user.setUid(AuthModel.get().getCurrentUid());
user.setBirthStr(birth);
UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver);
val birth = "$year-$monthStr-$dayStr"
val user = UserInfo()
user.uid = AuthModel.get().currentUid
user.birthStr = birth
UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver)
}
override fun onTimeSet(view: RadialPickerLayout, hourOfDay: Int, minute: Int) {}
interface Method {
companion object {
/**
* 录音
*/
const val AUDIO = 2
@Override
public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute) {
/**
* 昵称
*/
const val NICK = 3
/**
* 个人介绍
*/
const val DESC = 4
/**
* 拍照
*/
const val PHOTO = 5
}
}
public interface Method {
/**
* 录音
*/
int AUDIO = 2;
/**
* 昵称
*/
int NICK = 3;
/**
* 个人介绍
*/
int DESC = 4;
int PHOTO = 5;
}
PermissionActivity.CheckPermListener checkPermissionListener = new PermissionActivity.CheckPermListener() {
@Override
public void superPermission() {
takePhoto();
}
};
private void takePhoto() {
ErbanTakePhotoActivity.startToTakePhoto(this, this);
}
private void checkPermissionAndStartCamera() {
//低版本授权检查
checkPermission(checkPermissionListener, R.string.ask_camera, Manifest.permission.CAMERA);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) {
MLog.info(this, "return is not ok,resultCode=%d", resultCode);
return;
}
if (requestCode == Method.NICK) {
getDialogManager().showProgressDialog(UserInfoModifyActivity.this, "请稍后");
String stringExtra = data.getStringExtra(ModifyInfoActivity.CONTENT_NICK);
tvNick.setText(stringExtra);
UserInfo user = new UserInfo();
user.setUid(AuthModel.get().getCurrentUid());
user.setNick(stringExtra);
UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver);
}
if (requestCode == Method.DESC) {
getDialogManager().showProgressDialog(UserInfoModifyActivity.this, "请稍后");
String stringExtra = data.getStringExtra(ModifyInfoActivity.CONTENT);
setTvDesc(stringExtra);
UserInfo user = new UserInfo();
user.setUid(AuthModel.get().getCurrentUid());
user.setUserDesc(stringExtra);
UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver);
}
// 刷新声音资源
if (requestCode == Method.AUDIO) {
// 传给上个页面
setResult(RESULT_OK, data);
// 获取数据并刷新显示
audioFileUrl = data.getStringExtra(RecordingVoiceActivity.AUDIO_FILE);
int audioDura = data.getIntExtra(RecordingVoiceActivity.AUDIO_DURA, 0);
// 更新用户信息
UserInfo user = new UserInfo();
user.setUid(AuthModel.get().getCurrentUid());
user.setUserVoice(audioFileUrl);
user.setVoiceDura(audioDura);
UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver);
}
if (requestCode == Method.PHOTO && data != null) {
boolean isChanged = data.getBooleanExtra(UserModifyPhotosActivity.FLAG_CHANGE, false);
if (isChanged)
UserModel.get().getUserInfo(userId).subscribe(userInfoUpdateObserver);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.layout_avatar:
if (mUserInfo != null && mUserInfo.isReview()) {
toast("头像正在审核中");
return;
override fun onClick(v: View) {
when (v.id) {
R.id.layout_avatar -> {
if (mUserInfo != null && mUserInfo?.isReview == true) {
toast("头像正在审核中")
return
}
ButtonItem buttonItem = new ButtonItem("拍照上传", this::checkPermissionAndStartCamera);
ButtonItem buttonItem1 = new ButtonItem("本地相册", () -> {
ErbanTakePhotoActivity.startToSelectPhoto(this, this);
});
List<ButtonItem> buttonItems = new ArrayList<>();
buttonItems.add(buttonItem);
buttonItems.add(buttonItem1);
getDialogManager().showCommonPopupDialog(buttonItems, "取消", false);
isAvatar = true;
break;
case R.id.tv_birth:
checkStoragePermission()
isAvatar = true
}
R.id.tv_birth -> {
if (mUserInfo != null) {
int year = TimeUtils.getYear(mUserInfo.getBirth());
int month = TimeUtils.getMonth(mUserInfo.getBirth());
int day = TimeUtils.getDayOfMonth(mUserInfo.getBirth());
datePickerDialog = DatePickerDialog.newInstance(this, year, (month - 1), day, true);
val year = TimeUtils.getYear(
mUserInfo?.birth ?: 0L
)
val month = TimeUtils.getMonth(
mUserInfo?.birth ?: 0L
)
val day = TimeUtils.getDayOfMonth(
mUserInfo?.birth ?: 0L
)
datePickerDialog =
DatePickerDialog.newInstance(this, year, month - 1, day, true)
}
Calendar calendar = Calendar.getInstance();
val calendar = Calendar.getInstance()
datePickerDialog?.apply {
setVibrate(true)
setYearRange(1945, calendar[Calendar.YEAR] - 18)
show(supportFragmentManager, "DATEPICKER_TAG_1")
}
}
R.id.tv_nick -> UIHelper.showModifyInfoAct(
this@UserInfoModifyActivity,
Method.NICK,
ModifyInfoActivity.NICK_MODIFY
)
R.id.iv_desc_more, R.id.layout_desc -> UIHelper.showModifyInfoAct(
this@UserInfoModifyActivity,
Method.DESC,
ModifyInfoActivity.CONTENT_MODIFY
)
R.id.rl_audio_record -> checkPermission(
{
datePickerDialog.setVibrate(true);
datePickerDialog.setYearRange(1945, calendar.get(Calendar.YEAR) - 18);
datePickerDialog.show(getSupportFragmentManager(), "DATEPICKER_TAG_1");
break;
case R.id.tv_nick:
UIHelper.showModifyInfoAct(UserInfoModifyActivity.this, Method.NICK, ModifyInfoActivity.NICK_MODIFY);
break;
case R.id.iv_desc_more:
case R.id.layout_desc:
UIHelper.showModifyInfoAct(UserInfoModifyActivity.this, Method.DESC, ModifyInfoActivity.CONTENT_MODIFY);
break;
case R.id.rl_audio_record:
checkPermission(() -> {
// 点击跳转到我的声音页面
UIHelper.showMyVoiceAct(UserInfoModifyActivity.this, Method.AUDIO, "编辑资料");
isAvatar = false;
}, R.string.ask_again,
Manifest.permission.RECORD_AUDIO);
break;
case R.id.layout_photos:
UserModifyPhotosActivity.startForResult(UserInfoModifyActivity.this, userId, Method.PHOTO);
break;
default:
// 点击跳转到我的声音页面
UIHelper.showMyVoiceAct(this@UserInfoModifyActivity, Method.AUDIO, "编辑资料")
isAvatar = false
}, R.string.ask_again,
Manifest.permission.RECORD_AUDIO
)
R.id.layout_photos -> UserModifyPhotosActivity.startForResult(
this@UserInfoModifyActivity,
userId,
Method.PHOTO
)
else -> {}
}
}
private boolean isAvatar = false;
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<out String>, grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
}
public void onUpload(String url) {
if (isAvatar) {
UserInfo user = new UserInfo();
user.setUid(AuthModel.get().getCurrentUid());
user.setAvatar(url);
showAvatarAuditing = true;
UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver);
override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
if (requestCode == PERMISSION_CODE_STORAGE) {
checkStoragePermission()
}
}
public void onUploadFail() {
toast("上传失败");
getDialogManager().dismissDialog();
}
@SuppressLint("CheckResult")
@Override
public void takeSuccess(TResult result) {
getDialogManager().showProgressDialog(UserInfoModifyActivity.this, "请稍后");
FileModel.get()
.uploadFile(result.getImage().getCompressPath())
.compose(bindToLifecycle())
.subscribe((url, throwable) -> {
if (throwable != null) {
onUploadFail();
} else {
onUpload(url);
override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
if (requestCode == PERMISSION_CODE_STORAGE) {
val requestTip = "为了能正常加载您本地的文件内容,请前往应用权限设置界面打开存储空间权限。"
val mPrivacyDialog = CommonTipDialog(context)
mPrivacyDialog.setTipMsg(requestTip)
mPrivacyDialog.setOkText("去设置")
mPrivacyDialog.setOnActionListener(
object : CommonTipDialog.OnActionListener {
override fun onOk() {
//同意跳到应用详情页面
val packageUri =
Uri.parse("package:${packageName}")
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
packageUri
)
startActivityForResult(
intent, REQUEST_CODE_STORAGE
)
}
});
override fun onCancel() {
super.onCancel()
//取消跳到应用详情页面
ToastUtils.show("您已拒绝提供存储空间权限,将无法正常加载您本地的文件内容。")
}
}
)
mPrivacyDialog.show()
}
}
@Override
public void takeFail(TResult result, String msg) {
toast(msg);
private fun checkStoragePermission() {
if (!EasyPermissions.hasPermissions(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
) {
EasyPermissions.requestPermissions(
this,
"请您再次考虑授予存储空间权限,否则将无法正常加载您本地的文件内容。",
PERMISSION_CODE_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
} else {
mUri = Uri.parse("file://${FileHelper.getRootCacheDir()?.path}/${getNowTime()}.jpg")
PhotoProviderNew.photoProvider(
this,
resultCode = REQUEST_CODE_OPEN_PHOTO_PROVIDER
)
}
}
@Override
public void takeCancel() {
private fun getNowTime(): String {
val date = Date(System.currentTimeMillis())
val dateFormat = SimpleDateFormat("MMddHHmmssSS")
return dateFormat.format(date)
}
@Override
protected void onPause() {
super.onPause();
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_STORAGE) {
checkStoragePermission()
} else if (resultCode == RESULT_OK) {
when (requestCode) {
Method.NICK -> {
data?.let {
dialogManager.showProgressDialog(
this@UserInfoModifyActivity,
"请稍后"
)
val stringExtra = it.getStringExtra(ModifyInfoActivity.CONTENT_NICK)
binding.tvNick.text = stringExtra
val user = UserInfo()
user.uid = AuthModel.get().currentUid
user.nick = stringExtra
UserModel.get().requestUpdateUserInfo(user)
.subscribe(userInfoUpdateObserver)
}
}
Method.DESC -> {
data?.let {
dialogManager.showProgressDialog(
this@UserInfoModifyActivity,
"请稍后"
)
val stringExtra = it.getStringExtra(ModifyInfoActivity.CONTENT)
setTvDesc(stringExtra)
val user = UserInfo()
user.uid = AuthModel.get().currentUid
user.userDesc = stringExtra
UserModel.get().requestUpdateUserInfo(user)
.subscribe(userInfoUpdateObserver)
}
}
Method.AUDIO -> {
data?.let {
// 传给上个页面
setResult(RESULT_OK, it)
// 获取数据并刷新显示
audioFileUrl = it.getStringExtra(RecordingVoiceActivity.AUDIO_FILE) ?: ""
val audioDura = it.getIntExtra(RecordingVoiceActivity.AUDIO_DURA, 0)
// 更新用户信息
val user = UserInfo()
user.uid = AuthModel.get().currentUid
user.userVoice = audioFileUrl
user.voiceDura = audioDura
UserModel.get().requestUpdateUserInfo(user)
.subscribe(userInfoUpdateObserver)
}
}
Method.PHOTO -> {
data?.let {
val isChanged =
it.getBooleanExtra(UserModifyPhotosActivity.FLAG_CHANGE, false)
if (isChanged) UserModel.get().getUserInfo(userId)
.subscribe(userInfoUpdateObserver)
}
}
REQUEST_CODE_OPEN_PHOTO_PROVIDER -> data?.let {
val photos = PhotoProviderNew.getResultPhotoList(it) ?: return
if (photos.isNotEmpty()) {
val photo = photos[0]
crop(photo.uri, photo.size, mUri)
}
}
UCrop.REQUEST_CROP -> mUri?.path?.let {
try {
mJob?.cancel()
mJob = PhotoCompressUtil.compress(
this,
it,
PhotoCompressUtil.getCompressCachePath(),
object : PhotoCompressCallback {
@SuppressLint("CheckResult")
override fun onSuccess(compressedImg: String) {
dialogManager.showProgressDialog(
this@UserInfoModifyActivity,
"请稍后"
)
FileModel.get()
.uploadFile(compressedImg)
.compose(bindToLifecycle())
.subscribe { url: String?, throwable: Throwable? ->
if (throwable != null) {
onUploadFail()
} else {
onUpload(url)
}
}
}
override fun onFail(e: Throwable) {
toast(e.message)
}
},
mostCompressSize = IMAGE_MOST_COMPRESS_SIZE
)
} catch (e: FileNotFoundException) {
Logger.error(TAG, e.message)
}
}
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
/**
* 第三方图片裁剪框架Ucrop
*/
private fun crop(sourceUri: Uri?, sourceSize: Long, destinationUri: Uri?) {
if (sourceUri == null || destinationUri == null) {
return
} //防止too large导致oom大于100m不处理内存大小
if (BitmapUtil.getSdBitmapSize(sourceUri) >= MAX_BITMAP_SIZE) {
toast(R.string.text_bitmap_too_large)
return
}
if (sourceSize > 0) {
//不能上传图片的最小文件大小
Logger.debug(TAG, "sourceSize: $sourceSize")
if (sourceSize < MIN_HEAD_PHOTO_SIZE) {
toast(R.string.text_bitmap_too_small)
return
}
}
val options = UCrop.Options().apply {
setCompressionQuality(100)
setShowCropGrid(false)
setToolbarColor(
ContextCompat.getColor(
XChatApplication.gContext,
android.R.color.black
)
)
setStatusBarColor(
ContextCompat.getColor(
XChatApplication.gContext,
android.R.color.black
)
)
setHideBottomControls(true)
setCompressionFormat(Bitmap.CompressFormat.JPEG)
setToolbarCancelDrawable(R.drawable.user_ucrop_ic_closs)
setToolbarCropDrawable(R.drawable.user_ucrop_ic_sure)
setToolbarWidgetColor(
ContextCompat.getColor(
XChatApplication.gContext,
R.color.color_white
)
)
}
UCrop.of(sourceUri, destinationUri).withOptions(options).withAspectRatio(1f, 1f)
.withMaxResultSize(800, 800).start(this)
}
private fun onUpload(url: String?) {
if (isAvatar) {
val user = UserInfo()
user.uid = AuthModel.get().currentUid
user.avatar = url
showAvatarAuditing = true
UserModel.get().requestUpdateUserInfo(user).subscribe(userInfoUpdateObserver)
}
}
private fun onUploadFail() {
toast("上传失败")
dialogManager.dismissDialog()
}
/**
* 观察用户信息
*/
private SingleObserver<UserInfo> userInfoUpdateObserver = new SingleObserver<UserInfo>() {
@Override
public void onSubscribe(Disposable d) {
mCompositeDisposable.add(d);
}
@Override
public void onSuccess(UserInfo info) {
if (info.getUid() == userId) {
mUserInfo = info;
initData(mUserInfo);
private val userInfoUpdateObserver: SingleObserver<UserInfo> =
object : SingleObserver<UserInfo> {
override fun onSubscribe(d: Disposable) {
mCompositeDisposable.add(d)
}
getDialogManager().dismissDialog();
if (showAvatarAuditing) {
showAvatarAuditing = false;
showAvatarAuditingDialog();
override fun onSuccess(info: UserInfo) {
if (info.uid == userId) {
mUserInfo = info
initData(mUserInfo)
}
dialogManager.dismissDialog()
if (showAvatarAuditing) {
showAvatarAuditing = false
showAvatarAuditingDialog()
}
}
override fun onError(e: Throwable) {
dialogManager.dismissDialog()
toast(e.message)
}
}
@Override
public void onError(Throwable e) {
getDialogManager().dismissDialog();
toast(e.getMessage());
}
};
@Override
protected boolean needSteepStateBar() {
return true;
}
@Override
protected void setStatusBar() {
StatusBarUtil.transparencyBar(this);
StatusBarUtil.StatusBarLightMode(this);
}
private void showAvatarAuditingDialog() {
toast(R.string.avatar_auditing);
private fun showAvatarAuditingDialog() {
toast(R.string.avatar_auditing)
//延迟3秒重新获取用户信息更新状态
ivAvatarAuditiong.setVisibility(View.VISIBLE);
binding.ivAvatarAuditing.visibility = View.VISIBLE
Completable.timer(3000, TimeUnit.MILLISECONDS)
.compose(bindUntilEvent(ActivityEvent.STOP))
.doOnComplete(() -> {
UserModel.get().updateCurrentUserInfo().subscribe(userInfoUpdateObserver);
}).doOnError(throwable -> {
throwable.printStackTrace();
}).subscribe();
.compose(bindUntilEvent<Any>(ActivityEvent.STOP))
.doOnComplete {
UserModel.get().updateCurrentUserInfo().subscribe(userInfoUpdateObserver)
}
.doOnError { throwable: Throwable -> throwable.printStackTrace() }.subscribe()
}
}
override fun needSteepStateBar(): Boolean {
return true
}
override fun setStatusBar() {
StatusBarUtil.transparencyBar(this)
StatusBarUtil.StatusBarLightMode(this)
}
override fun onDestroy() {
super.onDestroy()
dialogManager.dismissDialog()
mJob?.cancel()
}
}

View File

@@ -1,261 +1,393 @@
package com.nnbc123.app.ui.user;
package com.nnbc123.app.ui.user
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.GridView;
import com.nnbc123.app.takephoto.app.TakePhotoActivity;
import com.nnbc123.app.takephoto.compress.CompressConfig;
import com.nnbc123.app.takephoto.model.TResult;
import com.netease.nim.uikit.StatusBarUtil;
import com.orhanobut.logger.Logger;
import com.trello.rxlifecycle3.android.ActivityEvent;
import com.nnbc123.app.R;
import com.nnbc123.app.base.TitleBar;
import com.nnbc123.app.common.permission.PermissionActivity;
import com.nnbc123.app.ui.widget.ButtonItem;
import com.nnbc123.core.file.FileModel;
import com.nnbc123.core.user.UserModel;
import com.nnbc123.core.user.bean.UserInfo;
import com.nnbc123.core.user.bean.UserPhoto;
import com.nnbc123.core.utils.net.BeanObserver;
import com.nnbc123.library.utils.file.JXFileUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.view.View
import android.widget.GridView
import androidx.core.content.ContextCompat
import com.hjq.toast.ToastUtils
import com.netease.nim.uikit.StatusBarUtil
import com.nnbc123.app.R
import com.nnbc123.app.application.XChatApplication
import com.nnbc123.app.base.TitleBar
import com.nnbc123.app.common.util.BitmapUtil
import com.nnbc123.app.takephoto.app.TakePhotoActivity
import com.nnbc123.app.ui.user.UserModifyPhotosAdapter.PhotoItemClickListener
import com.nnbc123.app.ui.widget.dialog.CommonTipDialog
import com.nnbc123.core.file.FileModel
import com.nnbc123.core.user.UserModel
import com.nnbc123.core.user.bean.UserInfo
import com.nnbc123.core.user.bean.UserPhoto
import com.nnbc123.core.utils.net.BeanObserver
import com.nnbc123.library.common.file.FileHelper
import com.nnbc123.library.common.photo.PhotoProviderNew
import com.nnbc123.library.common.util.PhotoCompressCallback
import com.nnbc123.library.common.util.PhotoCompressUtil
import com.nnbc123.library.easypermisssion.EasyPermissions
import com.orhanobut.logger.Logger
import com.trello.rxlifecycle3.android.ActivityEvent
import com.yalantis.ucrop.UCrop
import kotlinx.coroutines.Job
import java.io.FileNotFoundException
import java.text.SimpleDateFormat
import java.util.*
/**
* Created by chenran on 2017/7/24.
*/
class UserModifyPhotosActivity : TakePhotoActivity(), PhotoItemClickListener,
EasyPermissions.PermissionCallbacks {
private var userId: Long = 0
private var userInfo: UserInfo? = null
private var photoGridView: GridView? = null
private var isEditMode = false
private var adapter: UserModifyPhotosAdapter? = null
private var mActivity: UserModifyPhotosActivity? = null
public class UserModifyPhotosActivity extends TakePhotoActivity implements UserModifyPhotosAdapter.PhotoItemClickListener {
private var mUri: Uri? = null
private var mJob: Job? = null
public static final String FLAG_CHANGE = "isChanged";
companion object {
const val FLAG_CHANGE = "isChanged"
private const val TAG = "UserModifyPhotosActivit"
fun startForResult(activity: Activity, userId: Long, requestCode: Int) {
val intent = Intent(activity, UserModifyPhotosActivity::class.java)
intent.putExtra("userId", userId)
activity.startActivityForResult(intent, requestCode)
}
private long userId;
private UserInfo userInfo;
private GridView photoGridView;
private boolean isEditMode;
private UserModifyPhotosAdapter adapter;
private UserModifyPhotosActivity mActivity;
private const val PERMISSION_CODE_STORAGE = 12
private const val REQUEST_CODE_STORAGE = 42
private const val REQUEST_CODE_OPEN_PHOTO_PROVIDER = 111 // 从相册中选择
private const val MAX_BITMAP_SIZE = 100 * 1024 * 1024 // 剪切的图片最大为100 MB
private const val MIN_HEAD_PHOTO_SIZE = 20 * 1024 // 剪切的图片最小为20kb
//头像压缩后的大小不能超过大小 200KB
private const val IMAGE_MOST_COMPRESS_SIZE = 200
}
// 判断相册是否做过增减操作
private boolean isChanged = false;
public static void startForResult(Activity activity, long userId, int requestCode) {
Intent intent = new Intent(activity, UserModifyPhotosActivity.class);
intent.putExtra("userId", userId);
activity.startActivityForResult(intent, requestCode);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_photos_modify);
initView();
mActivity = this;
userId = getIntent().getLongExtra("userId", 0);
userInfo = UserModel.get().getCacheLoginUserInfo();
adapter = new UserModifyPhotosAdapter(this, new ArrayList<UserPhoto>(), this);
photoGridView.setAdapter(adapter);
private var isChanged = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user_photos_modify)
PhotoCompressUtil.clearCompressCache()
initView()
mActivity = this
userId = intent.getLongExtra("userId", 0)
userInfo = UserModel.get().cacheLoginUserInfo
adapter = UserModifyPhotosAdapter(
this,
ArrayList(),
this
)
photoGridView!!.adapter = adapter
if (userInfo != null) {
updateView();
updateView()
}
}
private void initView() {
initWhiteTitleBar("我的相册");
TitleBar titleBar = findViewById(R.id.title_bar);
titleBar.addAction(new TitleBar.TextAction("编辑",getResources().getColor(R.color.text_normal_282828)) {
@Override
public void performAction(View view) {
notifyEditMode();
private fun initView() {
initWhiteTitleBar("我的相册")
val titleBar = findViewById<TitleBar>(R.id.title_bar)
titleBar.addAction(object : TitleBar.TextAction(
"编辑",
ContextCompat.getColor(this, R.color.text_normal_282828)
) {
override fun performAction(view: View) {
notifyEditMode()
}
});
photoGridView = findViewById(R.id.gridView);
})
photoGridView = findViewById(R.id.gridView)
}
@Override
protected void onLeftClickListener() {
onBackPressed();
override fun onLeftClickListener() {
onBackPressed()
}
private void updateView() {
adapter.setData(userInfo.getPrivatePhoto());
adapter.notifyDataSetChanged();
private fun updateView() {
adapter!!.setData(userInfo!!.privatePhoto)
adapter!!.notifyDataSetChanged()
}
private void notifyEditMode() {
adapter.setEditMode(!isEditMode);
isEditMode = !isEditMode;
adapter.notifyDataSetChanged();
private fun notifyEditMode() {
adapter!!.setEditMode(!isEditMode)
isEditMode = !isEditMode
adapter!!.notifyDataSetChanged()
}
private void takePhoto() {
File cameraOutFile = JXFileUtils.getTempFile(this, "picture_" + System.currentTimeMillis() + ".jpg");
if (!cameraOutFile.getParentFile().exists()) {
cameraOutFile.getParentFile().mkdirs();
}
Uri uri = Uri.fromFile(cameraOutFile);
CompressConfig compressConfig = new CompressConfig.Builder().create();
compressConfig.setMaxSize(500 * 1024);
getTakePhoto().onEnableCompress(compressConfig, false);
getTakePhoto().onPickFromCapture(uri);
}
PermissionActivity.CheckPermListener checkPermissionListener = new PermissionActivity.CheckPermListener() {
@Override
public void superPermission() {
takePhoto();
}
};
private void checkPermissionAndStartCamera() {
//低版本授权检查
checkPermission(checkPermissionListener, R.string.ask_camera, android.Manifest.permission.CAMERA);
}
@Override
public void onPhotoDeleteClick(int position) {
getDialogManager().showProgressDialog(this, "请稍后");
override fun onPhotoDeleteClick(position: Int) {
dialogManager.showProgressDialog(this, "请稍后")
if (position != 0) {
UserPhoto userPhoto = userInfo.getPrivatePhoto().get(position - 1);
UserModel.get().requestDeletePhoto(userPhoto.getPid())
.subscribe(new BeanObserver<UserInfo>() {
@Override
public void onErrorMsg(String error) {
toast("操作失败,请检查网络");
getDialogManager().dismissDialog();
}
val userPhoto = userInfo!!.privatePhoto[position - 1]
UserModel.get().requestDeletePhoto(userPhoto.pid)
.subscribe(object : BeanObserver<UserInfo?>() {
override fun onErrorMsg(error: String) {
toast("操作失败,请检查网络")
dialogManager.dismissDialog()
}
@Override
public void onSuccess(UserInfo info) {
isChanged = true;
getDialogManager().dismissDialog();
if (info.getUid() == userId) {
userInfo = info;
updateView();
}
override fun onSuccess(info: UserInfo) {
isChanged = true
dialogManager.dismissDialog()
if (info.uid == userId) {
userInfo = info
updateView()
}
});
}
})
}
}
@Override
public void onPhotoItemClick(int position) {
override fun onPhotoItemClick(position: Int) {
if (userInfo == null) {
return;
return
}
if (position == 0) {
if (userInfo.getPrivatePhoto() != null && userInfo.getPrivatePhoto().size() == 8) {
toast("照片已达到最大上传数");
return;
if (userInfo!!.privatePhoto != null && userInfo!!.privatePhoto.size == 8) {
toast("照片已达到最大上传数")
return
}
ButtonItem upItem = new ButtonItem("拍照上传", new ButtonItem.OnClickListener() {
@Override
public void onClick() {
checkPermissionAndStartCamera();
}
});
ButtonItem loaclItem = new ButtonItem("本地相册", new ButtonItem.OnClickListener() {
@Override
public void onClick() {
CompressConfig compressConfig = new CompressConfig.Builder().create();
compressConfig.setMaxSize(500 * 1024);
getTakePhoto().onEnableCompress(compressConfig, true);
getTakePhoto().onPickFromGallery();
}
});
List<ButtonItem> buttonItemList = new ArrayList<>();
buttonItemList.add(upItem);
buttonItemList.add(loaclItem);
getDialogManager().showCommonPopupDialog(buttonItemList, "取消", false);
checkStoragePermission()
} else {
ArrayList<UserPhoto> userPhotos1 = new ArrayList<>();
userPhotos1.addAll(userInfo.getPrivatePhoto());
Intent intent = new Intent(mActivity, ShowPhotoActivity.class);
int position1 = position - 1;
intent.putExtra("position", position1);
intent.putExtra("photoList", userPhotos1);
startActivity(intent);
val userPhotos1 = ArrayList<UserPhoto>()
userPhotos1.addAll(userInfo!!.privatePhoto)
val intent = Intent(mActivity, ShowPhotoActivity::class.java)
val position1 = position - 1
intent.putExtra("position", position1)
intent.putExtra("photoList", userPhotos1)
startActivity(intent)
}
}
public void onUploadPhoto(String url) {
Logger.d("onUploadPhoto:" + url);
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<out String>, grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
}
override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
if (requestCode == PERMISSION_CODE_STORAGE) {
checkStoragePermission()
}
}
override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
if (requestCode == PERMISSION_CODE_STORAGE) {
val requestTip = "为了能正常加载您本地的文件内容,请前往应用权限设置界面打开存储空间权限。"
val mPrivacyDialog = CommonTipDialog(context)
mPrivacyDialog.setTipMsg(requestTip)
mPrivacyDialog.setOkText("去设置")
mPrivacyDialog.setOnActionListener(
object : CommonTipDialog.OnActionListener {
override fun onOk() {
//同意跳到应用详情页面
val packageUri =
Uri.parse("package:${packageName}")
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
packageUri
)
startActivityForResult(
intent, REQUEST_CODE_STORAGE
)
}
override fun onCancel() {
super.onCancel()
//取消跳到应用详情页面
ToastUtils.show("您已拒绝提供存储空间权限,将无法正常加载您本地的文件内容。")
}
}
)
mPrivacyDialog.show()
}
}
private fun checkStoragePermission() {
if (!EasyPermissions.hasPermissions(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
) {
EasyPermissions.requestPermissions(
this,
"请您再次考虑授予存储空间权限,否则将无法正常加载您本地的文件内容。",
PERMISSION_CODE_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
} else {
mUri = Uri.parse("file://${FileHelper.getRootCacheDir()?.path}/${getNowTime()}.jpg")
PhotoProviderNew.photoProvider(
this,
resultCode = REQUEST_CODE_OPEN_PHOTO_PROVIDER
)
}
}
private fun getNowTime(): String {
val date = Date(System.currentTimeMillis())
val dateFormat = SimpleDateFormat("MMddHHmmssSS")
return dateFormat.format(date)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_STORAGE) {
checkStoragePermission()
} else if (resultCode == RESULT_OK) {
when (requestCode) {
REQUEST_CODE_OPEN_PHOTO_PROVIDER -> data?.let {
val photos = PhotoProviderNew.getResultPhotoList(data) ?: return
if (photos.isNotEmpty()) {
val photo = photos[0]
crop(photo.uri, photo.size, mUri)
}
}
UCrop.REQUEST_CROP -> mUri?.path?.let {
try {
mJob?.cancel()
mJob = PhotoCompressUtil.compress(
XChatApplication.gContext,
it,
PhotoCompressUtil.getCompressCachePath(),
object : PhotoCompressCallback {
@SuppressLint("CheckResult")
override fun onSuccess(compressedImg: String) {
dialogManager.showProgressDialog(
this@UserModifyPhotosActivity,
"请稍后"
)
FileModel.get()
.uploadFile(compressedImg)
.compose(bindToLifecycle())
.subscribe { url: String?, throwable: Throwable? ->
if (throwable != null) {
onUploadFail()
} else {
onUpload(url)
}
}
}
override fun onFail(e: Throwable) {
toast(e.message)
}
},
mostCompressSize = IMAGE_MOST_COMPRESS_SIZE
)
} catch (e: FileNotFoundException) {
com.nnbc123.core.utils.Logger.error(TAG, e.message)
}
}
}
}
}
/**
* 第三方图片裁剪框架Ucrop
*/
private fun crop(sourceUri: Uri?, sourceSize: Long, destinationUri: Uri?) {
if (sourceUri == null || destinationUri == null) {
return
} //防止too large导致oom大于100m不处理内存大小
if (BitmapUtil.getSdBitmapSize(sourceUri) >= MAX_BITMAP_SIZE) {
toast(R.string.text_bitmap_too_large)
return
}
if (sourceSize > 0) {
//不能上传图片的最小文件大小
com.nnbc123.core.utils.Logger.debug(TAG, "sourceSize: $sourceSize")
if (sourceSize < MIN_HEAD_PHOTO_SIZE) {
toast(R.string.text_bitmap_too_small)
return
}
}
val options = UCrop.Options().apply {
setCompressionQuality(100)
setShowCropGrid(false)
setToolbarColor(
ContextCompat.getColor(
XChatApplication.gContext,
android.R.color.black
)
)
setStatusBarColor(
ContextCompat.getColor(
XChatApplication.gContext,
android.R.color.black
)
)
setHideBottomControls(true)
setCompressionFormat(Bitmap.CompressFormat.JPEG)
setToolbarCancelDrawable(R.drawable.user_ucrop_ic_closs)
setToolbarCropDrawable(R.drawable.user_ucrop_ic_sure)
setToolbarWidgetColor(
ContextCompat.getColor(
XChatApplication.gContext,
R.color.color_white
)
)
}
UCrop.of(sourceUri, destinationUri).withOptions(options).withAspectRatio(1f, 1f)
.withMaxResultSize(800, 800).start(this)
}
private fun onUpload(url: String?) {
Logger.d("onUploadPhoto:$url")
UserModel.get().requestAddPhoto(url)
.compose(bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(new BeanObserver<UserInfo>() {
@Override
public void onErrorMsg(String error) {
toast("操作失败,请检查网络");
getDialogManager().dismissDialog();
.compose(bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(object : BeanObserver<UserInfo?>() {
override fun onErrorMsg(error: String) {
toast("操作失敗,請檢查網絡")
dialogManager.dismissDialog()
}
override fun onSuccess(info: UserInfo) {
toast("相片已送審,審核成功後自動上傳相片")
isChanged = true
dialogManager.dismissDialog()
if (info.uid == userId) {
userInfo = info
updateView()
}
@Override
public void onSuccess(UserInfo info) {
toast("相片已送审,审核成功后自动上传相片");
isChanged = true;
getDialogManager().dismissDialog();
if (info.getUid() == userId) {
userInfo = info;
updateView();
}
}
});
}
})
}
public void onUploadPhotoFail() {
toast("操作失败,请检查网络");
getDialogManager().dismissDialog();
private fun onUploadFail() {
toast("操作失敗,請檢查網絡")
dialogManager.dismissDialog()
}
@SuppressLint("CheckResult")
@Override
public void takeSuccess(TResult result) {
getDialogManager().showProgressDialog(this, "请稍后");
FileModel.get()
.uploadFile(result.getImage().getCompressPath())
.compose(bindToLifecycle())
.subscribe((url, throwable) -> {
if (throwable != null) {
onUploadPhotoFail();
} else {
onUploadPhoto(url);
}
});
override fun onBackPressed() {
val intent = Intent()
intent.putExtra(FLAG_CHANGE, isChanged)
setResult(RESULT_OK, intent)
super.onBackPressed()
}
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra(FLAG_CHANGE, isChanged);
setResult(RESULT_OK, intent);
super.onBackPressed();
override fun needSteepStateBar(): Boolean {
return true
}
@Override
public void takeFail(TResult result, String msg) {
toast(msg);
override fun setStatusBar() {
StatusBarUtil.transparencyBar(this)
StatusBarUtil.StatusBarLightMode(this)
}
@Override
protected boolean needSteepStateBar() {
return true;
override fun onDestroy() {
super.onDestroy()
mJob?.cancel()
}
@Override
protected void setStatusBar() {
StatusBarUtil.transparencyBar(this);
StatusBarUtil.StatusBarLightMode(this);
}
}
}

View File

@@ -572,4 +572,8 @@
<item name="android:windowExitAnimation">@anim/anim_right_out</item>
</style>
<style name="AppThemeUCrop" parent="Theme.AppCompat.Light.NoActionBar">
<item name="windowNoTitle">true</item>
</style>
</resources>