修改可以使用

This commit is contained in:
2025-07-17 22:46:35 +08:00
parent 4a7e96473a
commit 7f0df85123
114 changed files with 267690 additions and 266676 deletions

View File

@@ -124,7 +124,9 @@ dependencies {
//判断是否是模拟器
api(libs.easy.protector.release)
//第三方Popup
api(libs.custompopwindow)
// api(libs.custompopwindow)
// api 'com.github.pinguo-zhouwei:CustomPopwindow:2.1.1'
api 'com.example.zhouwei.library:library:1.0.0'
// cookie
api(libs.persistentcookiejar)
@@ -168,7 +170,7 @@ dependencies {
// 集成音频 SDK声网
// api('io.agora.rtc:voice-sdk:4.5.2')
// api( 'io.agora.rtc:agora-special-full:4.1.1.29')
api( 'com.github.AgoraIO-Community:LyricsView:1.1.3')
api('com.github.AgoraIO-Community:LyricsView:1.1.3')
//声网集成屏幕共享
def agora_sdk_version = "4.5.2"
api "io.agora.rtc:full-sdk:${agora_sdk_version}"
@@ -187,7 +189,7 @@ dependencies {
api "com.tencent.liteav:LiteAVSDK_Professional:latest.release"
api "com.tencent.imsdk:imsdk-plus:latest.release"
//悬浮框
api"io.github.petterpx:floatingx:2.3.5"
api "io.github.petterpx:floatingx:2.3.5"
// system浮窗&&compose时需要导入 https://github.com/Petterpx/FloatingX/
// 记得AppHelper里调用 enableComposeSupport()
api 'io.github.petterpx:floatingx-compose:2.3.5'
@@ -197,6 +199,12 @@ dependencies {
// api 'org.eclipse.paho:org.eclipse.paho.mqttv5.client:1.2.5'
api 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.1'
api 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
// api 'com.github.hannesa2:paho.mqtt.android:3.3.5'
// api 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
api 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
// api 'io.github.mayzs:paho.mqtt.android:1.1.2'
//2. 云normal SDK
//aar的名称例如WbCloudNormal-v5.1.10-123456789.aar填入 'WbCloudNormal-v5.1.10-123456789.aar'

View File

@@ -22,11 +22,12 @@
android:name=".activity.news.OfficialNoticeActivity"
android:exported="false" />
<service android:name="org.eclipse.paho.android.service.MqttService" />
<receiver android:name="org.eclipse.paho.android.service.AlarmPingSender$AlarmReceiver"
android:exported="false"
tools:ignore="Instantiatable" />
<service android:name=".service.EMqttService"
android:foregroundServiceType="dataSync"/>
<!-- <receiver android:name="org.eclipse.paho.android.service.AlarmPingSender$AlarmReceiver"-->
<!-- android:enabled="true"-->
<!-- android:exported="true"-->
<!-- tools:ignore="Instantiatable" />-->
<!-- <service android:name=".service.EMqttService"-->
<!-- android:foregroundServiceType="dataSync"/>-->
<service android:name=".service.MyMqttService"
android:foregroundServiceType="dataSync"/>
</application>

View File

@@ -20,6 +20,7 @@ import androidx.databinding.ViewDataBinding;
import com.alibaba.android.arouter.launcher.ARouter;
import com.blankj.utilcode.util.BarUtils;
import com.qxcm.moduleutil.R;
import com.qxcm.moduleutil.utils.DisplayUtil;
import com.qxcm.moduleutil.utils.LanguageUtil;
import org.greenrobot.eventbus.EventBus;
@@ -65,19 +66,40 @@ public abstract class BaseAppCompatActivity<VDB extends ViewDataBinding> extends
EventBus.getDefault().register(this);
}
// 设置全屏模式,隐藏状态栏和导航栏
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
// @Override
// public Resources getResources() {//禁止app字体大小跟随系统字体大小调节
// Resources resources = super.getResources();
// if (resources != null && resources.getConfiguration().fontScale != 1.0f) {
// android.content.res.Configuration configuration = resources.getConfiguration();
// configuration.fontScale = 1.0f;
// resources.updateConfiguration(configuration, resources.getDisplayMetrics());
// }
// return resources;
// }
static float fontScale = 1f;
@Override
public Resources getResources() {//禁止app字体大小跟随系统字体大小调节
public Resources getResources() {
Resources resources = super.getResources();
if (resources != null && resources.getConfiguration().fontScale != 1.0f) {
android.content.res.Configuration configuration = resources.getConfiguration();
configuration.fontScale = 1.0f;
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
}
return resources;
return DisplayUtil.getResources(this,resources,fontScale);
}
public void setFontScale(float fontScale) {
this.fontScale = fontScale;
DisplayUtil.recreate(this);
}
public boolean isLightMode() {
return true;
}

View File

@@ -29,6 +29,7 @@ import com.qxcm.moduleutil.R;
import com.qxcm.moduleutil.base.CommonAppContext;
import com.qxcm.moduleutil.bean.UserBean;
import com.qxcm.moduleutil.bean.UserInfo;
import com.qxcm.moduleutil.event.UnreadCountEvent;
import com.qxcm.moduleutil.utils.LanguageUtil;
import com.qxcm.moduleutil.utils.location.LocationProvider;
import com.qxcm.moduleutil.utils.location.LocationServiceFactory;
@@ -36,6 +37,8 @@ import com.qxcm.moduleutil.utils.location.SystemLocationProvider;
import com.tencent.imsdk.v2.V2TIMCallback;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMUserFullInfo;
import com.tencent.imsdk.v2.V2TIMValueCallback;
import com.tencent.liteav.base.Log;
import com.tencent.qcloud.tuicore.TUILogin;
import com.tencent.qcloud.tuicore.interfaces.TUICallback;
@@ -117,6 +120,20 @@ public abstract class BaseMvpActivity<P extends IPresenter, VDB extends ViewData
}
});
initLocation();
// V2TIMManager.getConversationManager().getTotalUnreadMessageCount(new V2TIMValueCallback<Long>() {
// @Override
// public void onSuccess(Long aLong) {
// Log.i("imsdk", "success");
//// EventBus.getDefault().post(new UnreadCountEvent(aLong));
// }
//
// @Override
// public void onError(int code, String desc) {
// Log.i("imsdk", "failure, code:" + code + ", desc:" + desc);
// }
// });
}
});

View File

@@ -257,6 +257,16 @@ public class WebViewActivity extends BaseAppCompatActivity<ActivityWebViewBindin
ARouter.getInstance().build(ARouteConstants.CURRENCY).navigation();
}
@JavascriptInterface
public void Withdrawal() {
ARouter.getInstance().build(ARouteConstants.WITHDRAWAL_ACTIVITY).navigation();
}
@JavascriptInterface
public void enterAuthent() {//实名认证
ARouter.getInstance().build(ARouteConstants.REAL_NAME_ACTIVITY).navigation();
}
}
@JavascriptInterface

View File

