diff --git a/app/build.gradle b/app/build.gradle
index 71e2210f6..a161775cb 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -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 {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7f0e5c4f5..7200237a8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1324,6 +1324,13 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/nnbc123/app/common/util/BitmapUtil.java b/app/src/main/java/com/nnbc123/app/common/util/BitmapUtil.java
new file mode 100644
index 000000000..12e1b8a3f
--- /dev/null
+++ b/app/src/main/java/com/nnbc123/app/common/util/BitmapUtil.java
@@ -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();
+ }
+}
diff --git a/app/src/main/java/com/nnbc123/app/ui/user/UserInfoModifyActivity.kt b/app/src/main/java/com/nnbc123/app/ui/user/UserInfoModifyActivity.kt
index 5a0b6cd69..ed55cdc40 100644
--- a/app/src/main/java/com/nnbc123/app/ui/user/UserInfoModifyActivity.kt
+++ b/app/src/main/java/com/nnbc123/app/ui/user/UserInfoModifyActivity.kt
@@ -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(),
+ 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 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, 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) {
+ 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) {
+ 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 userInfoUpdateObserver = new SingleObserver() {
- @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 =
+ object : SingleObserver {
+ 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(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()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/nnbc123/app/ui/user/UserModifyPhotosActivity.kt b/app/src/main/java/com/nnbc123/app/ui/user/UserModifyPhotosActivity.kt
index 926079c55..643eff998 100644
--- a/app/src/main/java/com/nnbc123/app/ui/user/UserModifyPhotosActivity.kt
+++ b/app/src/main/java/com/nnbc123/app/ui/user/UserModifyPhotosActivity.kt
@@ -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(), 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(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() {
- @Override
- public void onErrorMsg(String error) {
- toast("操作失败,请检查网络");
- getDialogManager().dismissDialog();
- }
+ val userPhoto = userInfo!!.privatePhoto[position - 1]
+ UserModel.get().requestDeletePhoto(userPhoto.pid)
+ .subscribe(object : BeanObserver() {
+ 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 buttonItemList = new ArrayList<>();
- buttonItemList.add(upItem);
- buttonItemList.add(loaclItem);
- getDialogManager().showCommonPopupDialog(buttonItemList, "取消", false);
+ checkStoragePermission()
} else {
- ArrayList 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()
+ 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, grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
+ }
+
+ override fun onPermissionsGranted(requestCode: Int, perms: MutableList) {
+ if (requestCode == PERMISSION_CODE_STORAGE) {
+ checkStoragePermission()
+ }
+ }
+
+ override fun onPermissionsDenied(requestCode: Int, perms: MutableList) {
+ 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() {
- @Override
- public void onErrorMsg(String error) {
- toast("操作失败,请检查网络");
- getDialogManager().dismissDialog();
+ .compose(bindUntilEvent(ActivityEvent.DESTROY))
+ .subscribe(object : BeanObserver() {
+ 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);
- }
-
-}
+}
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 227d729ee..50a77bfb5 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -572,4 +572,8 @@
- @anim/anim_right_out
+
+
diff --git a/library/src/main/res/drawable-xhdpi/user_ucrop_ic_closs.webp b/library/src/main/res/drawable-xhdpi/user_ucrop_ic_closs.webp
new file mode 100644
index 000000000..d7b4aeb46
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/user_ucrop_ic_closs.webp differ
diff --git a/library/src/main/res/drawable-xhdpi/user_ucrop_ic_sure.webp b/library/src/main/res/drawable-xhdpi/user_ucrop_ic_sure.webp
new file mode 100644
index 000000000..eb6c5557c
Binary files /dev/null and b/library/src/main/res/drawable-xhdpi/user_ucrop_ic_sure.webp differ