6 Commits

30 changed files with 281 additions and 41 deletions

View File

@@ -3,13 +3,16 @@ package com.nnbc123.app.avroom.fragment
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import android.view.*
@@ -115,6 +118,7 @@ import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder
import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage
import com.nnbc123.app.avroom.hour_rank.RoomHourRankWidget
import com.nnbc123.app.ui.widget.dialog.CommonTipDialog
import com.orhanobut.logger.Logger
import com.tbruyelle.rxpermissions2.RxPermissions
import com.trello.rxlifecycle3.android.FragmentEvent
@@ -1146,11 +1150,37 @@ open class BaseRoomFragment<V : IBaseRoomView?, P : BaseRoomPresenter<V>?> :
if (result) {
mvpPresenter?.upMicroPhone(micPosition, currentUid, b)
} else {
toast("请给予麦克风权限后再试!")
showDeniedTips(
requireContext(),
ResUtil.getString(R.string.permission_denied_tips_mic)
)
}
}, { throwable: Throwable? -> toast("发生一些异常,请稍后重试!") })
}
private fun showDeniedTips(context: Context, message: String) {
CommonTipDialog(context).apply {
setTipMsg(message)
setOkText("去设置")
setOnActionListener(
object : CommonTipDialog.OnActionListener {
override fun onOk() {
//同意跳到应用详情页面
val packageUri =
Uri.parse("package:${context.packageName}")
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
packageUri
)
(context as? Activity)?.startActivityForResult(
intent, 0
)
}
}
)
}.show()
}
/**
* 是否有麦克风权限
*

View File

@@ -34,6 +34,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import androidx.annotation.ColorInt;
import androidx.core.util.Consumer;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@@ -821,6 +822,17 @@ public abstract class BaseActivity extends RxAppCompatActivity
}, Throwable::printStackTrace);
}
@SuppressLint("CheckResult")
public void checkPermission(Consumer<Boolean> consumer, String... mPerms) {
rxPermissions.request(mPerms)
.subscribe(aBoolean -> {
if (consumer != null) {
consumer.accept(aBoolean);
}
}, Throwable::printStackTrace);
}
@SuppressLint("CheckResult")
public Observable<Boolean> checkPermission(String... mPerms) {
return rxPermissions.request(mPerms);

View File

@@ -21,6 +21,11 @@ import com.qiyukf.unicorn.api.YSFOptions;
import com.qiyukf.unicorn.api.YSFUserInfo;
import com.qiyukf.unicorn.api.customization.input.ActionPanelOptions;
import com.qiyukf.unicorn.api.customization.input.InputPanelOptions;
import com.qiyukf.unicorn.api.event.EventCallback;
import com.qiyukf.unicorn.api.event.EventProcessFactory;
import com.qiyukf.unicorn.api.event.SDKEvents;
import com.qiyukf.unicorn.api.event.UnicornEventBase;
import com.qiyukf.unicorn.api.event.entry.RequestPermissionEventEntry;
import com.soundcloud.android.crop.UriUtil;
import java.util.ArrayList;
@@ -109,7 +114,17 @@ public class CustomerServerHelper {
options.uiCustomization.leftAvatar = uri.toString();
options.uiCustomization.titleCenter = true;
options.sdkEvents = new SDKEvents();
options.sdkEvents.eventProcessFactory = new EventProcessFactory() {
@Override
public UnicornEventBase eventOf(int i) {
if (i == 5) {
return new RequestPermissionEvent();
} else {
return null;
}
}
};
// appKey 可以在七鱼管理系统->设置->App 接入 页面找到
Unicorn.init(context, XChatConstants.QI_YU_KF_KEY, options, new GlideImageLoader(context));
Unicorn.initSdk();
@@ -133,5 +148,4 @@ public class CustomerServerHelper {
Unicorn.logout();
isInit = false;
}
}

View File

@@ -0,0 +1,78 @@
package com.nnbc123.app.qiyukefu
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import com.nnbc123.app.R
import com.nnbc123.app.ui.widget.dialog.CommonTipDialog
import com.nnbc123.library.utils.ResUtil
import com.qiyukf.unicorn.api.event.EventCallback
import com.qiyukf.unicorn.api.event.UnicornEventBase
import com.qiyukf.unicorn.api.event.entry.RequestPermissionEventEntry
/**
* Created by Max on 2024/1/4 11:10
* Desc:
**/
class RequestPermissionEvent : UnicornEventBase<RequestPermissionEventEntry> {
override fun onEvent(
p0: RequestPermissionEventEntry?,
p1: Context?,
p2: EventCallback<RequestPermissionEventEntry>?
) {
p2?.onNotPorcessEvent()
}
override fun onDenyEvent(p0: Context?, p1: RequestPermissionEventEntry?): Boolean {
if (p0 == null) {
return super.onDenyEvent(p0, p1)
}
when (p1?.scenesType) {
RequestPermissionEventEntry.SCENES_TAKE_AUDIO -> {
showDeniedTips(p0, ResUtil.getString(R.string.permission_denied_tips_mic))
return true
}
RequestPermissionEventEntry.SCENES_SELECT_MEDIA,
RequestPermissionEventEntry.SCENES_TAKE_VIDEO,
RequestPermissionEventEntry.SCENES_SAVE_IMAGE,
RequestPermissionEventEntry.SCENES_SAVE_VIDEO,
RequestPermissionEventEntry.SCENES_SELECT_VIDEO,
RequestPermissionEventEntry.SCENES_SELECT_FILE,
RequestPermissionEventEntry.SCENES_SELECT_IMAGE,
RequestPermissionEventEntry.SCENES_TAKE_PHOTO,
RequestPermissionEventEntry.SCENES_VIDEO_CHAT -> {
showDeniedTips(p0, ResUtil.getString(R.string.permission_denied_tips_image))
return true
}
else -> {
return super.onDenyEvent(p0, p1)
}
}
}
private fun showDeniedTips(context: Context, message: String) {
CommonTipDialog(context).apply {
setTipMsg(message)
setOkText("去设置")
setOnActionListener(
object : CommonTipDialog.OnActionListener {
override fun onOk() {
//同意跳到应用详情页面
val packageUri =
Uri.parse("package:${context.packageName}")
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
packageUri
)
(context as? Activity)?.startActivityForResult(
intent, 0
)
}
}
)
}.show()
}
}