@@ -5,294 +5,18 @@ import com.qxcm.moduleutil.bean.room.RankInfo;
import java.util.List;
import lombok.Data;
/**
* 项目名称 qipao-android
* 包名com.qpyy.room.bean
* 创建人 黄强
* 创建时间 2020/7/25 14:38
* 描述 describe
*@author qx
*@data 2025/7/16
*@description: 房间排行榜
*/
@Data
public class CharmRankingResp {
private MyBean my;
private List<ListsBean> lists;
public MyBean getMy() {
return my;
}
public void setMy(MyBean my) {
this.my = my;
}
public List<ListsBean> getLists() {
return lists;
}
public void setLists(List<ListsBean> lists) {
this.lists = lists;
}
public static class MyBean {
/**
* head_picture : https://gudao-prod.oss-cn-hangzhou.aliyuncs.com/android_images/577547/20200331141523_1585635321420.png
* nickname : 687592
* user_id : 577547
* level : 55
* number : 0
* rank : -1
* diff : 52474
* rank_info : {"rank_id":"55","rank_name":1000,"nobility_id":0,"nobility_name":"","picture":""}
*/
private String head_picture;
private String nickname;
private String user_id;
private String level;
private String number;
private int rank;
private String diff;
private String sex;
private String number_format;
public String getNumber_format() {
return number_format;
}
public void setNumber_format(String number_format) {
this.number_format = number_format;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
private RankInfo rank_info;
private String nobility_icon;
private String level_icon;
public String getNobility_icon() {
return nobility_icon;
}
public void setNobility_icon(String nobility_icon) {
this.nobility_icon = nobility_icon;
}
public String getLevel_icon() {
return level_icon;
}
public void setLevel_icon(String level_icon) {
this.level_icon = level_icon;
}
public String getHead_picture() {
return head_picture;
}
public void setHead_picture(String head_picture) {
this.head_picture = head_picture;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public String getDiff() {
return diff;
}
public void setDiff(String diff) {
this.diff = diff;
}
public RankInfo getRank_info() {
return rank_info;
}
public void setRank_info(RankInfo rank_info) {
this.rank_info = rank_info;
}
}
public static class ListsBean {
/**
* user_id : 642649
* number : 43280001
* head_picture : https://gudao-prod.oss-cn-hangzhou.aliyuncs.com/android_images/642649/20200601132728_1590989246548.jpeg
* nickname : 109179
* level : 4
* sex : 1
* nobility_icon : http://gudao-prod.oss-cn-hangzhou.aliyuncs.com/admin_images/5e71d1ef847ba.png
* rank : 1
* rank_info : {"rank_id":"4","rank_name":4,"nobility_id":6,"nobility_name":"帝皇","picture":""}
*/
private String user_id;
private String number;
private String head_picture;
private String nickname;
private String level;
private String sex;
private String nobility_icon;
private String level_icon;
private String user_code;
private int rank;
private RankInfo rank_info;
private String number_format;
private String good_number;
private String id_color;
public String getUser_code() {
return user_code;
}
public void setUser_code(String user_code) {
this.user_code = user_code;
}
public String getNumber_format() {
return number_format;
}
public void setNumber_format(String number_format) {
this.number_format = number_format;
}
public String getLevel_icon() {
return level_icon;
}
public void setLevel_icon(String level_icon) {
this.level_icon = level_icon;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getHead_picture() {
return head_picture;
}
public void setHead_picture(String head_picture) {
this.head_picture = head_picture;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getNobility_icon() {
return nobility_icon;
}
public void setNobility_icon(String nobility_icon) {
this.nobility_icon = nobility_icon;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public RankInfo getRank_info() {
return rank_info;
}
public void setRank_info(RankInfo rank_info) {
this.rank_info = rank_info;
}
public String getGood_number() {
return good_number;
}
public void setGood_number(String good_number) {
this.good_number = good_number;
}
public String getId_color() {
return id_color;
}
public void setId_color(String id_color) {
this.id_color = id_color;
}
}
private String user_id;
private String nickname;
private String avatar;
private List<String> icon;
private String total;
}

View File

@@ -19,4 +19,6 @@ public class HeadlineBean {
private String money;//花了多钱发的这个头条
private String nickname;//昵称
private String avatar;//头像
private String end_time;//倒计时时间
private String room_id;
}

View File

@@ -0,0 +1,16 @@
package com.qxcm.moduleutil.bean;
import lombok.Data;
/**
*@author qx
*@data 2025/7/16
*@description:抢头条推送过来的参数
*/
@Data
public class HeadlineEvent {
private int type;
private String content;
private UserInfo user_info;
private String room_id;
private String end_time;
}

View File

@@ -52,6 +52,7 @@ public class UserInfo implements Serializable {
private String is_room_owner;//是否是房主 0否 1是
private String pit_number;//在点击麦上用户的时候使用
private String auction_id;//在拍卖中的拍卖序号
private int auth;//是否实名 1实名 0未实名

View File

@@ -36,7 +36,7 @@ public class EMMessageInfo implements MultiItemEntity {
public static final int QXRoomMessageTypeAplayPitModeDidChanged = 1014;
/// pk房数值变化
public static final int QXRoomMessageTypePKValueDidChanged = 1015;
/// 房间类型发生变化
/// 禁言禁麦解除解禁
public static final int QXRoomMessageTypeRoomTypeDidChanged = 1016;
/// 管理员被删除
public static final int QXRoomMessageTypeManagerIsDelete = 1017;
@@ -119,6 +119,9 @@ public class EMMessageInfo implements MultiItemEntity {
case QXRoomMessageTypeRoomPKStart:
case QXRoomMessageTypeRoomPKEnd:
case QXRoomMessageTypeRoomPKDisconnect:
case QXRoomMessageTypeSeatMute:
case QXRoomMessageTypeSeatLock:
case QXRoomMessageTypeRoomTypeDidChanged:
return 1;
case QXRoomMessageTypeGift:
return 3;

View File

@@ -36,6 +36,7 @@ public class RoomAuction implements Serializable {
private String relation_icon;//关系图标
private String base_image;//礼物图片
private long duration;//时间
private String charm;
}
@Data
@@ -46,7 +47,7 @@ public class RoomAuction implements Serializable {
private String avatar;
private String dress;
private String sex;
private String gift_price;
private String gift_prices;
private String charm;
private List<String> icon;
}

View File

@@ -61,5 +61,7 @@ public class RoomPitBean implements Serializable {
private boolean is_pk;//是否是在pk模式中
private boolean isMute;//是否打开麦圈
private int is_pm;//是否是拍卖房 1是 0否
}

View File

@@ -0,0 +1,16 @@
package com.qxcm.moduleutil.event;
import lombok.Data;
/**
*@author qx
*@data 2025/7/15
*@description: 这是im展示需要显示的未读消息数
*/
@Data
public class UnreadCountEvent {
private long aLong;
public UnreadCountEvent(long aLong) {
this.aLong = aLong;
}
}

View File

@@ -6,6 +6,7 @@ import com.qxcm.moduleutil.bean.AppPay;
import com.qxcm.moduleutil.bean.BannerModel;
import com.qxcm.moduleutil.bean.BindType;
import com.qxcm.moduleutil.bean.BlackUserBean;
import com.qxcm.moduleutil.bean.CharmRankingResp;
import com.qxcm.moduleutil.bean.CircleListBean;
import com.qxcm.moduleutil.bean.CommentBean;
import com.qxcm.moduleutil.bean.ExpandColumnBean;
@@ -95,7 +96,7 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.SEND_HEADLINE)
Call<BaseModel<String>> sendHeadine(@Field("content") String content ,@Field("money") String money);
Call<BaseModel<String>> sendHeadine(@Field("content") String content ,@Field("money") String money,@Field("room_id") String roomId);
@FormUrlEncoded
@POST(Constants.POST_WITHDRAWAL)
@@ -121,6 +122,10 @@ public interface ApiServer {
@GET(Constants.GET_WITHDRAWAL_LIST)
Observable<BaseModel<List<WithdrawalBean>>> withdrawalList(@Query("page") String page, @Query("page_limit") String page_limit,@Query("search_stime") String search_stime, @Query("search_etime") String search_etime);
@FormUrlEncoded
@POST(Constants.POST_ROOM_RANK)
Observable<BaseModel<List<CharmRankingResp>>> getRoomRank(@Field("room_id") String room_id, @Field("type") String type, @Field("time_type") String time_type, @Field("page") String page, @Field("page_limit") String page_limit);
@FormUrlEncoded
@POST(Constants.POST_ROOM_RANKING)
Observable<BaseModel<PlaceholderBean>> roomRanking( @Field("type") String type);
@@ -182,7 +187,7 @@ public interface ApiServer {
Observable<BaseModel<UserBean>> userUpdate(@Field("nickname")String nickname, @Field("birthday")String birthday,@Field("sex")String sex, @Field("avatar")String avatar,@Field("init_code")String init_code,@Field("user_id")String user_id);
@GET(Constants.AUTHORIZATION)
Observable<BaseModel<String>> authorization();
Call<ResponseBody> authorization();
@FormUrlEncoded
@POST(Constants.CHANGE_PASSWORD)
@@ -254,7 +259,7 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.CHECK_TXT)
Call<BaseModel<String>> checkTxt(@Field("room_name") String room_name, @Field("room_cover") String room_cover, @Field("room_intro") String room_intro);
Call<ResponseBody> checkTxt(@Field("room_name") String room_name, @Field("room_cover") String room_cover, @Field("room_intro") String room_intro);
@FormUrlEncoded
@POST(Constants.GET_REWARD_LIST)
@@ -533,7 +538,7 @@ public interface ApiServer {
@FormUrlEncoded
@POST(Constants.SET_PRESIDED_RATIO)
Call<BaseModel<String>> setPresidedRatio(@Field("room_id") String room_id,@Field("user_id") String userId,@Field("ration") String ration);
Call<BaseModel<String>> setPresidedRatio(@Field("room_id") String room_id,@Field("user_id") String userId,@Field("ratio") String ration);
@FormUrlEncoded
@POST(Constants.GET_PRESIDED_RATIO)

View File

@@ -21,6 +21,7 @@ import com.qxcm.moduleutil.bean.AppPay;
import com.qxcm.moduleutil.bean.BannerModel;
import com.qxcm.moduleutil.bean.BindType;
import com.qxcm.moduleutil.bean.BlackUserBean;
import com.qxcm.moduleutil.bean.CharmRankingResp;
import com.qxcm.moduleutil.bean.CircleListBean;
import com.qxcm.moduleutil.bean.CommentBean;
import com.qxcm.moduleutil.bean.ExpandColumnBean;
@@ -324,6 +325,10 @@ public class RetrofitClient {
sApiServer.withdrawalList(page,page_limit,search_stime,search_etime).compose(new DefaultTransformer<>()).subscribe(observer);
}
public void getRoomRank(String roomId, String type, String time_type, String page, String page_limit, BaseObserver<List<CharmRankingResp>> observer){
sApiServer.getRoomRank(roomId, type, time_type, page, page_limit).compose(new DefaultTransformer<>()).subscribe(observer);
}
public void wealthRanking(String ranking_type, String type, BaseObserver<PlaceholderBean> observer){
if (ranking_type.equals("0")){
sApiServer.roomRanking(type).compose(new DefaultTransformer<>()).subscribe(observer);
@@ -380,8 +385,8 @@ public class RetrofitClient {
sApiServer.dailyTasksOpenBox(gift_box_id).compose(new DefaultTransformer<>()).subscribe(observer);
}
public void sendHeadine(String content, String money, BaseObserver<String> observer) {
sApiServer.sendHeadine(content, money).enqueue(new Callback<BaseModel<String>>() {
public void sendHeadine(String content, String money,String roomId, BaseObserver<String> observer) {
sApiServer.sendHeadine(content, money,roomId).enqueue(new Callback<BaseModel<String>>() {
@Override
public void onResponse(Call<BaseModel<String>> call, Response<BaseModel<String>> response) {
onNextRetu(response, observer);
@@ -545,7 +550,26 @@ public class RetrofitClient {
}
public void authorization(BaseObserver<String> observer) {
sApiServer.authorization().compose(new DefaultTransformer<>()).subscribe(observer);
sApiServer.authorization().enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.code()==200){
try {
String json = response.body().string();
BaseModel<String> baseModel = GsonUtils.fromJson(json, BaseModel.class);
observer.onNext(baseModel.getData());
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}
public void oauthLogin(String netease_token, BaseObserver<List<UserBean>> observer) {
@@ -1307,15 +1331,27 @@ public class RetrofitClient {
}
public void checkTxt(String room_name, String room_cover, String room_intro, BaseObserver<String> observer) {
sApiServer.checkTxt(room_name, room_cover, room_intro).enqueue(new Callback<BaseModel<String>>() {
sApiServer.checkTxt(room_name, room_cover, room_intro).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<BaseModel<String>> call, Response<BaseModel<String>> response) {
onNextRetu(response, observer);
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.code() == 200) {
try {
String json = response.body().string();
BaseModel<String> baseModel = GsonUtils.fromJson(json, BaseModel.class);
if (baseModel.getCode()==1) {
observer.onNext(baseModel.getData());
}else {
com.hjq.toast.ToastUtils.show(baseModel.getMsg());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onFailure(Call<BaseModel<String>> call, Throwable t) {
com.blankj.utilcode.util.ToastUtils.showShort(t.toString());
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}

View File

@@ -4,8 +4,12 @@ import android.util.Log;
import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.LogUtils;
import com.qxcm.moduleutil.bean.HeadlineBean;
import com.qxcm.moduleutil.bean.HeadlineEvent;
import com.qxcm.moduleutil.bean.RoomMessageEvent;
import com.qxcm.moduleutil.bean.room.RoomInfoResp;
import com.qxcm.moduleutil.utils.SpUtil;
import com.tencent.imsdk.v2.V2TIMAdvancedMsgListener;
import com.tencent.imsdk.v2.V2TIMCallback;
import com.tencent.imsdk.v2.V2TIMGroupListener;
import com.tencent.imsdk.v2.V2TIMGroupMemberInfo;
@@ -32,6 +36,7 @@ public class MessageListenerSingleton {
private static MessageListenerSingleton instance;
private List<OnMessageReceivedListener> listeners = new ArrayList<>();
private V2TIMSimpleMsgListener simpleMsgListener;
private V2TIMAdvancedMsgListener v2TIMAdvancedMsgListener;
private static String mRoomId="";
private V2TIMGroupListener groupListener;
private MessageListenerSingleton() {
@@ -69,15 +74,35 @@ public class MessageListenerSingleton {
public void onRecvGroupCustomMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, byte[] customData) {
// notifyMessageReceived("群自定义(信令)消息:群组 " + groupID + " 中 " + sender.getNickName());
LogUtils.d("收到群自定义消息:群组 " + groupID + "" + sender.getNickName());
String message = new String(customData, StandardCharsets.UTF_8);
RoomMessageEvent event = GsonUtils.fromJson(message, RoomMessageEvent.class);
notifyMessageReceived(event);
LogUtils.d("收到群自定义消息(信令):",message);
if (!groupID.equals("")) {
String message = new String(customData, StandardCharsets.UTF_8);
RoomMessageEvent event = GsonUtils.fromJson(message, RoomMessageEvent.class);
notifyMessageReceived(event);
LogUtils.d("收到群自定义消息(信令):", message);
}else {
String message = new String(customData, StandardCharsets.UTF_8);
LogUtils.d("收到群自定义消息(信令):", message);
HeadlineBean event = GsonUtils.fromJson(message, HeadlineBean.class);
EventBus.getDefault().post(event);
}
}
};
V2TIMManager.getMessageManager().addAdvancedMsgListener(v2TIMAdvancedMsgListener);
V2TIMManager.getInstance().addSimpleMsgListener(simpleMsgListener);
v2TIMAdvancedMsgListener=new V2TIMAdvancedMsgListener() {
@Override
public void onRecvNewMessage(V2TIMMessage msg) {
super.onRecvNewMessage(msg);
if (msg.isBroadcastMessage()) {
// 收到了广播消息
String message = new String(msg.getCustomElem().getData(), StandardCharsets.UTF_8);
LogUtils.e("收到广播消息(系统):",message);
}
}
};
groupListener = new V2TIMGroupListener() {
@Override
public void onMemberEnter(String groupID, List<V2TIMGroupMemberInfo> memberList) {
@@ -254,7 +279,7 @@ public class MessageListenerSingleton {
// 创建自定义群消息
V2TIMMessage v2TIMMessage = V2TIMManager.getMessageManager().createCustomMessage(binaryData);
// v2TIMMessage.setNeedReadReceipt(true);
// 发送消息
V2TIMManager.getMessageManager().sendMessage(
v2TIMMessage,
@@ -272,6 +297,7 @@ public class MessageListenerSingleton {
V2TIMMessage v2TIMMessage = V2TIMManager.getMessageManager().createCustomMessage(binaryData);
v2TIMMessage.setExcludedFromUnreadCount( true);
v2TIMMessage.setExcludedFromContentModeration(true);
// v2TIMMessage.setNeedReadReceipt(true);
//
// // 发送消息
V2TIMManager.getMessageManager().sendMessage(v2TIMMessage,"u"+userId,null, V2TIMMessage.V2TIM_PRIORITY_HIGH,

View File

@@ -28,11 +28,11 @@ import com.blankj.utilcode.util.ObjectUtils;
import com.blankj.utilcode.util.PathUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.liulishuo.okdownload.DownloadTask;
import com.liulishuo.okdownload.StatusUtil;
import com.liulishuo.okdownload.core.cause.EndCause;
import com.liulishuo.okdownload.core.cause.ResumeFailedCause;
import com.liulishuo.okdownload.core.listener.DownloadListener1;
import com.liulishuo.okdownload.core.listener.assist.Listener1Assist;
import com.orhanobut.logger.Logger;
import com.qxcm.moduleutil.base.CommonAppContext;
import com.qxcm.moduleutil.bean.RoomMessageEvent;
import com.qxcm.moduleutil.event.CabinEvent;
@@ -41,11 +41,14 @@ import com.qxcm.moduleutil.interfaces.SoundLevelUpdateListener;
import com.qxcm.moduleutil.listener.MessageListenerSingleton;
import com.qxcm.moduleutil.utils.Md5Utils;
import com.qxcm.moduleutil.utils.SpUtil;
import com.qxcm.moduleutil.utils.logger.Logger;
import com.tencent.bugly.idasc.crashreport.CrashReport;
import org.greenrobot.eventbus.EventBus;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
@@ -375,6 +378,14 @@ public class AgoraManager {
}
}
public void muteAllRemoteAudioStreamsEx(boolean enabled){
if (rtcEngine != null){
RtcConnection connection = new RtcConnection();
connection.channelId = mRoomId;
rtcEngine.muteAllRemoteAudioStreamsEx(enabled, connection);
}
}
public void ClientRole(boolean enabled) {
if (rtcEngine != null) {
@@ -648,13 +659,8 @@ public class AgoraManager {
for (SoundLevelUpdateListener listener : soundLevelUpdateListeners) {
if (listener != null) {
ThreadUtils.runOnUiThread(() -> {
// if (uid <= 0) {
// // 本地用户音量变化
// listener.onLocalSoundLevelUpdate(volume);
// } else {
// 远程用户音量变化
listener.onRemoteSoundLevelUpdate(uid > 0 ? String.valueOf(uid) : SpUtil.getUserId() + "", volume);
// listener.onRemoteSoundLevelUpdate( String.valueOf(uid), volume);
// }
});
}
@@ -775,8 +781,10 @@ public class AgoraManager {
} else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_OPENING) {
LogUtils.e("lxj", musicPlayer.getState());
isPreload(mSongCode, type);
}else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_PLAYING){
LogUtils.e("lxj", musicPlayer.getState());
isPreload(mSongCode, type);
}
}
} else if (type == 2) {
if (code < 0) {
@@ -786,11 +794,41 @@ public class AgoraManager {
musicContentCenter.preload(mSongCode);
isPreload(mSongCode, type);
} catch (Exception e) {
Log.e("@@@", "预加载歌曲失败: songCode=" + mSongCode, e);
Log.e("lxj", "预加载歌曲失败: songCode=" + mSongCode, e);
}
}, 3000); // 3秒延迟
} else {
musicPlayer.open(mSongCode, 0);
// if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_PAUSED) {//暂停
// LogUtils.e("lxj", "暂停");
// musicPlayer.resume();
//
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_IDLE) {//空闲
// LogUtils.e("lxj", "空闲");
// musicPlayer.open(mSongCode, 0);
// isPreload(mSongCode, type);
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_OPEN_COMPLETED) {//打开成功
// LogUtils.e("lxj", "播放");
// musicPlayer.play();
// musicPlayer.selectAudioTrack(0);
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_IDLE) {
// LogUtils.e("lxj", "空闲");
// musicPlayer.open(mSongCode, 0);
// isPreload(mSongCode, type);
//// LogUtils.e("@@@", musicPlayer.getState());
//// musicPlayer.pause() ;
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_PAUSING_INTERNAL) {
// LogUtils.e("lxj", "关闭");
// musicPlayer.pause();
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_PLAYBACK_ALL_LOOPS_COMPLETED) {
// LogUtils.e("lxj", "daki");
// musicPlayer.open(mSongCode, 0);
// isPreload(mSongCode, type);
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_OPENING) {
// LogUtils.e("lxj", musicPlayer.getState());
// isPreload(mSongCode, type);
// }
}
}
@@ -861,6 +899,35 @@ public class AgoraManager {
}, 3000); // 3秒延迟
} else {
musicPlayer.open(mSongCode, 0);
// if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_PAUSED) {//暂停
// LogUtils.e("lxj", "暂停");
// musicPlayer.resume();
//
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_IDLE) {//空闲
// LogUtils.e("lxj", "空闲");
// musicPlayer.open(mSongCode, 0);
// isPreload2(mSongCode, type);
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_OPEN_COMPLETED) {//打开成功
// LogUtils.e("lxj", "播放");
// musicPlayer.play();
// musicPlayer.selectAudioTrack(0);
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_IDLE) {
// LogUtils.e("lxj", "空闲");
// musicPlayer.open(mSongCode, 0);
// isPreload2(mSongCode, type);
//// LogUtils.e("@@@", musicPlayer.getState());
//// musicPlayer.pause() ;
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_PAUSING_INTERNAL) {
// LogUtils.e("lxj", "关闭");
// musicPlayer.pause();
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_PLAYBACK_ALL_LOOPS_COMPLETED) {
// LogUtils.e("lxj", "daki");
// musicPlayer.open(mSongCode, 0);
// isPreload2(mSongCode, type);
// } else if (musicPlayer.getState() == io.agora.mediaplayer.Constants.MediaPlayerState.PLAYER_STATE_OPENING) {
// LogUtils.e("lxj", musicPlayer.getState());
// isPreload2(mSongCode, type);
// }
}
}
@@ -1011,36 +1078,100 @@ public class AgoraManager {
* @param lrcUri
*/
public void getLyricsInstance(String lrcUri) {
final File[] file = new File[1];
// 设置可缓存的歌词文件的最大数量,默认为 50
LyricsFileDownloader.getInstance(context).setMaxFileNum(50);
// 设置单个歌词文件的有效期,默认为 8 小时
LyricsFileDownloader.getInstance(context).setMaxFileAge(8 * 60 * 60);
LyricsFileDownloader.getInstance(context).download(lrcUri);
LyricsFileDownloader.getInstance(context).setLyricsFileDownloaderCallback(new LyricsFileDownloaderCallback() {
// 歌词文件下载回调
@Override
public void onLyricsFileDownloadProgress(int requestId, float progress) {
LogUtils.e("onLyricsFileDownloadProgress", "requestId: " + requestId + ", progress: " + progress);
MusicFileBean musicFileBean = new MusicFileBean();
musicFileBean.setFileData(null);
EventBus.getDefault().post(musicFileBean);
}
downloadAndPlayMp4(lrcUri);
// 歌词文件下载完成回调
@Override
public void onLyricsFileDownloadCompleted(int requestId, byte[] fileData, DownloadError error) {
LogUtils.e("onLyricsFileDownloadCompleted", "requestId: " + requestId + ", error: " + error);
if (error == null) {
MusicFileBean musicFileBean = new MusicFileBean();
musicFileBean.setFileData(fileData);
EventBus.getDefault().post(musicFileBean);
}
}
});
// final File[] file = new File[1];
//// 设置可缓存的歌词文件的最大数量,默认为 50
// LyricsFileDownloader.getInstance(context).setMaxFileNum(50);
//// 设置单个歌词文件的有效期,默认为 8 小时
// LyricsFileDownloader.getInstance(context).setMaxFileAge(8 * 60 * 60);
// LyricsFileDownloader.getInstance(context).download(lrcUri);
// LyricsFileDownloader.getInstance(context).setLyricsFileDownloaderCallback(new LyricsFileDownloaderCallback() {
// // 歌词文件下载回调
// @Override
// public void onLyricsFileDownloadProgress(int requestId, float progress) {
// LogUtils.e("onLyricsFileDownloadProgress", "requestId: " + requestId + ", progress: " + progress);
// MusicFileBean musicFileBean = new MusicFileBean();
// musicFileBean.setFileData(null);
// EventBus.getDefault().post(musicFileBean);
// }
//
// // 歌词文件下载完成回调
// @Override
// public void onLyricsFileDownloadCompleted(int requestId, byte[] fileData, DownloadError error) {
// LogUtils.e("onLyricsFileDownloadCompleted", "requestId: " + requestId + ", error: " + error);
// if (error == null) {
// MusicFileBean musicFileBean = new MusicFileBean();
// musicFileBean.setFileData(fileData);
// EventBus.getDefault().post(musicFileBean);
// }
//
// }
// });
}
private void downloadAndPlayMp4(String url) {
DownloadTask task = new DownloadTask.Builder(url, PathUtils.getInternalAppCachePath()
, Md5Utils.getStringMD5(url))
// the minimal interval millisecond for callback progress
.setMinIntervalMillisCallbackProcess(100)
// do re-download even if the task has already been completed in the past.
.setPassIfAlreadyCompleted(false)
.setAutoCallbackToUIThread(true)
.build();
if (StatusUtil.isCompleted(task)) {
MusicFileBean musicFileBean = new MusicFileBean();
musicFileBean.setFileData(convertFileToByteArray(task.getFile()));
EventBus.getDefault().post(musicFileBean);
} else {
task.enqueue(new DownloadListener1() {
@Override
public void taskStart(@NonNull DownloadTask task, @NonNull Listener1Assist.Listener1Model model) {
com.qxcm.moduleutil.utils.logger.Logger.e("taskStart", model);
}
@Override
public void retry(@NonNull DownloadTask task, @NonNull ResumeFailedCause cause) {
com.qxcm.moduleutil.utils.logger.Logger.e("retry", cause);
CrashReport.postCatchedException(new RuntimeException("下载文件重试:" + cause == null ? "" : cause.name()));
}
@Override
public void connected(@NonNull DownloadTask task, int blockCount, long currentOffset, long totalLength) {
com.qxcm.moduleutil.utils.logger.Logger.e("connected", blockCount);
}
@Override
public void progress(@NonNull DownloadTask task, long currentOffset, long totalLength) {
com.qxcm.moduleutil.utils.logger.Logger.e("progress", currentOffset);
}
@Override
public void taskEnd(@NonNull DownloadTask task, @NonNull EndCause cause, @Nullable Exception realCause, @NonNull Listener1Assist.Listener1Model model) {
Logger.e("taskEnd", model);
MusicFileBean musicFileBean = new MusicFileBean();
musicFileBean.setFileData(convertFileToByteArray(task.getFile()));
EventBus.getDefault().post(musicFileBean);
if (cause != null && cause != EndCause.COMPLETED) {
// CrashReport.postCatchedException(new RuntimeException("下载任务结束:" + cause == null ? "" : cause.name() + "_realCause:" + realCause == null ? "" : realCause.getMessage()));
}
}
});
}
}
public static byte[] convertFileToByteArray(File file) {
byte[] byteArray = null;
try (FileInputStream fis = new FileInputStream(file)) {
byteArray = new byte[(int) file.length()];
fis.read(byteArray);
} catch (Exception e) {
e.printStackTrace();
}
return byteArray;
}
}

View File

@@ -41,6 +41,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class EMqttService extends Service implements NetworkUtils.OnNetworkStatusChangedListener {
private final static String TAG = "EMQTT消息";
@@ -65,10 +66,10 @@ public class EMqttService extends Service implements NetworkUtils.OnNetworkStatu
super.onCreate();
Logger.e(TAG, "服务创建成功");
NetworkUtils.registerNetworkStatusChangedListener(this);
scheduledExecutorService.scheduleWithFixedDelay(connectTask, 0, 10, TimeUnit.SECONDS);
// scheduledExecutorService.scheduleWithFixedDelay(connectTask, 0, 10, TimeUnit.SECONDS);
}
private final Runnable connectTask = this::doClientConnection;
// private final Runnable connectTask = this::doClientConnection;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
@@ -148,11 +149,11 @@ public class EMqttService extends Service implements NetworkUtils.OnNetworkStatu
*/
private String clientId = "";
private void init() {
private void init() throws MqttException {
UserBean user = CommonAppContext.getInstance().getUser();
if (mqttAndroidClient == null) {
clientId = "android-" + user.getUser_id() + "-" + MqttClient.generateClientId();
mqttAndroidClient = new MqttAndroidClient(this, HOST, clientId);
mqttAndroidClient = new MqttAndroidClient(this, HOST, clientId, MqttAndroidClient.Ack.AUTO_ACK);
}
mMqttConnectOptions = new MqttConnectOptions();
mMqttConnectOptions.setCleanSession(true);
@@ -161,16 +162,12 @@ public class EMqttService extends Service implements NetworkUtils.OnNetworkStatu
mMqttConnectOptions.setUserName("public");
mMqttConnectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
try {
mqttAndroidClient.connect(mMqttConnectOptions, null, iMqttActionListener);
mqttAndroidClient.setCallback(mqttCallback);
} catch (MqttException e) {
e.printStackTrace();
}
mqttAndroidClient.connect(mMqttConnectOptions, null, iMqttActionListener);
mqttAndroidClient.setCallback(mqttCallback);
}
private synchronized void doClientConnection() {
private synchronized void doClientConnection() throws MqttException {
Logger.e("doClientConnection", "doClientConnection");
if (!isAlreadyConnected() && isConnectIsNomarl()) {
releaseMQTT();
@@ -225,7 +222,7 @@ public class EMqttService extends Service implements NetworkUtils.OnNetworkStatu
MqttException mqttException = (MqttException) arg1;
Logger.e(TAG, "链接状态失败:" + mqttException.getMessage());
}
ThreadUtils.runOnUiThreadDelayed(connectTask, 1000);
// ThreadUtils.runOnUiThreadDelayed(connectTask, 1000);
}
};
@@ -236,7 +233,11 @@ public class EMqttService extends Service implements NetworkUtils.OnNetworkStatu
@Override
public void connectionLost(Throwable cause) {
Logger.e(TAG, "链接断开,请检查网络");
doClientConnection();
try {
doClientConnection();
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
@Override
@@ -363,7 +364,11 @@ public class EMqttService extends Service implements NetworkUtils.OnNetworkStatu
@Override
public void onConnected(NetworkUtils.NetworkType networkType) {
doClientConnection();
try {
doClientConnection();
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
@Override

View File

@@ -34,9 +34,10 @@ import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.greenrobot.eventbus.EventBus;
import org.jetbrains.annotations.Nullable;
public class MyMqttService extends Service {
private final static String TAG = MyMqttService.class.getCanonicalName();
private final static String TAG = "lxj";
private static int qos = 2;
private static String HOST = "tcp://81.70.45.221";
@@ -74,26 +75,30 @@ public class MyMqttService extends Service {
@Override
public void onCreate() {
super.onCreate();
init();
try {
init();
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
private Notification createNotification() {
// 创建你的前台通知
Notification.Builder builder = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder = new Notification.Builder(this, "channel_id")
.setContentTitle("MQTT Service")
.setSmallIcon(R.mipmap.default_avatar);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"channel_id", "MQTT Channel",
NotificationManager.IMPORTANCE_LOW);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
return builder.build();
}
// private Notification createNotification() {
// // 创建你的前台通知
// Notification.Builder builder = null;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// builder = new Notification.Builder(this, "channel_id")
// .setContentTitle("MQTT Service")
// .setSmallIcon(R.mipmap.default_avatar);
// }
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// NotificationChannel channel = new NotificationChannel(
// "channel_id", "MQTT Channel",
// NotificationManager.IMPORTANCE_LOW);
// NotificationManager manager = getSystemService(NotificationManager.class);
// manager.createNotificationChannel(channel);
// }
// return builder.build();
// }
/**
* 开启服务
@@ -127,28 +132,24 @@ public class MyMqttService extends Service {
*
* @param message 消息
*/
public static void publish(String topic, String message) {
public static void publish(String topic, String message) throws MqttException {
if (mqttAndroidClient == null) {
Logger.e(TAG, "mqttAndroidClient is null", "发送失败");
return;
}
try {
//参数分别为:主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息
IMqttDeliveryToken publish = mqttAndroidClient.publish(topic, message.getBytes(), qos, false);
publish.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Logger.e(TAG, "发送消息", "发送成功");
}
//参数分别为:主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息
IMqttDeliveryToken publish = mqttAndroidClient.publish(topic, message.getBytes(), qos, false);
publish.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Logger.e(TAG, "发送消息", "发送成功");
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Logger.e(TAG, "发送消息", "发送失败");
}
});
} catch (MqttException e) {
e.printStackTrace();
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Logger.e(TAG, "发送消息", "发送失败");
}
});
}
@@ -206,9 +207,9 @@ public class MyMqttService extends Service {
/**
* 初始化
*/
private void init() {
private void init() throws MqttException {
String CLIENTID = "android-" + CommonAppContext.getInstance().getUser().getUser_id() + "-" + MqttClient.generateClientId();
mqttAndroidClient = new MqttAndroidClient(this, HOST, CLIENTID);
mqttAndroidClient = new MqttAndroidClient(this, HOST, CLIENTID, MqttAndroidClient.Ack.AUTO_ACK);
mqttAndroidClient.setCallback(mqttCallback); //设置监听订阅消息的回调
mMqttConnectOptions = new MqttConnectOptions();
mMqttConnectOptions.setCleanSession(false); //设置是否清除缓存
@@ -216,39 +217,32 @@ public class MyMqttService extends Service {
mMqttConnectOptions.setKeepAliveInterval(10); //设置心跳包发送间隔,单位:秒
mMqttConnectOptions.setUserName("public"); //设置用户名
// mMqttConnectOptions.setPassword(new char[0]); //设置密码
mMqttConnectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
if (!mqttAndroidClient.isConnected()) {
doClientConnection();
}
}
private void doClientConnection() {
private void doClientConnection() throws MqttException {
if (mqttAndroidClient != null && !mqttAndroidClient.isConnected() && isConnectIsNomarl() && b) {
try {
mqttAndroidClient.connect(mMqttConnectOptions, null, iMqttActionListener);
} catch (MqttException e) {
e.printStackTrace();
}
mqttAndroidClient.connect(mMqttConnectOptions, null, iMqttActionListener);
}
}
public static void closeConnection() {
public static void closeConnection() throws MqttException {
if (mqttAndroidClient.isConnected()) {
try {
IMqttToken disconnect = mqttAndroidClient.disconnect();
disconnect.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Logger.e(TAG, "断开链接", "断开链接成功");
}
IMqttToken disconnect = mqttAndroidClient.disconnect();
disconnect.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Logger.e(TAG, "断开链接", "断开链接成功");
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Logger.e(TAG, "断开链接", "断开链接失败" + exception.getMessage());
}
});
} catch (MqttException e) {
e.printStackTrace();
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Logger.e(TAG, "断开链接", "断开链接失败" + exception.getMessage());
}
});
}
}
@@ -268,7 +262,11 @@ public class MyMqttService extends Service {
HandlerUtil.getInstance(this).postDelayed(new Runnable() {
@Override
public void run() {
doClientConnection();
try {
doClientConnection();
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
}, 3000);
return false;
@@ -293,14 +291,18 @@ public class MyMqttService extends Service {
if (mMyEmqttConnectListener != null) {
mMyEmqttConnectListener.onConnectFailure();
}
if (arg0 instanceof MqttException) {
Logger.e(TAG, "链接状态:", "链接失败" + ((MqttException) arg1).getMessage());
}
// if (arg0 instanceof MqttException) {
//// Logger.e(TAG, "链接状态:", "链接失败" + ((MqttException) arg1).getMessage());
// }
HandlerUtil.getInstance(getApplicationContext()).postDelayed(new Runnable() {
@Override
public void run() {
if (b) {
doClientConnection();
try {
doClientConnection();
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
}
}, 3000);
@@ -339,7 +341,11 @@ public class MyMqttService extends Service {
@Override
public void run() {
if (b) {
doClientConnection();
try {
doClientConnection();
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
}
}, 300);

View File

@@ -17,6 +17,11 @@ public class ARouteConstants {
public static final String ROOM_ALLOWANCE = "/modulevocal/RoomAllowanceActivity"; //补贴明细
public static final String ROOM_ALLOWANCE_DETAIL = "/modulevocal/RoomAllowanceDetailActivity"; //补贴历史
public static final String CURRENCY = "/modulevocal/CurrencyExchangeActivity"; //补贴历史
public static final String CREATED_ROOM = "/modulevocal/CreatedRoomActivity"; //创建房间
public static final String WITHDRAWAL_ACTIVITY = "/modulevocal/WithdrawalActivity"; //提现
public static final String REAL_NAME_ACTIVITY ="/modulevocal/RealName1Activity"; //实名认证

View File

@@ -0,0 +1,40 @@
package com.qxcm.moduleutil.utils;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
public class DisplayUtil {
/**
* 保持字体大小不随系统设置变化(用在界面加载之前)
* 要重写Activity的attachBaseContext()
*/
public static Context attachBaseContext(Context context, float fontScale) {
Configuration config = context.getResources().getConfiguration();
//正确写法
config.fontScale = fontScale;
return context.createConfigurationContext(config);
}
/**
* 保持字体大小不随系统设置变化(用在界面加载之前)
* 要重写Activity的getResources()
*/
public static Resources getResources(Context context, Resources resources, float fontScale) {
Configuration config = resources.getConfiguration();
if(config.fontScale != fontScale) {
config.fontScale = fontScale;
return context.createConfigurationContext(config).getResources();
} else {
return resources;
}
}
/**
* 保存字体大小后通知界面重建它会触发attachBaseContext来改变字号
*/
public static void recreate(Activity activity) {
activity.recreate();
}
}

View File

@@ -9,7 +9,7 @@ public enum EnvironmentEnum {
"qx-yusheng",
"https://qx-yusheng.oss-cn-hangzhou.aliyuncs.com/",
"wxc7681513be9f926b",
1600086675,
1600096860,
"4a521d6f1c6343998b1c8fd425dea02a"),
TEST(
"http://chat.qxmier.com/",
@@ -20,7 +20,7 @@ public enum EnvironmentEnum {
"qx-yusheng",
"https://qx-yusheng.oss-cn-hangzhou.aliyuncs.com/",
"wxc7681513be9f926b",
1600086675,
1600096890,
"4a521d6f1c6343998b1c8fd425dea02a");
private final String serverUrl;

View File

@@ -70,6 +70,7 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
boolean closePhone = false;//自己麦位关闭话筒,用于判断声纹显示
public String pitNumber;
public int pitImageVId;
public ImageView iv_zhul;
public ImageView iv_on_line;
@@ -222,6 +223,7 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
if (userId.equals(pitBean.getUser_id())) {
if (soundLevel == 0) {
mIvRipple.post(() -> {
mIvRipple.stopAnimation();
mIvRipple.setVisibility(GONE);
});
} else {
@@ -232,11 +234,11 @@ public abstract class BaseWheatView extends ConstraintLayout implements IBaseWhe
});
}
if (pitBean.getUser_id().equals(SpUtil.getUserId()) && closePhone) {
mIvRipple.post(() -> {
mIvRipple.setVisibility(GONE);
});
}
// if (pitBean.getUser_id().equals(SpUtil.getUserId()) && closePhone) {
// mIvRipple.post(() -> {
// mIvRipple.setVisibility(GONE);
// });
// }
}
// else {
// mIvRipple.post(() -> {

View File

@@ -10,11 +10,14 @@ import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;
import androidx.annotation.RequiresApi;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
@@ -22,6 +25,7 @@ import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
@RequiresApi(api = Build.VERSION_CODES.CUPCAKE)
public class ChannelSplitRenderer1 implements GLSurfaceView.Renderer {
private static final String VERTEX_SHADER =

View File

@@ -182,161 +182,13 @@ public class Constants {
public static final String CASH_ACCOUNT_NAME = "cashAccountName";
public static final String CASH_ACCOUNT_TYPE = "cashAccountType";
public static final int RED_PACK_TYPE_AVERAGE = 0;//平均红包
public static final int RED_PACK_TYPE_SHOU_QI = 1;//拼手气红包
public static final int RED_PACK_SEND_TIME_NORMAL = 0;//立即发放
public static final int RED_PACK_SEND_TIME_DELAY = 1;//延时发放
public static final int PUSH_TYPE_LIVE = 1;//直播
public static final int PUSH_TYPE_MESSAGE = 2;//消息
public static final String PUSH_TYPE = "pushType";
public static final String PUSH_DATA = "pushData";
public static final String VIDEO_HOME = "videoHome";
public static final String VIDEO_USER = "videoUser_";
public static final String VIDEO_LIKE = "videoLike_";
public static final String VIDEO_KEY = "videoKey";
public static final String VIDEO_POSITION = "videoPosition";
public static final String VIDEO_SINGLE = "videoSingle";
public static final String VIDEO_PAGE = "videoPage";
public static final String VIDEO_BEAN = "videoBean";
public static final String VIDEO_ID = "videoId";
public static final String VIDEO_COMMENT_BEAN = "videoCommnetBean";
public static final String VIDEO_FACE_OPEN = "videoOpenFace";
public static final String VIDEO_FACE_HEIGHT = "videoFaceHeight";
public static final String VIDEO_DURATION = "videoDuration";
public static final String VIDEO_PATH = "videoPath";
public static final String VIDEO_PATH_WATER = "videoPathWater";
public static final String VIDEO_FROM_RECORD = "videoFromRecord";
public static final String VIDEO_MUSIC_ID = "videoMusicId";
public static final String VIDEO_HAS_BGM = "videoHasBgm";
public static final String VIDEO_MUSIC_NAME_PREFIX = "videoMusicName_";
public static final String VIDEO_SAVE_TYPE = "videoSaveType";
public static final int VIDEO_SAVE_SAVE_AND_PUB = 1;//保存并发布
public static final int VIDEO_SAVE_SAVE = 2;//仅保存
public static final int VIDEO_SAVE_PUB = 3;//仅发布
public static final String MOB_QQ = "qq";
public static final String MOB_QZONE = "qzone";
public static final String MOB_WX = "wx";
public static final String MOB_WX_PYQ = "wchat";
public static final String MOB_FACEBOOK = "facebook";
public static final String MOB_TWITTER = "twitter";
public static final String MOB_PHONE = "phone";
public static final String LIVE_SDK = "liveSdk";
public static final String LIVE_CONFIG = "liveConfig";
public static final int LIVE_SDK_TX = 1;//腾讯推流
public static final int LINK_MIC_TYPE_NORMAL = 0;//观众与主播连麦
public static final int LINK_MIC_TYPE_ANCHOR = 1;//主播与主播连麦
public static final String HAVE_STORE = "haveStore";
public static final String IS_CHAT_ROOM = "isChatRoom";
public static final String CHAT_ROOM_TYPE = "voiceChatRoomType";
public static final String SCREEN_RECORD = "screenRecord";
public static final String MONEY_SIGN = "¥";
public static final String CHOOSE_IMG = "chooseImage";
public static final String CHOOSE_LOCATION = "chooseLocation";
public static final String ACTIVE_BEAN = "activeBean";
//动态类型
public static final int ACTIVE_TYPE_TEXT = 0;//0纯文字
public static final int ACTIVE_TYPE_IMAGE = 1;//1文字+图片;
public static final int ACTIVE_TYPE_VIDEO = 2;//2文字+视频;
public static final int ACTIVE_TYPE_VOICE = 3;//3文字+音频
public static final int ACTIVE_TYPE_GOODS = 4;//4文字+商品
public static final int GIFT_TYPE_NORMAL = 0;//正常礼物
public static final int GIFT_TYPE_DAO = 1;//道具
public static final int GIFT_TYPE_PACK = 2;//背包
public static final String MALL_APPLY_FAILED = "mallApplyFailed";
public static final String MALL_APPLY_MANAGE_CLASS = "mallApplyManageClass";
public static final String MALL_APPLY_BOND = "mallApplyBond";
public static final String MALL_GOODS_CLASS = "mallGoodsClass";
public static final String MALL_GOODS_ID = "mallGoodsId";
public static final String MALL_GOODS_NAME = "mallGoodsName";
public static final String MALL_GOODS_FROM_SHOP = "mallGoodsFromShop";
public static final String MALL_CERT_IMG = "mallCertImg";
public static final String MALL_CERT_TEXT = "mallCertText";
public static final String MALL_REFUND_NAME = "mallRefundName";
public static final String MALL_REFUND_PHONE = "mallRefundPhone";
public static final String MALL_REFUND_PROVINCE = "mallRefundProvince";
public static final String MALL_REFUND_CITY = "mallRefundCity";
public static final String MALL_REFUND_ZONE = "mallRefundZone";
public static final String MALL_REFUND_ADDRESS = "mallRefundAddress";
public static final String MALL_BUYER_ADDRESS = "mallBuyerAddress";
public static final String MALL_GOODS_SPEC = "mallGoodsSpec";
public static final String MALL_GOODS_COUNT = "mallGoodsCount";
public static final String MALL_POSTAGE = "mallPostage";
public static final String MALL_SHOP_NAME = "mallShopName";
public static final int GOODS_TYPE_OUT = 1;//站外商品
public static final int GOODS_TYPE_INNER = 2;//站内商品
public static final String MALL_ORDER_ID = "mallOrderId";
public static final String MALL_ORDER_MONEY = "mallOrderMoney";
public static final String MALL_ORDER_INDEX = "mallOrderIndex";
public static final String MALL_PAY_GOODS_ORDER = "Buyer.goodsOrderPay";
public static final String MALL_PAY_CONTENT_ALI = "Paidprogram.getAliOrder";
public static final String MALL_PAY_CONTENT_WX = "Paidprogram.getWxOrder";
public static final String MALL_PAY_CONTENT_PAYPAL = "Paidprogram.getBraintreePaypalOrder";
// 订单状态 -1已关闭0待付款1待发货2待收货3待评价4已评价5退款
public static final int MALL_ORDER_STATUS_CLOSE = -1;
public static final int MALL_ORDER_STATUS_WAIT_PAY = 0;
public static final int MALL_ORDER_STATUS_WAIT_SEND = 1;
public static final int MALL_ORDER_STATUS_WAIT_RECEIVE = 2;
public static final int MALL_ORDER_STATUS_WAIT_COMMENT = 3;
public static final int MALL_ORDER_STATUS_COMMENT = 4;
public static final int MALL_ORDER_STATUS_REFUND = 5;
public static final String MALL_CASH_BALANCE = "mallCashBalance";
public static final String MALL_CASH_TOTAL = "mallCashTotal";
public static final String MALL_GOODS_ORDER = "goodsorder_admin";
public static final String MALL_PLAT_UID = "1";
public static final int VOICE_CTRL_EMPTY = 0;//无人且麦位可用
public static final int VOICE_CTRL_BAN = 2;//无人且麦位不可用,被禁了
public static final int VOICE_CTRL_CLOSE = -1;//有人且被关麦,无法说话
public static final int VOICE_CTRL_OPEN = 1;//有人且正常说话
public static final String VOICE_FACE = "voiceRoomFace";
public static final String NOT_LOGIN_UID = "-9999";//未登录的uid
public static final String NOT_LOGIN_TOKEN = "-9999";//未登录的token
public static final int ZERO = 0;
public static final String EMPTY_STRING = "";
public static final String[] EMPTY_STRING_ARR = new String[]{};
public static final String IM_MSG_CONCAT = "dsp_fans";
public static final String IM_MSG_LIKE = "dsp_like";
public static final String IM_MSG_AT = "dsp_at";
public static final String IM_MSG_COMMENT = "dsp_comment";
public static final String IM_CUSTOM_METHOD_GOODS = "GoodsMsg";
public static final String IM_CUSTOM_METHOD_ORDER = "order";
public static final int FLOAT_TYPE_DEFAULT = 0;
public static final int FLOAT_TYPE_GOODS = 1;
public static final String LANGUAGE = "language";
public static final String LANG_EN = "en";//英文
public static final String LANG_ZH = "zh-cn";//中文
public static final String SOCKET_CT_ZH = "ct";
public static final String SOCKET_CT_EN = "ct_en";
public static final int CHAT_ROOM_TYPE_VOICE = 0;
public static final int CHAT_ROOM_TYPE_VIDEO = 1;
public static final String MUTE_REMOTE_AUDIO = "muteRemoteAudio";
public static final int PAYSUCESS = 0x0000;
@@ -355,7 +207,7 @@ public class Constants {
public static final String USER_UPDATE = "/api/UserData/modify_fist_user_info";
public static final String CHANGE_PASSWORD = "/api/UserData/modify_password";
public static final String CHANGE_PASSWORD = "/api/UserData/modify_password";//设置密码
public static final String URL_LOGIN = "/api/Login/one_click_login";//一键登录
public static final String URL_AUTH_CODE = "/api/Login/aliLogin";//支付宝登录
@@ -499,6 +351,7 @@ public class Constants {
public static final String GET_MY_BAG_OUTCOME = "/api/UserGiftPack/get_gift_pack_outcome";//背包礼物支出列表
public static final String GET_GIFT_PACK = "/api/UserGiftPack/get_gift_pack_list";//获取背包礼物列表
public static final String GET_WITHDRAWAL_LIST = "/api/UserWithdrawal/withdrawal_list";//提现记录
public static final String POST_ROOM_RANK = "/api/Room/room_rank";//房间排行榜(财富、魅力)

View File

@@ -41,12 +41,14 @@ public class RoomMakeWheatView extends BaseWheatView {
protected void initPit(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoomMakeWheatView);
pitNumber = typedArray.getString(R.styleable.RoomMakeWheatView_room_make_wheat_number);
pitImageVId=typedArray.getResourceId(R.styleable.RoomMakeWheatView_room_make_pic, 0);
typedArray.recycle();
mIvTagBoss = findViewById(R.id.iv_tag_boos);
mTvTime = findViewById(R.id.tv_time);
iv_on_line=findViewById(R.id.iv_online);
iv_tag_type=findViewById(R.id.iv_tag_type);
mCharmView = findViewById(R.id.charm_view);
mRiv.setImageResource(pitImageVId);
}
@Override

View File

@@ -0,0 +1,76 @@
package com.qxcm.moduleutil.widget;
import android.os.CountDownTimer;
public class SilentCountDownTimer {
private CountDownTimer countDownTimer;
private long remainingMillis; // 剩余毫秒数
private OnCountDownFinishListener listener;
public interface OnCountDownFinishListener {
void onFinish();
}
public void setOnCountDownFinishListener(OnCountDownFinishListener listener) {
this.listener = listener;
}
/**
* 启动或更新倒计时
*
* @param targetTimestamp 目标时间戳(单位:秒)
*/
public void start(long targetTimestamp) {
// 将目标时间戳(秒)转为毫秒,并计算剩余时间
long currentTimeMillis = System.currentTimeMillis();
long targetMillis = targetTimestamp * 1000L;
remainingMillis = targetMillis - currentTimeMillis;
if (remainingMillis <= 0) {
// 时间已过,直接结束
finishCountDown();
return;
}
// 释放旧的倒计时
if (countDownTimer != null) {
countDownTimer.cancel();
}
// 创建新倒计时
countDownTimer = new CountDownTimer(remainingMillis, 1000) {
@Override
public void onTick(long millisUntilFinished) {
remainingMillis = millisUntilFinished;
// 可选:输出日志或做一些后台处理
// Log.d("SilentCountDown", "剩余时间:" + millisUntilFinished / 1000 + " 秒");
}
@Override
public void onFinish() {
finishCountDown();
}
};
countDownTimer.start();
}
private void finishCountDown() {
if (listener != null) {
listener.onFinish(); // 回调完成
}
release(); // 释放资源
}
/**
* 销毁倒计时并释放资源
*/
public void release() {
if (countDownTimer != null) {
countDownTimer.cancel();
countDownTimer = null;
}
listener = null;
}
}

View File

@@ -13,21 +13,27 @@ import com.blankj.utilcode.util.ScreenUtils;
/**
* 可拖拽悬浮
* 稳定版悬浮窗控件 - 支持点击/拖动分离、适配横竖屏、自动吸附边缘
*/
public class FloatingMagnetView extends FrameLayout {
public static final int MARGIN_EDGE = 0;
private float mOriginalRawX;
private float mOriginalRawY;
private float mOriginalX;
private float mOriginalY;
private static final int TOUCH_TIME_THRESHOLD = 150;
private float mOriginalX, mOriginalY; // 当前 View 的坐标
private float mOriginalRawX, mOriginalRawY; // 触摸点的原始屏幕坐标
private long mLastTouchDownTime;
protected MoveAnimator mMoveAnimator;
protected int mScreenWidth;
private boolean isDragging = false;
private boolean isNearestLeft = true;
private int mScreenWidth;
private int mScreenHeight;
private int mStatusBarHeight;
private boolean isNearestLeft = true;
private MoveAnimator mMoveAnimator;
private OnFloatingClickListener listener;
private static final int TOUCH_TIME_THRESHOLD = 150;
private static final float CLICK_DRAG_THRESHOLD = 10;
public FloatingMagnetView(Context context) {
this(context, null);
@@ -50,58 +56,89 @@ public class FloatingMagnetView extends FrameLayout {
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event == null) {
return false;
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateSize();
moveToEdge(isNearestLeft);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
return false; // 不拦截,让子控件优先处理点击
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(ev.getX() - (mOriginalRawX - mOriginalX));
float dy = Math.abs(ev.getY() - (mOriginalRawY - mOriginalY));
if (dx > CLICK_DRAG_THRESHOLD || dy > CLICK_DRAG_THRESHOLD) {
isDragging = true;
}
return isDragging;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
isDragging = false;
return false;
default:
return super.onInterceptTouchEvent(ev);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event == null) return false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
changeOriginalTouchParams(event);
updateSize();
mOriginalX = getX();
mOriginalY = getY();
mOriginalRawX = event.getRawX();
mOriginalRawY = event.getRawY();
mLastTouchDownTime = System.currentTimeMillis();
mMoveAnimator.stop();
isDragging = false;
break;
case MotionEvent.ACTION_MOVE:
updateViewPosition(event);
if (isDragging) {
float newX = mOriginalX + (event.getRawX() - mOriginalRawX);
float newY = mOriginalY + (event.getRawY() - mOriginalRawY);
// 限制 Y 轴边界
if (newY < mStatusBarHeight) newY = mStatusBarHeight;
if (newY > mScreenHeight - getHeight()) newY = mScreenHeight - getHeight();
setX(newX);
setY(newY);
}
break;
case MotionEvent.ACTION_UP:
moveToEdge();
if (isOnClickEvent()) {
if (listener != null) {
listener.onClick();
}
} else {
moveToEdge();
}
isDragging = false;
break;
}
return true;
}
protected boolean isOnClickEvent() {
return System.currentTimeMillis() - mLastTouchDownTime < TOUCH_TIME_THRESHOLD;
private boolean isOnClickEvent() {
long time = System.currentTimeMillis() - mLastTouchDownTime;
float dx = Math.abs(getX() - mOriginalX);
float dy = Math.abs(getY() - mOriginalY);
return time < TOUCH_TIME_THRESHOLD && dx < CLICK_DRAG_THRESHOLD && dy < CLICK_DRAG_THRESHOLD;
}
private void updateViewPosition(MotionEvent event) {
setX(mOriginalX + event.getRawX() - mOriginalRawX);
// 限制不可超出屏幕高度
float desY = mOriginalY + event.getRawY() - mOriginalRawY;
if (desY < mStatusBarHeight) {
desY = mStatusBarHeight;
}
if (desY > mScreenHeight - getHeight()) {
desY = mScreenHeight - getHeight();
}
setY(desY);
}
private void changeOriginalTouchParams(MotionEvent event) {
mOriginalX = getX();
mOriginalY = getY();
mOriginalRawX = event.getRawX();
mOriginalRawY = event.getRawY();
mLastTouchDownTime = System.currentTimeMillis();
}
protected void updateSize() {
mScreenWidth = (ScreenUtils.getScreenWidth() - this.getWidth());
private void updateSize() {
mScreenWidth = ScreenUtils.getScreenWidth() - getWidth();
mScreenHeight = ScreenUtils.getScreenHeight();
}
@@ -110,69 +147,55 @@ public class FloatingMagnetView extends FrameLayout {
}
public void moveToEdge(boolean isLeft) {
float moveDistance = isLeft ? MARGIN_EDGE : mScreenWidth - MARGIN_EDGE;
mMoveAnimator.start(moveDistance, getY());
float moveX = isLeft ? MARGIN_EDGE : mScreenWidth - MARGIN_EDGE;
mMoveAnimator.start(moveX, getY());
isNearestLeft = isLeft;
}
protected boolean isNearestLeft() {
int middle = mScreenWidth / 2;
isNearestLeft = getX() < middle;
return isNearestLeft;
return getX() < middle;
}
protected class MoveAnimator implements Runnable {
private Handler handler = new Handler(Looper.getMainLooper());
private float destinationX;
private float destinationY;
private long startingTime;
private float destinationX, destinationY;
private long startTime;
void start(float x, float y) {
this.destinationX = x;
this.destinationY = y;
startingTime = System.currentTimeMillis();
this.startTime = System.currentTimeMillis();
handler.post(this);
}
@Override
public void run() {
if (getRootView() == null || getRootView().getParent() == null) {
return;
}
float progress = Math.min(1, (System.currentTimeMillis() - startingTime) / 400f);
if (getRootView() == null || getRootView().getParent() == null) return;
float progress = Math.min(1f, (System.currentTimeMillis() - startTime) / 400f);
float deltaX = (destinationX - getX()) * progress;
float deltaY = (destinationY - getY()) * progress;
move(deltaX, deltaY);
if (progress < 1) {
setX(getX() + deltaX);
setY(getY() + deltaY);
if (progress < 1f) {
handler.post(this);
}
}
private void stop() {
void stop() {
handler.removeCallbacks(this);
}
}
private void move(float deltaX, float deltaY) {
setX(getX() + deltaX);
setY(getY() + deltaY);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
updateSize();
moveToEdge(isNearestLeft);
}
public void setListener(OnFloatingClickListener listener) {
public void setOnFloatingClickListener(OnFloatingClickListener listener) {
this.listener = listener;
}
private OnFloatingClickListener listener;
public interface OnFloatingClickListener {
void onClick();
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 KiB