diff --git a/app/build.gradle b/app/build.gradle index 7f7a889..561e220 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -406,4 +406,5 @@ dependencies { implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.1' implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 665daf0..4d6ab05 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -116,6 +116,7 @@ tools:replace="android:label,android:allowBackup" tools:targetApi="r"> + @@ -176,7 +177,8 @@ - + + + + + diff --git a/app/src/main/java/com/xuebiping/bolizhuzi/view/main/CoverActivity.java b/app/src/main/java/com/xuebiping/bolizhuzi/view/main/CoverActivity.java index 96478c4..385800d 100644 --- a/app/src/main/java/com/xuebiping/bolizhuzi/view/main/CoverActivity.java +++ b/app/src/main/java/com/xuebiping/bolizhuzi/view/main/CoverActivity.java @@ -89,7 +89,7 @@ public class CoverActivity extends BaseActivity { @Override public SwipeRefreshLayout getRefresh() { - return refreshLayout; + return null; } public void showLoginDialog() { @@ -360,14 +360,14 @@ public class CoverActivity extends BaseActivity { return false; } - SwipeRefreshLayout refreshLayout; + //SwipeRefreshLayout refreshLayout; @Override public void onCreate(Bundle onSavedInstance) { AppStatusCallbacks.get().setmAppStatus(AppStatusCallbacks.STATUS_NORMAL); super.onCreate(onSavedInstance); setContentView(R.layout.activity_cover); - refreshLayout = findViewById(R.id.refreshLayout); + // refreshLayout = findViewById(R.id.refreshLayout); // 全屏 // 获取唤醒参数 // OpenInstall.getWakeUp(getIntent(), wakeUpAdapter); diff --git a/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/PhotoListActivity.java b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/PhotoListActivity.java new file mode 100644 index 0000000..4e677f4 --- /dev/null +++ b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/PhotoListActivity.java @@ -0,0 +1,481 @@ +package com.xuebiping.bolizhuzi.view.settings; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; + +import android.Manifest; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.media.ThumbnailUtils; +import android.net.Uri; +import android.os.Bundle; +import android.provider.MediaStore; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; + +import com.fengliyan.http.httprequest.UploadFile; +import com.fengliyan.uikit.photopicker.MultiImageSelector; +import com.fengliyan.uikit.sketch.SketchImageView; +import com.fengliyan.uikit.toast.MaleToast; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.xuebiping.bolizhuzi.R; +import com.xuebiping.bolizhuzi.controller.constant.ConsUser; +import com.xuebiping.bolizhuzi.controller.constant.ConstUrl; +import com.xuebiping.bolizhuzi.controller.constant.Constant; +import com.xuebiping.bolizhuzi.controller.dynamics.manager.DynamicsManager; +import com.xuebiping.bolizhuzi.controller.main.manager.GlobalManager; +import com.xuebiping.bolizhuzi.controller.settings.adapter.InfoEditPhotoRecyclerAdapter; +import com.xuebiping.bolizhuzi.controller.settings.manager.SettingManager; +import com.xuebiping.bolizhuzi.controller.settings.manager.UserAvatarManager; +import com.xuebiping.bolizhuzi.im.uikit.common.Constans; +import com.xuebiping.bolizhuzi.im.uikit.common.util.file.AttachmentStore; +import com.xuebiping.bolizhuzi.im.uikit.common.util.file.FileUtil; +import com.xuebiping.bolizhuzi.im.uikit.common.util.storage.StorageType; +import com.xuebiping.bolizhuzi.im.uikit.common.util.storage.StorageUtil; +import com.xuebiping.bolizhuzi.im.uikit.common.util.string.MD5; +import com.xuebiping.bolizhuzi.model.dynamics.UploadImageBean; +import com.xuebiping.bolizhuzi.model.settings.UserHomeBean; +import com.xuebiping.bolizhuzi.utils.PermissionUtil; +import com.xuebiping.bolizhuzi.utils.SPUtils; +import com.xuebiping.bolizhuzi.utils.SimpleItemTouchCallBack; +import com.xuebiping.bolizhuzi.utils.StrU; +import com.xuebiping.bolizhuzi.utils.camera2.BitmapUtils; +import com.xuebiping.bolizhuzi.view.base.BaseActivity; +import com.xuebiping.bolizhuzi.view.base.utils.HttpUiCallBack; +import com.xuebiping.bolizhuzi.view.base.utils.ImageUtils; +import com.xuebiping.bolizhuzi.view.diooto.Diooto; +import com.xuebiping.bolizhuzi.view.diooto.config.DiootoConfig; +import com.xuebiping.bolizhuzi.view.diooto.tools.Utils; +import com.xuebiping.bolizhuzi.view.main.dialog.CustomAlertDialog; +import com.xuebiping.bolizhuzi.view.main.dialog.PermissionDialog; +import com.xuebiping.bolizhuzi.view.settings.video.VideoSelectActivity; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import kotlin.Unit; +import kotlin.jvm.functions.Function1; +import kotlin.jvm.functions.Function2; + +public class PhotoListActivity extends BaseActivity implements UserAvatarManager.UserImgListener { + + private RecyclerView mPhotoListView; + private InfoEditPhotoRecyclerAdapter mPhotoAdapter; + + private String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_PHONE_STATE}; + + private List mPhotoDataList = new ArrayList() { + { + add("selector"); + add(""); + add(""); + add(""); + add(""); + add(""); + add(""); + add(""); + add(""); + } + }; + + private List mOldPhotoDataList = new ArrayList() { + { + add("selector"); + add(""); + add(""); + add(""); + add(""); + add(""); + add(""); + add(""); + add(""); + } + }; + + private MultiImageSelector mSelector; + private PermissionDialog permissionDialog; + + private UserAvatarManager mManager; + public static final int MULTI_SELECTOR_REQUEST = 200; + private HashMap photoListIndexMap; + private StringBuilder mImages; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_photo_list); + setTitleName("相册"); + + mSelector = MultiImageSelector.create().multi().count(9); + + mManager = new UserAvatarManager(this); + + initView(); + + } + + private void initView() { + mPhotoListView = findViewById(R.id.rv_list); + + mPhotoListView.setLayoutManager(new GridLayoutManager(this, 3)); + mPhotoListView.setNestedScrollingEnabled(false); + ViewGroup.LayoutParams layoutParams = mPhotoListView.getLayoutParams(); + layoutParams.height = Utils.dip2px(this, 360); + mPhotoListView.setLayoutParams(layoutParams); + + mPhotoAdapter = new InfoEditPhotoRecyclerAdapter(this); + mPhotoAdapter.setPhotoList(mPhotoDataList); + mPhotoAdapter.setOnSelectorClickedListener(new InfoEditPhotoRecyclerAdapter + .OnSelectorClickedListener() { + @Override + public void onSelectorClicked() { + checkPermission(2); + } + + @Override + public void onClickImage(List mPhotoList, int position) { + if (null != mPhotoList && mPhotoList.size() != 0) { + List imageUrl = new ArrayList<>(); + for (String imagePath : mPhotoList) { + if (!TextUtils.isEmpty(imagePath) && !imagePath.equals("selector")) { + if (imagePath.contains("uploads/")) { + imageUrl.add(StrU.getResourcePath(imagePath, PhotoListActivity.this)); + } else { + imageUrl.add("file://" + imagePath); + } + } + } + clickImage((ArrayList) imageUrl, position); + } + } + }); + mPhotoListView.setAdapter(mPhotoAdapter); + // 拖拽移动和左滑删除 + SimpleItemTouchCallBack simpleItemTouchCallBack = new SimpleItemTouchCallBack(mPhotoAdapter); + ItemTouchHelper helper = new ItemTouchHelper(simpleItemTouchCallBack); + helper.attachToRecyclerView(mPhotoListView); + + findViewById(R.id.submit_button).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + //TODO 这里需要调接口上传 提交 + //updateData(); + } + }); + } + + public void getUserInfo() { + SettingManager.getHomeUser(this, new HttpUiCallBack() { + @Override + public void onSuccess(BaseActivity activity, UserHomeBean result, String message) { + if (result.getUserinfo() != null) { + + List album_list = result.getUserinfo().getAlbum_list(); + int size = album_list.size(); + if (size > 0) { + for (int i = 0; i < size; i++) { + mPhotoDataList.set(i, album_list.get(i)); + mOldPhotoDataList.set(i, album_list.get(i)); + + } + if (size < 6) { + mPhotoDataList.set(size, "selector"); + mOldPhotoDataList.set(size, "selector"); + } + mPhotoAdapter.setPhotoList(mPhotoDataList); + mPhotoAdapter.notifyDataSetChanged(); + } + } + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + + } + }); + } + + /** + * @param type 0.封面视频 1.头像 2.相册 + */ + private void checkPermission(int type) { + permissionDialog = new PermissionDialog(PhotoListActivity.this, permissions); + permissionDialog.show(); + XXPermissions.with(PhotoListActivity.this) + .permission(permissions) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + startImageSelector(); + } + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + CustomAlertDialog customAlertDialog = new CustomAlertDialog(PhotoListActivity.this); + customAlertDialog.setTitle("芊颜需要开启读写权限,以便查看本地图库内容"); + customAlertDialog.hideContent(true); + customAlertDialog.setRightBtnText("去开启"); + customAlertDialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(PhotoListActivity.this); + } + }); + customAlertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + customAlertDialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + } + + /** + * 跳到图片展示页 + * + * @param pathList + * @param innerCount + */ + private void clickImage(ArrayList pathList, int innerCount) { + String[] strings = new String[pathList.size()]; + for (int i = 0; i < pathList.size(); i++) { + strings[i] = pathList.get(i); + } + Diooto diooto = new Diooto(this) + .urls(strings) + .type(DiootoConfig.PHOTO) + .immersive(true) + .position(innerCount, 0) + .views(mPhotoListView, R.id.info_edit_photo_normal, pathList.size()) + .loadPhotoBeforeShowBigImage(new Diooto.OnLoadPhotoBeforeShowBigImageListener() { + @Override + public void loadView(SketchImageView sketchImageView, int position) { + sketchImageView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + return false; + } + }); + } + }) + .start(); + } + + public void startImageSelector() { + mSelector.multi(); + mSelector.count(1); + mSelector.start(this, MULTI_SELECTOR_REQUEST); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { +// if (isChooseVideo) { +// helper.onGetLocalVideoResult(data); +// return; +// } + super.onActivityResult(requestCode, resultCode, data); + if (mManager != null) { + mManager.onActivityResult(requestCode, resultCode, data); + } + if (requestCode == MULTI_SELECTOR_REQUEST && resultCode == RESULT_OK) { + List albumList = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT); + String s = "file://" + albumList.get(0); + mManager.whoStartCropWithUi(Uri.parse(s)); + } + } + + @Override + public void getUserImg(@Nullable final String path) { + if (null != path && !TextUtils.isEmpty(path)) { + List albumList = new ArrayList<>(); + + albumList.add(path); + + for (int i = 0; i < albumList.size(); i++) { + if (5 - i >= 0) { + mPhotoDataList.remove(5 - i); + } + } + + int realSize = 0; + for (int i = 0; i < mPhotoDataList.size(); i++) { + if (!"".equals(mPhotoDataList.get(i)) && !"selector".equals(mPhotoDataList.get(i))) { + realSize++; + } + } + + mPhotoDataList.addAll(realSize, albumList); + mPhotoAdapter.notifyDataSetChanged(); + } + } + + /** + * 更新数据 + */ + private void updateData() { + boolean hasPhoto = false; + for (String path : mPhotoDataList) { + if (path.equals("") || path.equals("selector")) { + continue; + } + + hasPhoto = true; + } + + if (!hasPhoto) { + //editProfile(null); + } else { + new Thread(new Runnable() { + @Override + public void run() { + compressAndUpload(); + } + }).start(); + + } + } + + private void compressAndUpload() { + List photoList = mPhotoAdapter.getmPhotoList(); + Iterator i = photoList.iterator(); + int realSize = 0; + int currentListCount = 6; + photoListIndexMap = new HashMap<>(); + for (int index = 0; index < photoList.size(); index++) { + String path = photoList.get(index); + if ("selector".equals(path)) { + currentListCount = index; + } + if ("".equals(path) || "selector".equals(path) || path.contains("uploads/")) { + continue; + } + photoListIndexMap.put(realSize, index); + realSize++; + } + + final UploadFile[] uploadFiles = new UploadFile[realSize]; + int count = 0; + while (i.hasNext()) { + String path = i.next(); + if ("".equals(path) || "selector".equals(path) || path.contains("uploads/")) { + continue; + } + path = ImageUtils.compressImage(this, path, Constant.IMAGE_MEMORY_SIZE, true); + File file = new File(path); + UploadFile uploadFile = new UploadFile("file[" + count + "]", file); + uploadFiles[count] = uploadFile; + count++; + } + + if (null != uploadFiles) { + if (uploadFiles.length != 0) { + if (uploadFiles[0].getFile().exists()) { + runOnUiThread(new Runnable() { + @Override + public void run() { + uploadImage(uploadFiles); + } + }); + } + } else { + final StringBuilder stringBuilder = new StringBuilder(); + for (int i1 = 0; i1 < currentListCount; i1++) { + String str = photoList.get(i1); + if (TextUtils.isEmpty(str) || "selector".equals(str)) { + continue; + } + stringBuilder.append(str); + if (i1 < currentListCount - 1) { + stringBuilder.append(","); + } + } + runOnUiThread(new Runnable() { + @Override + public void run() { + //editProfile(stringBuilder.toString()); + } + }); + } + } + } + + private void uploadImage(final UploadFile[] uploadFiles) { + DynamicsManager.uploadImage(this, uploadFiles, "album", + new HttpUiCallBack>() { + @Override + public void onSuccess(BaseActivity activity, List result, String message) { + mImages = new StringBuilder(); + List photoList = mPhotoAdapter.getmPhotoList(); + for (int i = 0; i < result.size(); i++) { + Integer integer = photoListIndexMap.get(i); + photoList.set(integer, result.get(i).getUrl()); + } + + for (int i = 0; i < photoList.size(); i++) { + String str = photoList.get(i); + if (TextUtils.isEmpty(str) || "selector".equals(str)) { + continue; + } + mImages.append(str); + if (i < photoList.size() - 1) { + mImages.append(","); + } + } + + //editProfile(mImages.toString()); + photoListIndexMap.clear(); + + //上传成功后删掉本地图片 + new Thread(new Runnable() { + @Override + public void run() { + for (UploadFile uploadFile : uploadFiles) { + File file = uploadFile.getFile(); + if (file.exists()) { + file.delete(); + } + } + } + }).start(); + } + + @Override + public void onFailure(BaseActivity activity, String tip) { + MaleToast.showMessage(activity, tip); + } + + @Override + public void onException(BaseActivity activity, Throwable e) { + MaleToast.showMessage(activity, "图片上传失败"); + } + }); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/RealNameTwoActivity.java b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/RealNameTwoActivity.java new file mode 100644 index 0000000..1f96455 --- /dev/null +++ b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/RealNameTwoActivity.java @@ -0,0 +1,259 @@ +package com.xuebiping.bolizhuzi.view.settings; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import android.Manifest; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.media.ThumbnailUtils; +import android.net.Uri; +import android.os.Bundle; +import android.provider.MediaStore; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Log; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.uikit.photopicker.MultiImageSelector; +import com.fengliyan.uikit.photopicker.bean.Image; +import com.fengliyan.uikit.toast.MaleToast; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.xuebiping.bolizhuzi.R; +import com.xuebiping.bolizhuzi.controller.constant.ConstUrl; +import com.xuebiping.bolizhuzi.controller.settings.manager.UserAvatarManager; +import com.xuebiping.bolizhuzi.im.uikit.common.util.file.AttachmentStore; +import com.xuebiping.bolizhuzi.im.uikit.common.util.file.FileUtil; +import com.xuebiping.bolizhuzi.im.uikit.common.util.storage.StorageType; +import com.xuebiping.bolizhuzi.im.uikit.common.util.storage.StorageUtil; +import com.xuebiping.bolizhuzi.im.uikit.common.util.string.MD5; +import com.xuebiping.bolizhuzi.utils.PermissionUtil; +import com.xuebiping.bolizhuzi.utils.camera2.BitmapUtils; +import com.xuebiping.bolizhuzi.view.base.BaseActivity; +import com.xuebiping.bolizhuzi.view.main.dialog.CustomAlertDialog; +import com.xuebiping.bolizhuzi.view.main.dialog.PermissionDialog; +import com.xuebiping.bolizhuzi.view.settings.video.VideoSelectActivity; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import kotlin.Unit; +import kotlin.jvm.functions.Function1; +import kotlin.jvm.functions.Function2; + +public class RealNameTwoActivity extends BaseActivity implements UserAvatarManager.UserImgListener { + + private EditText ed_name; + private EditText ed_id_num; + private LinearLayout ll_card_z_layout; + private SimpleDraweeView iv_card_z; + private LinearLayout ll_card_f_layout; + private SimpleDraweeView iv_card_f; + private LinearLayout ll_card_shou_layout; + private SimpleDraweeView iv_shou_z; + private TextView tv_commit; + private PermissionDialog permissionDialog; + + private MultiImageSelector mSelector; + + private UserAvatarManager mManager; + + String avatarPath; + String avatarUrl; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_real_name_two); + + setTitleName("身份认证"); + + mSelector = MultiImageSelector.create().multi().count(1); + + mManager = new UserAvatarManager(this); + + initView(); + } + + private void initView() { + ed_name = findViewById(R.id.ed_name); + ed_id_num = findViewById(R.id.ed_id_num); + ll_card_z_layout = findViewById(R.id.ll_card_z_layout); + iv_card_z = findViewById(R.id.iv_card_z); + ll_card_f_layout = findViewById(R.id.ll_card_f_layout); + iv_card_f = findViewById(R.id.iv_card_f); + ll_card_shou_layout = findViewById(R.id.ll_card_shou_layout); + iv_shou_z = findViewById(R.id.iv_shou_z); + tv_commit = findViewById(R.id.tv_commit); + + ed_id_num.addTextChangedListener(mTextWatcher); + ed_name.addTextChangedListener(mTextWatcher); + + tv_commit.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (checkIsEnable()) { + //TODO 调接口提交 + } + } + }); + + ll_card_z_layout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + type = 1; + checkPermission(); + } + }); + + ll_card_f_layout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + type = 2; + checkPermission(); + } + }); + + ll_card_shou_layout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + type = 3; + checkPermission(); + } + }); + + } + + private TextWatcher mTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void afterTextChanged(Editable editable) { + if (isCommitEnable()) { + tv_commit.setEnabled(true); + } else { + tv_commit.setEnabled(false); + } + } + }; + + public boolean isCommitEnable() { + if (TextUtils.isEmpty(ed_id_num.getText().toString())) { + return false; + } + if (TextUtils.isEmpty(ed_name.getText().toString())) { + return false; + } + return true; + } + + public boolean checkIsEnable() { + if (TextUtils.isEmpty(ed_id_num.getText())) { + MaleToast.showMessage(RealNameTwoActivity.this, "请输入身份证号"); + return false; + } + if (TextUtils.isEmpty(ed_name.getText())) { + MaleToast.showMessage(RealNameTwoActivity.this, "请输入你的真实姓名"); + return false; + } + return true; + } + + private String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE}; + + //type 1 身份证正面 2身份证反面 3手持正面 + int type = 0; + + private void checkPermission() { + permissionDialog = new PermissionDialog(RealNameTwoActivity.this, permissions); + permissionDialog.show(); + XXPermissions.with(RealNameTwoActivity.this) + .permission(permissions) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + startImageSelector(); + } + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + CustomAlertDialog customAlertDialog = new CustomAlertDialog(RealNameTwoActivity.this); + customAlertDialog.setTitle("芊颜需要开启读写权限,以便查看本地图库内容"); + customAlertDialog.hideContent(true); + customAlertDialog.setRightBtnText("去开启"); + customAlertDialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(RealNameTwoActivity.this); + } + }); + customAlertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + customAlertDialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + } + + public void startImageSelector() { + mSelector.multi(); + mSelector.count(1); + mSelector.start(this, 200); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { +// if (isChooseVideo) { +// helper.onGetLocalVideoResult(data); +// return; +// } + super.onActivityResult(requestCode, resultCode, data); + if (mManager != null) { + mManager.onActivityResult(requestCode, resultCode, data); + } + if (requestCode == 200 && resultCode == RESULT_OK) { + List albumList = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT); + String s = "file://" + albumList.get(0); + mManager.whoStartCropWithUi(Uri.parse(s)); + } + } + + @Override + public void getUserImg(@Nullable @org.jetbrains.annotations.Nullable String path) { + this.avatarPath = path; + avatarUrl = null; + if(type == 1) { + iv_card_z.setImageURI("file://" + this.avatarPath); + }else if(type == 2){ + iv_card_f.setImageURI("file://" + this.avatarPath); + }else if(type == 3){ + iv_shou_z.setImageURI("file://" + this.avatarPath); + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/SettingFragment.java b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/SettingFragment.java index b52d857..9547d7d 100644 --- a/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/SettingFragment.java +++ b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/SettingFragment.java @@ -893,10 +893,11 @@ public class SettingFragment extends Fragment implements View.OnClickListener { mHint.setVisibility(View.GONE); mArrow.setVisibility(View.VISIBLE); mLogo.setImageResource(R.mipmap.ic_my_ntequan); - mName.setText("女神特权"); + mName.setText("up主认证"); view.setOnClickListener(view19 -> { if (!BaseApplication.getInstance().showCertificationDialog(getActivity())) { - startActivity(new Intent(getActivity(), GoddessPrivilegeActivity.class)); + //startActivity(new Intent(getActivity(), GoddessPrivilegeActivity.class)); + startActivity(new Intent(getActivity(), UpPrivilegeActivity.class)); } }); break; diff --git a/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/UpPrivilegeActivity.java b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/UpPrivilegeActivity.java new file mode 100644 index 0000000..fe7a762 --- /dev/null +++ b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/UpPrivilegeActivity.java @@ -0,0 +1,634 @@ +package com.xuebiping.bolizhuzi.view.settings; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import android.Manifest; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.media.ThumbnailUtils; +import android.net.Uri; +import android.os.Bundle; +import android.provider.MediaStore; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.bigkoo.pickerview.builder.OptionsPickerBuilder; +import com.bigkoo.pickerview.builder.TimePickerBuilder; +import com.bigkoo.pickerview.configure.PickerOptions; +import com.bigkoo.pickerview.listener.OnOptionsSelectChangeListener; +import com.bigkoo.pickerview.listener.OnOptionsSelectListener; +import com.bigkoo.pickerview.listener.OnTimeSelectListener; +import com.bigkoo.pickerview.view.OptionsPickerView; +import com.bigkoo.pickerview.view.TimePickerView; +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.uikit.photopicker.MultiImageSelector; +import com.fengliyan.uikit.toast.MaleToast; +import com.google.gson.Gson; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.xuebiping.bolizhuzi.R; +import com.xuebiping.bolizhuzi.controller.constant.ConsUser; +import com.xuebiping.bolizhuzi.controller.constant.ConstUrl; +import com.xuebiping.bolizhuzi.controller.main.manager.GlobalManager; +import com.xuebiping.bolizhuzi.controller.settings.manager.UserAvatarManager; +import com.xuebiping.bolizhuzi.im.uikit.common.util.file.AttachmentStore; +import com.xuebiping.bolizhuzi.im.uikit.common.util.file.FileUtil; +import com.xuebiping.bolizhuzi.im.uikit.common.util.storage.StorageType; +import com.xuebiping.bolizhuzi.im.uikit.common.util.storage.StorageUtil; +import com.xuebiping.bolizhuzi.im.uikit.common.util.storage.SysSPUtils; +import com.xuebiping.bolizhuzi.im.uikit.common.util.string.MD5; +import com.xuebiping.bolizhuzi.model.main.GlobalConfigBean; +import com.xuebiping.bolizhuzi.utils.PermissionUtil; +import com.xuebiping.bolizhuzi.utils.SPUtils; +import com.xuebiping.bolizhuzi.utils.camera2.BitmapUtils; +import com.xuebiping.bolizhuzi.view.base.BaseActivity; +import com.xuebiping.bolizhuzi.view.main.CityPickerActivity; +import com.xuebiping.bolizhuzi.view.main.dialog.CustomAlertDialog; +import com.xuebiping.bolizhuzi.view.main.dialog.PermissionDialog; +import com.xuebiping.bolizhuzi.view.settings.video.VideoSelectActivity; + +import java.io.File; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import kotlin.Unit; +import kotlin.jvm.functions.Function1; +import kotlin.jvm.functions.Function2; + +public class UpPrivilegeActivity extends BaseActivity implements View.OnClickListener, UserAvatarManager.UserImgListener { + + private RelativeLayout rl_avatar_layout; + private EditText tv_nikename; + private EditText tv_sign; + private EditText tv_zybq; + private RelativeLayout rl_gender_layout; + private RelativeLayout rl_cover_layout; + private RelativeLayout rl_card_layout; + private RelativeLayout rl_video_rz_layout; + private RelativeLayout rl_birthday_layout; + private RelativeLayout rl_wxcode_layout; + private RelativeLayout rl_sanwei_layout; + private RelativeLayout rl_photo_layout; + private RelativeLayout rl_video_cover_layout; + private RelativeLayout rl_height_layout; + private RelativeLayout rl_tiz_layout; + private RelativeLayout rl_xz_layout; + private RelativeLayout rl_city_layout; + private PermissionDialog permissionDialog; + + private TimePickerView mAgePicker; + private String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_PHONE_STATE}; + + public static final int MULTI_SELECTOR_REQUEST = 200; + public static final int VIDEO_COVER_REQUEST = 501;//封面视频 + public static final int MAX_IMAGE_COUNT = 9; + + private boolean isChooseAvatar = false; + boolean isChooseVideo = false; + + private MultiImageSelector mSelector; + + String avatarPath; + String avatarUrl; + String videoCoverPath; + String videoCoverUrl; + String videoUrl; + + private String del_video = "0"; + private String height = "未填写"; + private String tizhong = "未填写"; + private String xingzuo = "未填写"; + private String sanwwei = "未填写"; + private String gender = "未填写"; + + private UserAvatarManager mManager; + private SimpleDraweeView sd_avatar; + private TextView tv_birthday; + private SimpleDraweeView sd_video_cover; + + private File videoFile; + private TextView tv_height; + private OptionsPickerView pvHeighttions; + private OptionsPickerView pvTiZhongttions; + private OptionsPickerView pvXingZuottions; + private OptionsPickerView pvSanWeittions; + private OptionsPickerView pvGenderttions; + private TextView tv_tiz; + private TextView tv_city; + private String mCityId; + private TextView tv_xz; + private TextView tv_sanwei; + private TextView tv_gender; + private Button submit_button; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_up_privilege); + + setRightCustomTextTitle("UP主认证", "准则", new View.OnClickListener() { + @Override + public void onClick(View view) { + + } + }); + + mManager = new UserAvatarManager(this); + + initView(); + } + + private void initView() { + rl_avatar_layout = findViewById(R.id.rl_avatar_layout); + sd_avatar = findViewById(R.id.sd_avatar); + tv_nikename = findViewById(R.id.tv_nikename); + tv_sign = findViewById(R.id.tv_sign); + tv_zybq = findViewById(R.id.tv_zybq); + rl_gender_layout = findViewById(R.id.rl_gender_layout); + tv_gender = findViewById(R.id.tv_gender); + rl_cover_layout = findViewById(R.id.rl_cover_layout); + rl_card_layout = findViewById(R.id.rl_card_layout); + rl_video_rz_layout = findViewById(R.id.rl_video_rz_layout); + rl_birthday_layout = findViewById(R.id.rl_birthday_layout); + tv_birthday = findViewById(R.id.tv_birthday); + rl_wxcode_layout = findViewById(R.id.rl_wxcode_layout); + rl_sanwei_layout = findViewById(R.id.rl_sanwei_layout); + tv_sanwei = findViewById(R.id.tv_sanwei); + rl_photo_layout = findViewById(R.id.rl_photo_layout); + rl_video_cover_layout = findViewById(R.id.rl_video_cover_layout); + sd_video_cover = findViewById(R.id.sd_video_cover); + rl_height_layout = findViewById(R.id.rl_height_layout); + tv_height = findViewById(R.id.tv_height); + rl_tiz_layout = findViewById(R.id.rl_tiz_layout); + tv_tiz = findViewById(R.id.tv_tiz); + rl_xz_layout = findViewById(R.id.rl_xz_layout); + tv_xz = findViewById(R.id.tv_xz); + rl_city_layout = findViewById(R.id.rl_city_layout); + tv_city = findViewById(R.id.tv_city); + submit_button = findViewById(R.id.submit_button); + + mSelector = MultiImageSelector.create().multi().count(MAX_IMAGE_COUNT); + + rl_avatar_layout.setOnClickListener(this); + rl_gender_layout.setOnClickListener(this); + rl_cover_layout.setOnClickListener(this); + rl_card_layout.setOnClickListener(this); + rl_video_rz_layout.setOnClickListener(this); + rl_birthday_layout.setOnClickListener(this); + rl_wxcode_layout.setOnClickListener(this); + rl_sanwei_layout.setOnClickListener(this); + rl_photo_layout.setOnClickListener(this); + rl_video_cover_layout.setOnClickListener(this); + rl_height_layout.setOnClickListener(this); + rl_tiz_layout.setOnClickListener(this); + rl_xz_layout.setOnClickListener(this); + rl_city_layout.setOnClickListener(this); + submit_button.setOnClickListener(this); + + initAgePicker(); + initHeightOptionPicker(); + initTiZhongOptionPicker(); + initXingZuoOptionPicker(); + initSanWeiOptionPicker(); + initGenderOptionPicker(); + + } + + @Override + public void onClick(View view) { + if (view.getId() == R.id.rl_avatar_layout) { + checkPermission(1); + } else if (view.getId() == R.id.rl_gender_layout) { + pvGenderttions.show(); + } else if (view.getId() == R.id.rl_cover_layout) { + startActivityForResult(new Intent(this,UploadPhotoCoverActivity.class),202); + } else if (view.getId() == R.id.rl_card_layout) { + startActivityForResult(new Intent(this,RealNameTwoActivity.class),203); + } else if (view.getId() == R.id.rl_video_rz_layout) { + startActivityForResult(new Intent(this,VideoRenzhengActivity.class),204); + } else if (view.getId() == R.id.rl_birthday_layout) { + mAgePicker.show(); + } else if (view.getId() == R.id.rl_wxcode_layout) { + startActivity(new Intent(this, WXAccountActivity.class)); + } else if (view.getId() == R.id.rl_sanwei_layout) { + pvSanWeittions.show(); + } else if (view.getId() == R.id.rl_photo_layout) { + startActivity(new Intent(this, PhotoListActivity.class)); + }else if (view.getId() == R.id.rl_height_layout) { + pvHeighttions.show(); + }else if (view.getId() == R.id.rl_tiz_layout) { + pvTiZhongttions.show(); + }else if (view.getId() == R.id.rl_xz_layout) { + pvXingZuottions.show(); + }else if (view.getId() == R.id.rl_video_cover_layout) { + checkPermission(0); + }else if (view.getId() == R.id.rl_city_layout) { + Intent intent = new Intent(this, CityPickerActivity.class); + startActivityForResult(intent, 1001); + }else if (view.getId() == R.id.submit_button) { + //TODO 这个调提交接口 + } + } + + /** + * @param type 0.封面视频 1.头像 2.相册 + */ + private void checkPermission(int type) { + permissionDialog = new PermissionDialog(UpPrivilegeActivity.this, permissions); + permissionDialog.show(); + XXPermissions.with(UpPrivilegeActivity.this) + .permission(permissions) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + if (type == 0) { + VideoSelectActivity.launchForResult(UpPrivilegeActivity.this, VideoSelectActivity.TYPE_VIDEO_CUT, VIDEO_COVER_REQUEST); + } else { + startImageSelector(type == 1); + } + } + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + CustomAlertDialog customAlertDialog = new CustomAlertDialog(UpPrivilegeActivity.this); + customAlertDialog.setTitle("芊颜需要开启读写权限,以便查看本地图库内容"); + customAlertDialog.hideContent(true); + customAlertDialog.setRightBtnText("去开启"); + customAlertDialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(UpPrivilegeActivity.this); + } + }); + customAlertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + customAlertDialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + } + + public void startImageSelector(boolean isChooseAvatar) { + isChooseVideo = false; + this.isChooseAvatar = isChooseAvatar; + mSelector.multi(); + mSelector.count(1); + mSelector.start(this, MULTI_SELECTOR_REQUEST); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { +// if (isChooseVideo) { +// helper.onGetLocalVideoResult(data); +// return; +// } + super.onActivityResult(requestCode, resultCode, data); + if (mManager != null) { + mManager.onActivityResult(requestCode, resultCode, data); + } + if (requestCode == MULTI_SELECTOR_REQUEST && resultCode == RESULT_OK) { + List albumList = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT); + String s = "file://" + albumList.get(0); + mManager.whoStartCropWithUi(Uri.parse(s)); + } else if (requestCode == VIDEO_COVER_REQUEST) {//封面视频 + if (data != null) { + String videoPath = data.getStringExtra("VideoPath"); + if (ConstUrl.LOGDEBUG) + Log.i("TAG", "onActivityResult: videoPath----------->" + videoPath); + + String md5 = MD5.getStreamMD5(videoPath); + String filename = md5 + "." + FileUtil.getExtensionName(videoPath); + String md5Path = StorageUtil.getWritePath(filename, StorageType.TYPE_VIDEO); + + if (AttachmentStore.copy(videoPath, md5Path) != -1) { + videoFile = new File(md5Path); + } + Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(videoFile.getAbsolutePath(), MediaStore.Video.Thumbnails.FULL_SCREEN_KIND); + BitmapUtils.savePicNoRotate(BitmapUtils.toByteArray(bitmap), "video_cover", + new Function2() { + @Override + public Unit invoke(String s, String s2) { + bitmap.recycle(); + runOnUiThread(new Runnable() { + @Override + public void run() { + List paths = new ArrayList<>(); + paths.add(s); + videoUrl = null; + videoCoverUrl = null; + videoCoverPath = s; + del_video = "0"; + sd_video_cover.setImageURI("file://" + videoCoverPath); + } + }); + return null; + } + }, new Function1() { + @Override + public Unit invoke(String s) { + runOnUiThread(new Runnable() { + @Override + public void run() { + MaleToast.showMessage(UpPrivilegeActivity.this, "获取视频缩略图失败"); + + } + }); + return null; + } + }); + } + }else if(requestCode == 202){ //上传封面图返回 + //TODO + }else if(requestCode == 203){ //修改身份认证状态 + //TODO + }else if(requestCode == 204){ //视频认证结果 + //TODO + } else if (requestCode == 1001 && resultCode == RESULT_OK) { + if (null != data) { + String city = data.getStringExtra("city"); + SPUtils.saveString(this, ConsUser.PICKER_CITY + "", city); + tv_city.setText(city); + if (!TextUtils.isEmpty(city)) { + mCityId = GlobalManager.getCityMap().get(city); + } + } + } + } + + @Override + public void getUserImg(@Nullable @org.jetbrains.annotations.Nullable String path) { + if (isChooseAvatar) { + this.avatarPath = path; + avatarUrl = null; + sd_avatar.setImageURI("file://" + this.avatarPath); + return; + } + } + + private void initAgePicker() { + Calendar endCalendar = Calendar.getInstance(); + endCalendar.set(endCalendar.get(Calendar.YEAR) - 18 + , endCalendar.get(Calendar.MONTH) + , endCalendar.get(Calendar.DAY_OF_MONTH)); + + Calendar startCalendar = Calendar.getInstance(); + startCalendar.set(1940, 1, 1); + + mAgePicker = new TimePickerBuilder(this, new OnTimeSelectListener() { + @Override + public void onTimeSelect(Date date, View v) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int month = calendar.get(Calendar.MONTH) + 1; + int day = calendar.get(Calendar.DATE); + int year = calendar.get(Calendar.YEAR); + tv_birthday.setText(year + "-" + month + "-" + day + " "); + } + }).setRangDate(startCalendar, endCalendar).build(); + + mAgePicker.setDate(endCalendar); + } + + public void onDestroy() { + super.onDestroy(); + if (null != mAgePicker && mAgePicker.isShowing()) { + mAgePicker.dismiss(); + } + } + + public List heightLists=new ArrayList<>(); + + private void initHeightOptionPicker() {//条件选择器初始化 + heightLists.clear(); + for (int i = 160; i < 191; i++) { + heightLists.add(i+"CM"); + } + /** + * 注意 :如果是三级联动的数据(省市区等),请参照 JsonDataActivity 类里面的写法。 + */ + pvHeighttions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { + @Override + public void onOptionsSelect(int options1, int options2, int options3, View v) { + //返回的分别是三个级别的选中位置 + if (heightLists.size() > 0) { + String occupation = heightLists.get(options1); + tv_height.setText(occupation); + height = heightLists.get(options1); + } + } + }) + .setTitleText("身高") + .setSelectOptions(0, 0)//默认选中项 + .setTitleBgColor(Color.WHITE) + .isRestoreItem(true)//切换时是否还原,设置默认选中第一项。 + .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 + .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() { + @Override + public void onOptionsSelectChanged(int options1, int options2, int options3) { + String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3; + //Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); + } + }) + .build(); + + if (heightLists.size() > 0) { + pvHeighttions.setPicker(heightLists);//二级选择器 + } + } + + public List tiZhongLists=new ArrayList<>(); + + private void initTiZhongOptionPicker() {//条件选择器初始化 + tiZhongLists.clear(); + for (int i = 40; i < 71; i++) { + tiZhongLists.add(i+"KG"); + } + /** + * 注意 :如果是三级联动的数据(省市区等),请参照 JsonDataActivity 类里面的写法。 + */ + pvTiZhongttions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { + @Override + public void onOptionsSelect(int options1, int options2, int options3, View v) { + //返回的分别是三个级别的选中位置 + if (tiZhongLists.size() > 0) { + String occupation = tiZhongLists.get(options1); + tv_tiz.setText(occupation); + tizhong = tiZhongLists.get(options1); + } + } + }) + .setTitleText("体重") + .setSelectOptions(0, 0)//默认选中项 + .setTitleBgColor(Color.WHITE) + .isRestoreItem(true)//切换时是否还原,设置默认选中第一项。 + .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 + .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() { + @Override + public void onOptionsSelectChanged(int options1, int options2, int options3) { + String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3; + //Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); + } + }) + .build(); + + if (tiZhongLists.size() > 0) { + pvTiZhongttions.setPicker(tiZhongLists);//二级选择器 + } + } + + private void initXingZuoOptionPicker() {//条件选择器初始化 + List xzuoLists=new ArrayList<>(); + xzuoLists.clear(); + xzuoLists.add("水瓶座"); + xzuoLists.add("双鱼座"); + xzuoLists.add("白羊座"); + xzuoLists.add("金牛座"); + xzuoLists.add("双子座"); + xzuoLists.add("巨蟹座"); + xzuoLists.add("狮子座"); + xzuoLists.add("处女座"); + xzuoLists.add("天秤座"); + xzuoLists.add("天蝎座"); + xzuoLists.add("射手座"); + xzuoLists.add("摩羯座"); + /** + * 注意 :如果是三级联动的数据(省市区等),请参照 JsonDataActivity 类里面的写法。 + */ + pvXingZuottions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { + @Override + public void onOptionsSelect(int options1, int options2, int options3, View v) { + //返回的分别是三个级别的选中位置 + if (xzuoLists.size() > 0) { + String occupation = xzuoLists.get(options1); + tv_xz.setText(occupation); + xingzuo = xzuoLists.get(options1); + } + } + }) + .setTitleText("星座") + .setSelectOptions(0, 0)//默认选中项 + .setTitleBgColor(Color.WHITE) + .isRestoreItem(true)//切换时是否还原,设置默认选中第一项。 + .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 + .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() { + @Override + public void onOptionsSelectChanged(int options1, int options2, int options3) { + String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3; + //Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); + } + }) + .build(); + + if (xzuoLists.size() > 0) { + pvXingZuottions.setPicker(xzuoLists);//二级选择器 + } + } + + private void initSanWeiOptionPicker() {//条件选择器初始化 + List xwLists=new ArrayList<>(); + List ywLists=new ArrayList<>(); + List twLists=new ArrayList<>(); + for (int i = 70; i < 106; i++) { + xwLists.add(i+""); + } + for (int i = 50; i < 81; i++) { + ywLists.add(i+""); + } + for (int i = 80; i < 100; i++) { + twLists.add(i+""); + } + + /** + * 注意 :如果是三级联动的数据(省市区等),请参照 JsonDataActivity 类里面的写法。 + */ + pvSanWeittions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { + @Override + public void onOptionsSelect(int options1, int options2, int options3, View v) { + //返回的分别是三个级别的选中位置 + if (xwLists.size() > 0 && ywLists.size()> 0 && twLists.size() > 0) { + String occupation = xwLists.get(options1); + tv_sanwei.setText(occupation + " " + ywLists.get(options2) +" " + twLists.get(options3)); + sanwwei = xwLists.get(options1) + " " + ywLists.get(options2) +" " + twLists.get(options3); + } + } + }) + .setTitleText("选择三围") + .setLabels("胸围","腰围","臀围") + .setSelectOptions(0, 0)//默认选中项 + .setTitleBgColor(Color.WHITE) + .isRestoreItem(true)//切换时是否还原,设置默认选中第一项。 + .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 + .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() { + @Override + public void onOptionsSelectChanged(int options1, int options2, int options3) { + String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3; + //Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); + } + }) + .build(); + + if (xwLists.size() > 0 && ywLists.size()> 0 && twLists.size() > 0) { + pvSanWeittions.setNPicker(xwLists,ywLists,twLists);//二级选择器 + } + } + + private void initGenderOptionPicker() {//条件选择器初始化 + List genderLists=new ArrayList<>(); + genderLists.clear(); + genderLists.add("男"); + genderLists.add("女"); + + /** + * 注意 :如果是三级联动的数据(省市区等),请参照 JsonDataActivity 类里面的写法。 + */ + pvGenderttions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() { + @Override + public void onOptionsSelect(int options1, int options2, int options3, View v) { + //返回的分别是三个级别的选中位置 + if (genderLists.size() > 0) { + String occupation = genderLists.get(options1); + tv_gender.setText(occupation); + gender = genderLists.get(options1); + } + } + }) + .setTitleText("性别") + .setSelectOptions(0, 0)//默认选中项 + .setTitleBgColor(Color.WHITE) + .isRestoreItem(true)//切换时是否还原,设置默认选中第一项。 + .isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。 + .setOptionsSelectChangeListener(new OnOptionsSelectChangeListener() { + @Override + public void onOptionsSelectChanged(int options1, int options2, int options3) { + String str = "options1: " + options1 + "\noptions2: " + options2 + "\noptions3: " + options3; + //Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); + } + }) + .build(); + + if (genderLists.size() > 0) { + pvGenderttions.setPicker(genderLists);//二级选择器 + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/UploadPhotoCoverActivity.java b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/UploadPhotoCoverActivity.java new file mode 100644 index 0000000..7e57ed3 --- /dev/null +++ b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/UploadPhotoCoverActivity.java @@ -0,0 +1,167 @@ +package com.xuebiping.bolizhuzi.view.settings; + +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import android.Manifest; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.media.ThumbnailUtils; +import android.net.Uri; +import android.os.Bundle; +import android.provider.MediaStore; +import android.util.Log; +import android.view.View; +import android.widget.Button; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.fengliyan.uikit.photopicker.MultiImageSelector; +import com.fengliyan.uikit.toast.MaleToast; +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.xuebiping.bolizhuzi.R; +import com.xuebiping.bolizhuzi.controller.constant.ConstUrl; +import com.xuebiping.bolizhuzi.controller.settings.manager.UserAvatarManager; +import com.xuebiping.bolizhuzi.im.uikit.common.util.file.AttachmentStore; +import com.xuebiping.bolizhuzi.im.uikit.common.util.file.FileUtil; +import com.xuebiping.bolizhuzi.im.uikit.common.util.storage.StorageType; +import com.xuebiping.bolizhuzi.im.uikit.common.util.storage.StorageUtil; +import com.xuebiping.bolizhuzi.im.uikit.common.util.string.MD5; +import com.xuebiping.bolizhuzi.utils.PermissionUtil; +import com.xuebiping.bolizhuzi.utils.camera2.BitmapUtils; +import com.xuebiping.bolizhuzi.view.base.BaseActivity; +import com.xuebiping.bolizhuzi.view.main.dialog.CustomAlertDialog; +import com.xuebiping.bolizhuzi.view.main.dialog.PermissionDialog; +import com.xuebiping.bolizhuzi.view.settings.video.VideoSelectActivity; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import kotlin.Unit; +import kotlin.jvm.functions.Function1; +import kotlin.jvm.functions.Function2; + +public class UploadPhotoCoverActivity extends BaseActivity implements UserAvatarManager.UserImgListener { + + private SimpleDraweeView sd_cover; + private Button submit_button; + + private String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_PHONE_STATE}; + private PermissionDialog permissionDialog; + + private boolean isChooseAvatar = false; + boolean isChooseVideo = false; + + private MultiImageSelector mSelector; + private UserAvatarManager mManager; + + String avatarPath; + String avatarUrl; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_upload_photo_cover); + + setTitleName("上传封面图"); + + mSelector = MultiImageSelector.create().multi().count(1); + + mManager = new UserAvatarManager(this); + sd_cover = findViewById(R.id.sd_cover); + submit_button = findViewById(R.id.submit_button); + + sd_cover.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + checkPermission(1); + } + }); + + submit_button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + //TODO 做上传操作并返回前个界面 + } + }); + + } + + private void checkPermission(int type) { + permissionDialog = new PermissionDialog(UploadPhotoCoverActivity.this, permissions); + permissionDialog.show(); + XXPermissions.with(UploadPhotoCoverActivity.this) + .permission(permissions) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + startImageSelector(type == 1); + } + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + CustomAlertDialog customAlertDialog = new CustomAlertDialog(UploadPhotoCoverActivity.this); + customAlertDialog.setTitle("芊颜需要开启读写权限,以便查看本地图库内容"); + customAlertDialog.hideContent(true); + customAlertDialog.setRightBtnText("去开启"); + customAlertDialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(UploadPhotoCoverActivity.this); + } + }); + customAlertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + customAlertDialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + } + + public void startImageSelector(boolean isChooseAvatar) { + isChooseVideo = false; + this.isChooseAvatar = isChooseAvatar; + mSelector.multi(); + mSelector.count(1); + mSelector.start(this, 200); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { +// if (isChooseVideo) { +// helper.onGetLocalVideoResult(data); +// return; +// } + super.onActivityResult(requestCode, resultCode, data); + if (mManager != null) { + mManager.onActivityResult(requestCode, resultCode, data); + } + if (requestCode == 200 && resultCode == RESULT_OK) { + List albumList = data.getStringArrayListExtra(MultiImageSelector.EXTRA_RESULT); + String s = "file://" + albumList.get(0); + mManager.whoStartCropWithUi(Uri.parse(s)); + } + } + + @Override + public void getUserImg(@Nullable @org.jetbrains.annotations.Nullable String path) { + if (isChooseAvatar) { + this.avatarPath = path; + avatarUrl = null; + sd_cover.setImageURI("file://" + this.avatarPath); + return; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/VideoRenzhengActivity.java b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/VideoRenzhengActivity.java new file mode 100644 index 0000000..d8e1f18 --- /dev/null +++ b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/VideoRenzhengActivity.java @@ -0,0 +1,270 @@ +package com.xuebiping.bolizhuzi.view.settings; + +import android.Manifest; +import android.content.DialogInterface; +import android.hardware.Camera; +import android.os.Bundle; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.hjq.permissions.OnPermissionCallback; +import com.hjq.permissions.XXPermissions; +import com.xuebiping.bolizhuzi.R; +import com.xuebiping.bolizhuzi.utils.PermissionUtil; +import com.xuebiping.bolizhuzi.view.base.BaseActivity; +import com.xuebiping.bolizhuzi.view.main.dialog.CustomAlertDialog; +import com.xuebiping.bolizhuzi.view.main.dialog.PermissionDialog; +import com.xuebiping.bolizhuzi.view.settings.video.CameraPreview; + +import java.io.File; +import java.util.List; +import java.util.Locale; + +public class VideoRenzhengActivity extends BaseActivity implements CameraPreview.RecordingTimerListener { + + private TextView tv_rz_code; + private TextView tv_time; + private RelativeLayout rl_take_video; + private RelativeLayout rl_zanti_video; + private ImageView iv_wanc; + private ImageView iv_fanz; + private ImageView iv_cz; + + private String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_PHONE_STATE, + Manifest.permission.CAMERA, + Manifest.permission.RECORD_AUDIO + }; + private PermissionDialog permissionDialog; + private Camera camera; + private FrameLayout previewLayout; + private CameraPreview cameraPreview; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_video_renzheng); + + setTitleName("视频认证"); + + initView(); + + } + + private void initView() { + tv_rz_code = findViewById(R.id.tv_rz_code); + tv_time = findViewById(R.id.tv_time); + rl_take_video = findViewById(R.id.rl_take_video); + rl_zanti_video = findViewById(R.id.rl_zanti_video); + iv_wanc = findViewById(R.id.iv_wanc); + iv_fanz = findViewById(R.id.iv_fanz); + iv_cz = findViewById(R.id.iv_cz); + + previewLayout = findViewById(R.id.frame_layout); + + checkPermission(); + + iv_fanz.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + } + }); + + onViewClick(); + } + + private void onViewClick() { + rl_take_video.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + /*rl_take_video.setVisibility(View.INVISIBLE); + rl_take_video.setEnabled(false); + rl_zanti_video.setVisibility(View.VISIBLE); + rl_zanti_video.setEnabled(true);*/ + toggleRecording(); + } + }); + + rl_zanti_video.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + /*rl_take_video.setVisibility(View.VISIBLE); + rl_take_video.setEnabled(true); + rl_zanti_video.setVisibility(View.INVISIBLE); + rl_zanti_video.setEnabled(false);*/ + toggleRecording(); + + iv_cz.setVisibility(View.VISIBLE); + iv_cz.setEnabled(true); + + } + }); + + iv_wanc.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + File outputFile = cameraPreview.getOutputFile(); //获取到录制输出文件 + //TODO 提交视频 + } + }); + + iv_cz.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + iv_cz.setVisibility(View.INVISIBLE); + iv_cz.setEnabled(false); + iv_wanc.setVisibility(View.INVISIBLE); + iv_wanc.setEnabled(false); + tv_time.setText("00:00"); + initializeCamera(); + } + }); + iv_fanz.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + switchCamera(); + } + }); + } + + private void checkPermission() { + permissionDialog = new PermissionDialog(VideoRenzhengActivity.this, permissions); + permissionDialog.show(); + XXPermissions.with(VideoRenzhengActivity.this) + .permission(permissions) + .request(new OnPermissionCallback() { + @Override + public void onGranted(List permissions, boolean all) { + if (all) { + permissionDialog.dismiss(); + initializeCamera(); + } + } + + @Override + public void onDenied(List permissions, boolean never) { + if (never) { + CustomAlertDialog customAlertDialog = new CustomAlertDialog(VideoRenzhengActivity.this); + customAlertDialog.setTitle("芊颜需要开启读写权限,以便查看本地图库内容"); + customAlertDialog.hideContent(true); + customAlertDialog.setRightBtnText("去开启"); + customAlertDialog.setRightOnClickListener(new CustomAlertDialog.OnDialogRightClickListener() { + @Override + public void rightClick() { + PermissionUtil.jumpPermissionPage(VideoRenzhengActivity.this); + } + }); + customAlertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + permissionDialog.dismiss(); + } + }); + customAlertDialog.show(); + } else { + permissionDialog.dismiss(); + } + } + }); + } + + private void initializeCamera() { + // 创建CameraPreview + if(cameraPreview == null){ + cameraPreview = new CameraPreview(this); + } + cameraPreview.setRecordingTimerListener(this); + + // 添加到布局 + previewLayout.removeAllViews(); + previewLayout.addView(cameraPreview); + + // 检查是否有摄像头可用 + int cameraCount = cameraPreview.getCameraCount(); + if (cameraCount == 0) { + Toast.makeText(this, "没有可用的摄像头", Toast.LENGTH_SHORT).show(); + finish(); + return; + } + + // 打开前置摄像头 + cameraPreview.openCamera(Camera.CameraInfo.CAMERA_FACING_FRONT); + + // 检查是否有前置摄像头 + boolean hasBackCamera = cameraPreview.hasBackCamera(); + iv_fanz.setVisibility(hasBackCamera ? View.VISIBLE : View.INVISIBLE); + iv_fanz.setEnabled(hasBackCamera ? true : false); + + rl_take_video.setVisibility(View.VISIBLE); + rl_take_video.setEnabled(true); + } + + private void toggleRecording() { + if (cameraPreview == null) return; + + if (!cameraPreview.isRecording()) { + // 开始录制 + if (cameraPreview.startRecording()) { + rl_zanti_video.setVisibility(View.VISIBLE); + rl_zanti_video.setEnabled(true); + rl_take_video.setVisibility(View.INVISIBLE); + rl_take_video.setEnabled(false); + iv_fanz.setVisibility(View.INVISIBLE); + iv_fanz.setEnabled(false); + Toast.makeText(this, "录制开始", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, "开始录制失败", Toast.LENGTH_SHORT).show(); + } + } else { + // 停止录制 + if (cameraPreview.stopRecording()) { + rl_zanti_video.setVisibility(View.INVISIBLE); + rl_zanti_video.setEnabled(false); + rl_take_video.setVisibility(View.INVISIBLE); + rl_take_video.setEnabled(false); + iv_cz.setVisibility(View.VISIBLE); + iv_cz.setEnabled(true); + iv_wanc.setVisibility(View.VISIBLE); + iv_wanc.setEnabled(true); + Toast.makeText(this, "录制已保存", Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(this, "停止录制失败", Toast.LENGTH_SHORT).show(); + } + } + } + + private void switchCamera() { + if (cameraPreview != null) { + cameraPreview.switchCamera(); + } + } + + @Override + public void onTimerUpdate(int minutes, int seconds) { + String timeText = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds); + runOnUiThread(() -> tv_time.setText(timeText)); + } + + @Override + protected void onPause() { + super.onPause(); + if (cameraPreview != null && cameraPreview.isRecording()) { + cameraPreview.stopRecording(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (cameraPreview != null) { + cameraPreview.setRecordingTimerListener(null); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/video/CameraPreview.java b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/video/CameraPreview.java new file mode 100644 index 0000000..2b7a577 --- /dev/null +++ b/app/src/main/java/com/xuebiping/bolizhuzi/view/settings/video/CameraPreview.java @@ -0,0 +1,438 @@ +package com.xuebiping.bolizhuzi.view.settings.video; + +import android.content.Context; +import android.hardware.Camera; +import android.media.CamcorderProfile; +import android.media.MediaRecorder; +import android.os.Handler; +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { + private static final String TAG = "CameraPreview"; + private SurfaceHolder holder; + private Camera camera; + private MediaRecorder mediaRecorder; + private boolean isRecording = false; + private File outputFile; + private int currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK; + private RecordingTimerListener recordingTimerListener; + private Handler timerHandler = new Handler(); + private int recordingSeconds = 0; + private Runnable timerRunnable = new Runnable() { + @Override + public void run() { + recordingSeconds++; + if (recordingTimerListener != null) { + int minutes = recordingSeconds / 60; + int seconds = recordingSeconds % 60; + recordingTimerListener.onTimerUpdate(minutes, seconds); + } + timerHandler.postDelayed(this, 1000); + } + }; + + public interface RecordingTimerListener { + void onTimerUpdate(int minutes, int seconds); + } + + public CameraPreview(Context context) { + super(context); + holder = getHolder(); + holder.addCallback(this); + holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); + } + + public void openCamera(int cameraId) { + releaseCamera(); + try { + camera = Camera.open(cameraId); + currentCameraId = cameraId; + setupCamera(); + if (holder.getSurface() != null) { + startPreview(); + } + } catch (Exception e) { + Log.e(TAG, "Error opening camera: " + e.getMessage()); + } + } + + private void setupCamera() { + if (camera == null) return; + + try { + Camera.Parameters parameters = camera.getParameters(); + + // 设置自动对焦 + List focusModes = parameters.getSupportedFocusModes(); + if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { + parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + + // 设置最佳预览尺寸 + Camera.Size optimalSize = getOptimalPreviewSize( + parameters.getSupportedPreviewSizes(), + getWidth(), + getHeight() + ); + if (optimalSize != null) { + parameters.setPreviewSize(optimalSize.width, optimalSize.height); + } + + // 设置相机参数 + camera.setParameters(parameters); + + // 设置预览方向 + setCameraDisplayOrientation(); + + } catch (Exception e) { + Log.e(TAG, "Error setting camera parameters: " + e.getMessage()); + } + } + + private void setCameraDisplayOrientation() { + if (camera == null) return; + + Camera.CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(currentCameraId, info); + + int rotation = 0; // 假设为竖屏 + + int degrees = 0; + switch (rotation) { + case 0: + degrees = 0; + break; + case 90: + degrees = 90; + break; + case 180: + degrees = 180; + break; + case 270: + degrees = 270; + break; + } + + int result; + if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + result = (info.orientation + degrees) % 360; + result = (360 - result) % 360; // 补偿镜像 + } else { // 后置摄像头 + result = (info.orientation - degrees + 360) % 360; + } + camera.setDisplayOrientation(result); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + if (camera != null) { + startPreview(); + } + } + + private void startPreview() { + if (camera == null) return; + + try { + camera.setPreviewDisplay(holder); + camera.startPreview(); + } catch (IOException e) { + Log.e(TAG, "Error starting camera preview: " + e.getMessage()); + } + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + if (holder.getSurface() == null || camera == null) { + return; + } + + try { + camera.stopPreview(); + } catch (Exception e) { + // 忽略异常 + } + + setupCamera(); + startPreview(); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + releaseCamera(); + } + + // 翻转摄像头 + public void switchCamera() { + int newCameraId = (currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) ? + Camera.CameraInfo.CAMERA_FACING_FRONT : + Camera.CameraInfo.CAMERA_FACING_BACK; + openCamera(newCameraId); + } + + public int getCurrentCameraId() { + return currentCameraId; + } + + // 开始录制 + public boolean startRecording() { + if (isRecording) { + Log.w(TAG, "Already recording"); + return false; + } + + if (camera == null) { + Log.e(TAG, "Camera is not opened"); + return false; + } + + try { + // 解锁相机用于MediaRecorder + camera.unlock(); + + // 创建MediaRecorder + mediaRecorder = new MediaRecorder(); + + // 设置音频源 + mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); + + // 设置视频源 + mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); + + // 设置配置文件 + CamcorderProfile profile = CamcorderProfile.get( + currentCameraId, + CamcorderProfile.QUALITY_HIGH + ); + mediaRecorder.setProfile(profile); + + // 设置输出文件 + outputFile = getOutputMediaFile(); + if (outputFile == null) { + Log.e(TAG, "Cannot create output file"); + return false; + } + mediaRecorder.setOutputFile(outputFile.getAbsolutePath()); + + // 设置预览 + mediaRecorder.setPreviewDisplay(holder.getSurface()); + + // 设置视频方向 + mediaRecorder.setOrientationHint(getRecordingOrientation()); + + // 准备录制 + mediaRecorder.prepare(); + + // 开始录制 + mediaRecorder.start(); + + isRecording = true; + recordingSeconds = 0; + timerHandler.postDelayed(timerRunnable, 1000); + + Log.d(TAG, "Recording started: " + outputFile.getAbsolutePath()); + return true; + + } catch (Exception e) { + Log.e(TAG, "Error starting recording: " + e.getMessage()); + e.printStackTrace(); + releaseMediaRecorder(); + relockCamera(); + return false; + } + } + + private int getRecordingOrientation() { + Camera.CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(currentCameraId, info); + + int rotation = 0; // 假设竖屏 + int degrees = 0; + switch (rotation) { + case 0: degrees = 0; break; + case 90: degrees = 90; break; + case 180: degrees = 180; break; + case 270: degrees = 270; break; + } + + int result; + if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + result = (info.orientation + degrees) % 360; + result = (360 - result) % 360; + } else { + result = (info.orientation - degrees + 360) % 360; + } + return result; + } + + // 停止录制 + public boolean stopRecording() { + if (!isRecording || mediaRecorder == null) { + return false; + } + + try { + mediaRecorder.stop(); + mediaRecorder.reset(); + isRecording = false; + + // 停止计时器 + timerHandler.removeCallbacks(timerRunnable); + + Log.d(TAG, "Recording stopped. File saved: " + outputFile.getAbsolutePath()); + return true; + + } catch (Exception e) { + Log.e(TAG, "Error stopping recording: " + e.getMessage()); + return false; + } finally { + releaseMediaRecorder(); + relockCamera(); + } + } + + private void relockCamera() { + if (camera != null) { + try { + camera.lock(); + } catch (Exception e) { + Log.e(TAG, "Error relocking camera: " + e.getMessage()); + } + } + } + + // 释放MediaRecorder资源 + private void releaseMediaRecorder() { + if (mediaRecorder != null) { + try { + mediaRecorder.reset(); + mediaRecorder.release(); + } catch (Exception e) { + Log.e(TAG, "Error releasing MediaRecorder: " + e.getMessage()); + } + mediaRecorder = null; + } + } + + // 释放相机资源 + private void releaseCamera() { + if (camera != null) { + try { + camera.stopPreview(); + camera.release(); + } catch (Exception e) { + Log.e(TAG, "Error releasing camera: " + e.getMessage()); + } + camera = null; + } + } + + // 获取最佳预览尺寸 + private Camera.Size getOptimalPreviewSize(List sizes, int w, int h) { + if (sizes == null || sizes.isEmpty()) return null; + + final double ASPECT_TOLERANCE = 0.1; + double targetRatio = (double) h / w; + + Camera.Size optimalSize = null; + double minDiff = Double.MAX_VALUE; + + for (Camera.Size size : sizes) { + double ratio = (double) size.width / size.height; + if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; + if (Math.abs(size.height - h) < minDiff) { + optimalSize = size; + minDiff = Math.abs(size.height - h); + } + } + + if (optimalSize == null) { + minDiff = Double.MAX_VALUE; + for (Camera.Size size : sizes) { + if (Math.abs(size.height - h) < minDiff) { + optimalSize = size; + minDiff = Math.abs(size.height - h); + } + } + } + + return optimalSize; + } + + // 创建输出文件 + private File getOutputMediaFile() { + File mediaStorageDir = new File( + android.os.Environment.getExternalStoragePublicDirectory( + android.os.Environment.DIRECTORY_MOVIES), + "MyCameraApp" + ); + + if (!mediaStorageDir.exists()) { + if (!mediaStorageDir.mkdirs()) { + Log.e(TAG, "Failed to create directory: " + mediaStorageDir.getAbsolutePath()); + return null; + } + } + + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); + return new File(mediaStorageDir.getPath() + File.separator + "VID_" + timeStamp + ".mp4"); + } + + public void setRecordingTimerListener(RecordingTimerListener listener) { + this.recordingTimerListener = listener; + } + + public boolean isRecording() { + return isRecording; + } + + public File getOutputFile() { + return outputFile; + } + + public int getCameraCount() { + return Camera.getNumberOfCameras(); + } + + public boolean hasFrontCamera() { + int numberOfCameras = Camera.getNumberOfCameras(); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int i = 0; i < numberOfCameras; i++) { + Camera.getCameraInfo(i, cameraInfo); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + return true; + } + } + return false; + } + + public boolean hasBackCamera() { + int numberOfCameras = Camera.getNumberOfCameras(); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int i = 0; i < numberOfCameras; i++) { + Camera.getCameraInfo(i, cameraInfo); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { + return true; + } + } + return false; + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + timerHandler.removeCallbacks(timerRunnable); + stopRecording(); + releaseMediaRecorder(); + releaseCamera(); + } +} diff --git a/app/src/main/res/drawable-xhdpi/cover_1080.png b/app/src/main/res/drawable-xhdpi/cover_1080.png index 0cc6105..38eedc4 100644 Binary files a/app/src/main/res/drawable-xhdpi/cover_1080.png and b/app/src/main/res/drawable-xhdpi/cover_1080.png differ diff --git a/app/src/main/res/drawable-xxhdpi/cover_1080.png b/app/src/main/res/drawable-xxhdpi/cover_1080.png deleted file mode 100644 index cba20a6..0000000 Binary files a/app/src/main/res/drawable-xxhdpi/cover_1080.png and /dev/null differ diff --git a/app/src/main/res/drawable/shape_bg_7.xml b/app/src/main/res/drawable/shape_bg_7.xml new file mode 100644 index 0000000..eac094f --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_7.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_invitation_bg.xml b/app/src/main/res/drawable/shape_invitation_bg.xml index 877a809..8c4464f 100644 --- a/app/src/main/res/drawable/shape_invitation_bg.xml +++ b/app/src/main/res/drawable/shape_invitation_bg.xml @@ -4,6 +4,6 @@ + android:endColor="#F9DFD8" + android:startColor="#F9DFD8" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_cover.xml b/app/src/main/res/layout/activity_cover.xml index e6d2642..d3a7a3b 100644 --- a/app/src/main/res/layout/activity_cover.xml +++ b/app/src/main/res/layout/activity_cover.xml @@ -5,17 +5,27 @@ xmlns:tools="http://schemas.android.com/tools" tools:viewBindingIgnore="true" android:background="@android:color/white"> - + + - + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_invitation.xml b/app/src/main/res/layout/activity_invitation.xml index ce89895..5e285a8 100644 --- a/app/src/main/res/layout/activity_invitation.xml +++ b/app/src/main/res/layout/activity_invitation.xml @@ -54,6 +54,13 @@ android:scaleType="fitXY" android:src="@mipmap/invitaion_bg" /> + + @@ -369,7 +376,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="邀请数据" - android:textColor="#ffffffff" + android:textColor="#666666" android:textSize="12dp" /> @@ -381,7 +388,7 @@ android:layout_marginTop="20dp" android:layout_marginRight="16dp" android:layout_marginBottom="10dp" - app:rv_backgroundColor="#FFFBEC" + app:rv_backgroundColor="#FCF3EA" app:rv_cornerRadius="12dp"> + + + + + + + + +