View File

@@ -7,12 +7,12 @@ import android.graphics.Color;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -20,6 +20,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.util.Consumer;
import androidx.lifecycle.Lifecycle;
import com.netease.nim.uikit.api.UIKitOptions;
@@ -59,6 +60,7 @@ import com.nnbc123.app.ui.im.MessageListPanelEx;
import com.nnbc123.app.ui.im.chat.MVHChatterBoxStart;
import com.nnbc123.app.ui.im.model.IMCustomModel;
import com.nnbc123.app.ui.webview.CommonWebViewActivity;
import com.nnbc123.app.ui.widget.dialog.CommonTipDialog;
import com.nnbc123.app.utils.PushMessageHandler;
import com.nnbc123.core.UriProvider;
import com.nnbc123.core.auth.AuthModel;
@@ -70,6 +72,7 @@ import com.nnbc123.core.im.custom.bean.ImTipAttachment;
import com.nnbc123.core.room.event.MessageSizeEvent;
import com.nnbc123.core.statistic.StatisticManager;
import com.nnbc123.core.statistic.protocol.StatisticsProtocol;
import com.nnbc123.library.utils.ResUtil;
import com.nnbc123.library.utils.SingleToastUtil;
import com.nnbc123.library.utils.config.BasicConfig;
import com.tbruyelle.rxpermissions2.RxPermissions;
@@ -87,7 +90,6 @@ import java.util.Map;
import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
/**
@@ -228,7 +230,7 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi
IMMessage anchor = (IMMessage) getArguments().getSerializable(Extras.EXTRA_ANCHOR);
customization = (SessionCustomization) getArguments().getSerializable(Extras.EXTRA_CUSTOMIZATION);
Container container = new Container(getActivity(), sessionId, sessionType, this);
Container container = new Container(getActivity(), sessionId, sessionType, this,this::requestPermission);
if (messageListPanel == null) {
messageListPanel = new MessageListPanelEx(container, rootView, anchor, false, false);
@@ -275,13 +277,10 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi
GreetPresenter greetPresenter = new GreetPresenter(sessionId);
if (greetPresenter.isCanSendGreet()) {
greetDisposable = greetPresenter.greetMsgGetOne(AuthModel.get().getCurrentUid(), toUid)
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
if (!TextUtils.isEmpty(s)) {
sendMessage(MessageBuilder.createTextMessage(container.account,
container.sessionType, s));
}
.subscribe(s -> {
if (!TextUtils.isEmpty(s)) {
sendMessage(MessageBuilder.createTextMessage(container.account,
container.sessionType, s));
}
});
}
@@ -322,6 +321,18 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi
}
private void requestPermission(Consumer<Boolean> consumer, String deniedTips, String... perms) {
Disposable disposable = rxPermissions.request(perms).subscribe(aBoolean -> {
if (!aBoolean) {
showPermissionDeniedTipsDialog(deniedTips);
}
if (consumer != null) {
consumer.accept(aBoolean);
}
}, Throwable::printStackTrace);
compositeDisposable.add(disposable);
}
/**
* ********************** implements ModuleProxy *********************
*/
@@ -612,11 +623,34 @@ public class MessageFragment extends TFragment implements ModuleProxy, MessageLi
if (result) {
event.getSuccess().accept(result);
} else {
SingleToastUtil.showToast(getString(R.string.ask_again));
showPermissionDeniedTipsDialog(ResUtil.getString(R.string.permission_denied_tips_mic));
}
});
}
private void showPermissionDeniedTipsDialog(String message){
CommonTipDialog mPrivacyDialog = new CommonTipDialog(getContext());
mPrivacyDialog.setTipMsg(message);
mPrivacyDialog.setOkText("去设置");
mPrivacyDialog.setOnActionListener(
new CommonTipDialog.OnActionListener() {
@Override
public void onOk() {
//同意跳到应用详情页面
Uri packageUri = Uri.parse("package:" + getContext().getPackageName());
Intent intent = new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
packageUri
);
startActivityForResult(
intent, 0
);
}
}
);
mPrivacyDialog.show();
}
@Subscribe(threadMode = ThreadMode.MAIN)
@SuppressLint("CheckResult")
public void onNimImageActionEvent(NimImageActionEvent event) {

View File

@@ -97,7 +97,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/dp_18"
android:text="玩伴推荐"
android:text="玩伴"
android:textColor="#2B2D33"
android:textSize="@dimen/dp_16"
android:textStyle="bold"

View File

@@ -147,7 +147,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_19"
android:layout_marginTop="@dimen/dp_12"
android:text="热门推荐"
android:text="热门"
android:textColor="#2B2D33"
android:textSize="@dimen/dp_16"
android:textStyle="bold"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -987,5 +987,6 @@
<string name="gang_up_invite">开黑邀请</string>
<string name="Black_duration">开黑时长(局):</string>
<string name="diamond_inning">%d钻/局</string>
<string name="permission_denied_tips_mic">为了实现连麦及语音输入等功能,请您允许应用向您获取“麦克风”权限</string>
<string name="permission_denied_tips_image">访问你的本地内容,以能正常使用图片上传、视频发送等应用功能</string>
</resources>

View File

@@ -16,7 +16,6 @@
</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:statusBarColor" tools:targetApi="lollipop">@color/transparent</item>
</style>

View File

@@ -3,11 +3,13 @@ package com.nnbc123.app.community.publish.view;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -21,8 +23,11 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import com.google.android.flexbox.FlexboxLayout;
import com.hjq.toast.ToastUtils;
import com.netease.nim.uikit.StatusBarUtil;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.nnbc123.app.ui.widget.dialog.CommonTipDialog;
import com.nnbc123.library.utils.ResUtil;
import com.trello.rxlifecycle3.android.ActivityEvent;
import com.nnbc123.app.R;
import com.nnbc123.app.base.BaseMvpActivity;
@@ -191,26 +196,29 @@ public class PublishActivity extends BaseMvpActivity<IPublishView, PublishPresen
imageAdapter.setOnItemClickListener((adapter, view, position) -> {
PublishItem item = imageShowList.get(position);
if (item.isAddItem()) {
checkPermission(() -> {
CaptureStrategy captureStrategy = new CaptureStrategy(true, context.getPackageName() + ".fileprovider",
BasicConfig.INSTANCE.getImageDir().getAbsolutePath());
int maxCanSelect = 9 - uploadList.size();
Matisse.from(PublishActivity.this)
.choose(MimeType.ofImage())
.showSingleMediaType(true)
.capture(true)
.spanCount(4)
.captureStrategy(captureStrategy)
.countable(true)
.maxSelectable(maxCanSelect)
.originalEnable(false)
.maxOriginalSize(10)
.imageEngine(new Glide4Engine())
.setType(2)
.setOriginalImagee(isOriginalImage)
.forResult(ConstantValue.CODE_CHOOSE_PHOTO);
}, R.string.ask_storage, Manifest.permission.READ_EXTERNAL_STORAGE);
checkPermission((aBoolean) -> {
if (aBoolean) {
CaptureStrategy captureStrategy = new CaptureStrategy(true, context.getPackageName() + ".fileprovider",
BasicConfig.INSTANCE.getImageDir().getAbsolutePath());
int maxCanSelect = 9 - uploadList.size();
Matisse.from(PublishActivity.this)
.choose(MimeType.ofImage())
.showSingleMediaType(true)
.capture(true)
.spanCount(4)
.captureStrategy(captureStrategy)
.countable(true)
.maxSelectable(maxCanSelect)
.originalEnable(false)
.maxOriginalSize(10)
.imageEngine(new Glide4Engine())
.setType(2)
.setOriginalImagee(isOriginalImage)
.forResult(ConstantValue.CODE_CHOOSE_PHOTO);
} else {
showPermissionDeniedDialog();
}
}, Manifest.permission.READ_EXTERNAL_STORAGE);
} else {
BigPhotoActivity.startCanDelete(PublishActivity.this, (ArrayList<CustomItem>) uploadList,
position, new PagerOption().setDelete(true));
@@ -230,6 +238,29 @@ public class PublishActivity extends BaseMvpActivity<IPublishView, PublishPresen
updateImagesData();
}
private void showPermissionDeniedDialog(){
CommonTipDialog mPrivacyDialog = new CommonTipDialog(context);
mPrivacyDialog.setTipMsg(ResUtil.getString(R.string.permission_denied_tips_image));
mPrivacyDialog.setOkText("去设置");
mPrivacyDialog.setOnActionListener(
new CommonTipDialog.OnActionListener() {
@Override
public void onOk() {
//同意跳到应用详情页面
Uri packageUri = Uri.parse("package:" + getPackageName());
Intent intent = new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
packageUri
);
startActivityForResult(
intent, 0
);
}
}
);
mPrivacyDialog.show();
}
private void updateImagesData() {
List<PublishItem> tmp = new ArrayList<>();
for (int i = 0; i < uploadList.size(); i++) {

View File

@@ -1,9 +1,9 @@
package com.netease.nim.uikit.business.session.actions
import android.Manifest
import android.content.Intent
import android.text.TextUtils
import com.netease.nim.uikit.R
import com.netease.nim.uikit.business.session.helper.SendImageHelper
import com.nnbc123.library.common.application.BaseApp
import com.nnbc123.library.common.base.BaseDialogFragment
import com.nnbc123.library.common.photo.PhotoProviderNew
@@ -29,7 +29,18 @@ abstract class PickImageActionNew protected constructor(
protected abstract fun onPicked(file: File)
override fun onClick() {
checkStoragePermission()
container.permissionProxy?.let {
it.requestPermission(
{ result ->
if (result) {
checkStoragePermission()
}
},
"访问你的本地内容,以能正常使用图片上传、视频发送等应用功能",
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
} ?: checkStoragePermission()
}
private fun checkStoragePermission() {

View File

@@ -12,6 +12,7 @@ public class Container {
public final String account;
public final SessionTypeEnum sessionType;
public final ModuleProxy proxy;
public PermissionProxy permissionProxy;
public Container(Activity activity, String account, SessionTypeEnum sessionType, ModuleProxy proxy) {
this.activity = activity;
@@ -19,4 +20,12 @@ public class Container {
this.sessionType = sessionType;
this.proxy = proxy;
}
public Container(Activity activity, String account, SessionTypeEnum sessionType, ModuleProxy proxy, PermissionProxy permissionProxy) {
this.activity = activity;
this.account = account;
this.sessionType = sessionType;
this.proxy = proxy;
this.permissionProxy = permissionProxy;
}
}

View File

@@ -0,0 +1,17 @@
package com.netease.nim.uikit.business.session.module
import androidx.core.util.Consumer
/**
* Created by Max on 2024/1/4 15:21
* Desc:
**/
interface PermissionProxy {
/**
* 申请权限
* @param consumer
* @param perms 权限列表
*/
fun requestPermission(consumer: Consumer<Boolean>, deniedTips: String, vararg perms: String)
}

View File

@@ -11,6 +11,8 @@ import android.view.inputmethod.InputMethodManager;
import com.netease.nim.uikit.common.activity.UI;
import com.netease.nim.uikit.common.util.log.LogUtil;
import io.reactivex.disposables.CompositeDisposable;
public abstract class TFragment extends Fragment {
private static final Handler handler = new Handler();
@@ -18,6 +20,8 @@ public abstract class TFragment extends Fragment {
private boolean destroyed;
protected CompositeDisposable compositeDisposable = new CompositeDisposable();
protected final boolean isDestroyed() {
return destroyed;
}
@@ -42,7 +46,7 @@ public abstract class TFragment extends Fragment {
super.onDestroy();
LogUtil.ui("fragment: " + getClass().getSimpleName() + " onDestroy()");
compositeDisposable.dispose();
destroyed = true;
}