Commit 578fe20e authored by jyx's avatar jyx

代码优化

parent 2ac82af0
......@@ -31,6 +31,7 @@ android {
UMENG_KEY : RELEASE_UMENG_KEY,
SHARE_KEY : RELEASE_SHARESDK_KEY,
SHARE_SECRET : RELEASE_SHARESDK_SECRET,
MAP_KEY : RELEASE_MAP_KEY,
XG_ACCESS_ID : TX_XG_ACCESS_ID,
XG_ACCESS_KEY : TX_XG_ACCESS_KEY]
}
......@@ -148,6 +149,36 @@ android {
}
MobSDK {
appKey RELEASE_SHARESDK_KEY
appSecret RELEASE_SHARESDK_SECRET
def wxappid = WEIXIN_APP_ID
def wxsecret = WEIXIN_APP_SECRET
ShareSDK {
loopShare true
devInfo {
Wechat {
appId wxappid
appSecret wxsecret
userName "gh_afb25ac019c9"
path "pages/index/index.html?id=1"
withShareTicket true
miniprogramType 0
}
WechatMoments {
appId wxappid
appSecret wxsecret
}
}
}
MobPush {
pro true
lpk true
}
}
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.3.0'
......
......@@ -466,3 +466,13 @@
-keep class com.bytedance.ads.convert.broadcast.common.EncryptionTools {*;}
# ======================= 穿山甲商业化转化组件 END ================
# ======================= 高德地图 START ================
-keep class com.amap.api.maps.**{*;}
-keep class com.autonavi.**{*;}
-keep class com.amap.api.trace.**{*;}
-keep class com.amap.api.location.**{*;}
-keep class com.amap.api.fence.**{*;}
-keep class com.loc.**{*;}
-keep class com.autonavi.aps.amapapi.model.**{*;}
# ======================= 高德地图 END ================
......@@ -31,6 +31,12 @@
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.openadsdk.permission.TT_PANGOLIN" />
<!-- 高德地图使用权限 -->
<!--允许获取粗略位置,若用GPS实现定位小蓝点功能则必选-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--允许获取wifi状态改变,用于网络定位,若无gps但仍需实现定位小蓝点功能则此权限必选-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<application
android:name=".MintsApplication"
......@@ -46,6 +52,11 @@
tools:ignore="GoogleAppIndexingWarning"
tools:replace="android:allowBackup">
<!-- 高德地图 -->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="${MAP_KEY}" />
<!-- 适配小米(xiaomi)刘海屏 -->
<meta-data
android:name="android.max_aspect"
......@@ -62,6 +73,13 @@
android:name="UMENG_KEY"
android:value="${UMENG_KEY}" />
<meta-data
android:name="Mob-AppKey"
android:value="${SHARE_KEY}" />
<meta-data
android:name="Mob-AppSecret"
android:value="${SHARE_SECRET}" />
<!-- 渠道名称 -->
<meta-data
android:name="CHANNEL_NAME"
......@@ -215,6 +233,17 @@
android:name=".ui.service.UpdateService"
android:exported="true" />
<!-- ShareSDK -->
<activity
android:name="com.mob.tools.MobUIShell"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:windowSoftInputMode="stateHidden|adjustResize" />
<activity
android:name=".wxapi.WXEntryActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:exported="true"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
<!-- 自有下载 -->
<provider
......
This diff is collapsed.
......@@ -34,5 +34,10 @@ public class AppConfig {
public static double FLAVOR_VERSION = 0.0;
public static String IM_FLAVOR_VERSION = Constant.FLAVOR_LOCAL;
public static final int IM_UI_STYLE_CLASSIC = 0;
public static final int IM_UI_STYLE_MINIMALIST = 1;
public static int IM_UI_STYLE = IM_UI_STYLE_CLASSIC;
public static int IM_SDK_APPID = 0;
}
......@@ -31,12 +31,13 @@ object Constant {
const val CARRIERTYPE_NINE3 = "3"
/**
* app应用首页 0-主页 1-中间 2-尊享 3-我
* app应用首页
*/
const val FRAGMENT_CLICK_ONE = 0
const val FRAGMENT_CLICK_TWO = 1
const val FRAGMENT_CLICK_THREE = 2
const val FRAGMENT_CLICK_FOUR = 3
const val FRAGMENT_CLICK_FIVE = 4
// 协议地址
var REGISTER_URL = BuildConfig.MainIp+"/agreements/${VersionUtils.getEndPkg()}/yhxy.html"//注册协议
......@@ -49,4 +50,31 @@ object Constant {
const val GRO_MORE_ADTYPE2 = "2"
const val GRO_MORE_ADTYPE3 = "3"
const val GRO_MORE_ADTYPE4 = "4"
var mTabs = mutableListOf("城市不限", "20-60岁", "男士", "人气优先")
val mAges = listOf(
"20-60岁",
"18-22岁",
"23-26岁",
"27-30岁",
"31-34岁",
"35-38岁",
"39-42岁",
"43-46岁",
"47-50岁",
"51-54岁",
"55-58岁",
"59-62岁",
"63-64岁"
)
val mSexes = listOf("男士", "女士", "男同性", "女同性")
// val mConstellations = listOf("注册优先", "在线优先", "人气优先", "活跃优先", "照片优先", "最近距离")
val mConstellations = listOf("人气优先", "照片优先")
const val FLAVOR_LOCAL = "local"
const val USERINFO = "userInfo"
const val FLAVOR_INTERNATIONAL = "international"
}
\ No newline at end of file
package com.duben.roseplaylet.im;
import android.text.TextUtils;
import com.tencent.qcloud.tuicore.util.TUIBuild;
public class BrandUtil {
/**
* Xiaomi device
*/
public static boolean isBrandXiaoMi() {
return "xiaomi".equalsIgnoreCase(getBuildBrand()) || "xiaomi".equalsIgnoreCase(getBuildManufacturer());
}
/**
* oppo device
*
* @return
*/
public static boolean isBrandOppo() {
return "oppo".equalsIgnoreCase(getBuildBrand()) || "realme".equalsIgnoreCase(getBuildBrand()) || "oneplus".equalsIgnoreCase(getBuildBrand())
|| "oppo".equalsIgnoreCase(getBuildManufacturer()) || "realme".equalsIgnoreCase(getBuildManufacturer())
|| "oneplus".equalsIgnoreCase(getBuildManufacturer());
}
/**
* oppo device
*
* @return
*/
public static boolean isSamsungS9Series() {
return "samsung".equalsIgnoreCase(getBuildBrand())
&& (!TextUtils.isEmpty(getBuildModel()) && (getBuildModel().startsWith("SM-G965") || getBuildModel().startsWith("SM-G960")));
}
public static String getBuildBrand() {
return TUIBuild.getBrand();
}
public static String getBuildManufacturer() {
return TUIBuild.getManufacturer();
}
public static String getBuildModel() {
return TUIBuild.getModel();
}
public static String getBuildVersionRelease() {
return TUIBuild.getVersion();
}
public static int getBuildVersionSDKInt() {
return TUIBuild.getVersionInt();
}
}
package com.duben.roseplaylet.im;
import android.content.Context;
import com.tencent.qcloud.tuicore.TUIConfig;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuikit.tuichat.config.classicui.TUIChatConfigClassic;
import com.tencent.qcloud.tuikit.tuichat.config.minimalistui.TUIChatConfigMinimalist;
public class CustomConfigHelper {
private static Context mContext;
public static void initCustom(Context context) {
mContext = context;
initConversationDefaultAvatar();
initChatSettings();
}
public static void initConversationDefaultAvatar() {
TUIConfig.setEnableGroupGridAvatar(true);
TUIConfig.setDefaultAvatarImage(TUIThemeManager.getAttrResId(mContext, com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_user_icon));
TUIConfig.setDefaultGroupAvatarImage(TUIThemeManager.getAttrResId(mContext, com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_group_icon_work));
}
public static void initChatSettings() {
if (BrandUtil.isSamsungS9Series()) {
TUIChatConfigClassic.setUseSystemCamera(true);
TUIChatConfigMinimalist.setUseSystemCamera(true);
}
}
}
package com.duben.roseplaylet.im;
import android.text.TextUtils;
import android.util.Base64;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.zip.Deflater;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* Module: GenerateTestUserSig
*
* Function: Used to generate UserSig for testing. UserSig is a security signature designed by Tencent Cloud for its cloud services.
* It is calculated based on SDKAppID, UserID, and EXPIRETIME using the HMAC-SHA256 encryption algorithm.
*
* Attention: Do not use the code below in your commercial application. This is because:
*
* The code may be able to calculate UserSig correctly, but it is only for quick testing of the SDK’s basic features, not for commercial applications.
* SECRETKEY in client code can be easily decompiled and reversed, especially on web.
* Once your key is disclosed, attackers will be able to steal your Tencent Cloud traffic.
*
* The correct method is to deploy the UserSig calculation code and encryption key on your project server so that your application can request from your server a UserSig that is calculated whenever one is needed.
* Given that it is more difficult to hack a server than a client application, server-end calculation can better protect your key.
*
* Reference: https://intl.cloud.tencent.com/document/product/1047/34385
*/
public class GenerateTestUserSig {
/**
* Tencent Cloud SDKAppID. Set it to the SDKAppID of your account.
* <p>
* You can view your SDKAppID after creating an application in the [Tencent Cloud IM console](https://console.intl.cloud.tencent.com/im).
* SDKAppID uniquely identifies a Tencent Cloud account.
*/
public static final int SDKAPPID = 1600069405;
/**
* Signature validity period, which should not be set too short
* <p>
* Time unit: second
* Default value: 604800 (7 days)
*/
private static final int EXPIRETIME = 604800;
/**
* Follow the steps below to obtain the key required for UserSig calculation.
* <p>
* Step 1. Log in to the [Tencent Cloud IM console](https://console.intl.cloud.tencent.com/im), and create an application if you don’t have one.
* Step 2. Click Application Configuration to go to the basic configuration page and locate Account System Integration.
* Step 3. Click View Key to view the encrypted key used for UserSig calculation. Then copy and paste the key to the variable below.
* <p>
* Note: this method is for testing only. Before commercial launch, please migrate the UserSig calculation code and key to your backend server to prevent key disclosure and traffic stealing.
* Reference: https://intl.cloud.tencent.com/document/product/1047/34385
*/
private static final String SECRETKEY = "aa890ec2ba5679ae35f857288ce75ec9cfeee9715fd31682977a7bda7824d08c";
/**
* Calculate UserSig
* <p>
* The asymmetric encryption algorithm HMAC-SHA256 is used in the function to calculate UserSig based on SDKAppID, UserID, and EXPIRETIME.
*
* @note: Do not use the code below in your commercial application. This is because:
* <p>
* The code may be able to calculate UserSig correctly, but it is only for quick testing of the SDK’s basic features, not for commercial applications.
* SECRETKEY in client code can be easily decompiled and reversed, especially on web.
* Once your key is disclosed, attackers will be able to steal your Tencent Cloud traffic.
* <p>
* The correct method is to deploy the UserSig calculation code and encryption key on your project server so that your application can request from your server a UserSig that is calculated whenever one is needed.
* Given that it is more difficult to hack a server than a client application, server-end calculation can better protect your key.
* <p>
* Reference: https://intl.cloud.tencent.com/document/product/1047/34385
*/
public static String genTestUserSig(String userId) {
return GenTLSSignature(SDKAPPID, userId, EXPIRETIME, null, SECRETKEY);
}
/**
* Generate a TLS ticket
*
* @param sdkappid AppID of the application
* @param userId User ID
* @param expire Validity period, in seconds
* @param userbuf null by default
* @param priKeyContent Private key required for generating a TLS ticket
* @return If an error occurs, an empty string will be returned or exceptions printed. If the operation succeeds, a valid ticket will be returned.
*/
private static String GenTLSSignature(long sdkappid, String userId, long expire, byte[] userbuf, String priKeyContent) {
if (TextUtils.isEmpty(priKeyContent)) {
return "";
}
long currTime = System.currentTimeMillis() / 1000;
JSONObject sigDoc = new JSONObject();
try {
sigDoc.put("TLS.ver", "2.0");
sigDoc.put("TLS.identifier", userId);
sigDoc.put("TLS.sdkappid", sdkappid);
sigDoc.put("TLS.expire", expire);
sigDoc.put("TLS.time", currTime);
} catch (JSONException e) {
e.printStackTrace();
}
String base64UserBuf = null;
if (null != userbuf) {
base64UserBuf = Base64.encodeToString(userbuf, Base64.NO_WRAP);
try {
sigDoc.put("TLS.userbuf", base64UserBuf);
} catch (JSONException e) {
e.printStackTrace();
}
}
String sig = hmacsha256(sdkappid, userId, currTime, expire, priKeyContent, base64UserBuf);
if (sig.length() == 0) {
return "";
}
try {
sigDoc.put("TLS.sig", sig);
} catch (JSONException e) {
e.printStackTrace();
}
Deflater compressor = new Deflater();
compressor.setInput(sigDoc.toString().getBytes(Charset.forName("UTF-8")));
compressor.finish();
byte[] compressedBytes = new byte[2048];
int compressedBytesLength = compressor.deflate(compressedBytes);
compressor.end();
return new String(base64EncodeUrl(Arrays.copyOfRange(compressedBytes, 0, compressedBytesLength)));
}
private static String hmacsha256(long sdkappid, String userId, long currTime, long expire, String priKeyContent, String base64Userbuf) {
String contentToBeSigned = "TLS.identifier:" + userId + "\n"
+ "TLS.sdkappid:" + sdkappid + "\n"
+ "TLS.time:" + currTime + "\n"
+ "TLS.expire:" + expire + "\n";
if (null != base64Userbuf) {
contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
}
try {
byte[] byteKey = priKeyContent.getBytes("UTF-8");
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
hmac.init(keySpec);
byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes("UTF-8"));
return new String(Base64.encode(byteSig, Base64.NO_WRAP));
} catch (UnsupportedEncodingException e) {
return "";
} catch (NoSuchAlgorithmException e) {
return "";
} catch (InvalidKeyException e) {
return "";
}
}
private static byte[] base64EncodeUrl(byte[] input) {
byte[] base64 = new String(Base64.encode(input, Base64.NO_WRAP)).getBytes();
for (int i = 0; i < base64.length; ++i)
switch (base64[i]) {
case '+':
base64[i] = '*';
break;
case '/':
base64[i] = '-';
break;
case '=':
base64[i] = '_';
break;
default:
break;
}
return base64;
}
}
package com.duben.roseplaylet.im;
public interface HandleOfflinePushCallBack {
void onHandleOfflinePush(boolean hasLogged);
}
\ No newline at end of file
package com.duben.roseplaylet.im;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.text.TextUtils;
import android.util.Log;
import com.duben.roseplaylet.R;
import com.duben.roseplaylet.common.AppConfig;
import com.duben.roseplaylet.im.push.OfflinePushAPIDemo;
import com.duben.roseplaylet.im.push.OfflinePushConfigs;
import com.duben.roseplaylet.im.push.OfflinePushLocalReceiver;
import com.duben.roseplaylet.utils.LogUtil;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMValueCallback;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuicore.util.ErrorMessageConverter;
import com.tencent.qcloud.tuicore.util.PermissionRequester;
import com.tencent.qcloud.tuikit.tuichat.TUIChatConstants;
import com.tencent.qcloud.tuikit.tuichat.config.TUIChatConfigs;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class InitSetting {
private static final String TAG = InitSetting.class.getSimpleName();
public Context mContext;
private OfflinePushAPIDemo offlinePushAPIDemo;
private OfflinePushLocalReceiver offlinePushLocalReceiver = null;
public InitSetting(Context context) {
this.mContext = context;
}
public void init() {
// add Demo theme
// TUIThemeManager.addLightTheme(R.style.DemoLightTheme);
// TUIThemeManager.addLivelyTheme(R.style.DemoLivelyTheme);
// TUIThemeManager.addSeriousTheme(R.style.DemoSeriousTheme);
setPermissionRequestContent();
TUIChatConfigs.getGeneralConfig().setEnableMultiDeviceForCall(true);
TUIChatConfigs.getGeneralConfig().setEnableVirtualBackgroundForCall(true);
CustomConfigHelper.initCustom(mContext);
initOfflinePushConfigs();
initDemoStyle();
}
private void initDemoStyle() {
final SharedPreferences sharedPreferences = mContext.getSharedPreferences("TUIKIT_DEMO_SETTINGS", mContext.MODE_PRIVATE);
AppConfig.IM_UI_STYLE = sharedPreferences.getInt("tuikit_demo_style", AppConfig.IM_UI_STYLE_CLASSIC);
}
public void setPermissionRequestContent() {
if (mContext == null) {
return;
}
ApplicationInfo applicationInfo = mContext.getApplicationInfo();
CharSequence labelCharSequence = applicationInfo.loadLabel(mContext.getPackageManager());
String appName = "App";
if (!TextUtils.isEmpty(labelCharSequence)) {
appName = labelCharSequence.toString();
}
PermissionRequester.PermissionRequestContent microphoneContent = new PermissionRequester.PermissionRequestContent();
microphoneContent.setReasonTitle(mContext.getResources().getString(R.string.demo_permission_mic_reason_title, appName));
String micReason = mContext.getResources().getString(R.string.demo_permission_mic_reason);
microphoneContent.setReason(micReason);
microphoneContent.setIconResId(R.drawable.demo_permission_icon_mic);
String micDeniedAlert = mContext.getResources().getString(R.string.demo_permission_mic_dialog_alert, appName);
microphoneContent.setDeniedAlert(micDeniedAlert);
PermissionRequester.setPermissionRequestContent(PermissionRequester.PermissionConstants.MICROPHONE, microphoneContent);
PermissionRequester.PermissionRequestContent cameraContent = new PermissionRequester.PermissionRequestContent();
cameraContent.setReasonTitle(mContext.getResources().getString(R.string.demo_permission_camera_reason_title, appName));
String cameraReason = mContext.getResources().getString(R.string.demo_permission_camera_reason);
cameraContent.setReason(cameraReason);
cameraContent.setIconResId(R.drawable.demo_permission_icon_camera);
String cameraDeniedAlert = mContext.getResources().getString(R.string.demo_permission_camera_dialog_alert, appName);
cameraContent.setDeniedAlert(cameraDeniedAlert);
PermissionRequester.setPermissionRequestContent(PermissionRequester.PermissionConstants.CAMERA, cameraContent);
}
private void initOfflinePushConfigs() {
final SharedPreferences sharedPreferences = mContext.getSharedPreferences("TUIKIT_DEMO_SETTINGS", mContext.MODE_PRIVATE);
int callbackMode = sharedPreferences.getInt("test_OfflinePushCallbackMode_v2", 1);
Log.i(TAG, "initOfflinePushConfigs callbackMode = " + callbackMode);
OfflinePushConfigs.getOfflinePushConfigs().setClickNotificationCallbackMode(callbackMode);
// ring
boolean enablePrivateRing = sharedPreferences.getBoolean("test_enable_private_ring", false);
Map<String, Object> param = new HashMap<>();
param.put(TUIChatConstants.OFFLINE_MESSAGE_PRIVATE_RING, enablePrivateRing);
TUICore.notifyEvent(TUIChatConstants.EVENT_KEY_OFFLINE_MESSAGE_PRIVATE_RING, TUIChatConstants.EVENT_SUB_KEY_OFFLINE_MESSAGE_PRIVATE_RING, param);
// register callback
registerNotify();
}
// call after login success
public void registerPushManually() {
if (offlinePushAPIDemo == null) {
offlinePushAPIDemo = new OfflinePushAPIDemo();
}
offlinePushAPIDemo.registerPush(mContext);
}
// call in Application onCreate
private void registerNotify() {
if (offlinePushAPIDemo == null) {
offlinePushAPIDemo = new OfflinePushAPIDemo();
}
int callbackMode = OfflinePushConfigs.getOfflinePushConfigs().getClickNotificationCallbackMode();
Log.d(TAG, "OfflinePush callback mode:" + callbackMode);
switch (callbackMode) {
case OfflinePushConfigs.CLICK_NOTIFICATION_CALLBACK_NOTIFY:
// 1 TUICore NotifyEvent
offlinePushAPIDemo.registerNotifyEvent();
break;
case OfflinePushConfigs.CLICK_NOTIFICATION_CALLBACK_BROADCAST:
// 2 broadcast
if (offlinePushLocalReceiver == null) {
offlinePushLocalReceiver = new OfflinePushLocalReceiver();
}
offlinePushAPIDemo.registerNotificationReceiver(mContext, offlinePushLocalReceiver);
break;
default:
// 3 intent
break;
}
}
public void initBeforeLogin(int imsdkAppId) {
Log.d(TAG, "initBeforeLogin sdkAppid = " + imsdkAppId);
initBuildInformation();
int sdkAppId = 0;
if (imsdkAppId != 0) {
sdkAppId = imsdkAppId;
} else {
sdkAppId = GenerateTestUserSig.SDKAPPID;;
}
AppConfig.IM_SDK_APPID = sdkAppId;
}
private void initBuildInformation() {
try {
JSONObject buildInfoJson = new JSONObject();
buildInfoJson.put("buildBrand", BrandUtil.getBuildBrand());
buildInfoJson.put("buildManufacturer", BrandUtil.getBuildManufacturer());
buildInfoJson.put("buildModel", BrandUtil.getBuildModel());
buildInfoJson.put("buildVersionRelease", BrandUtil.getBuildVersionRelease());
buildInfoJson.put("buildVersionSDKInt", BrandUtil.getBuildVersionSDKInt());
// The Ministry of Industry and Information Technology requires the app to obtain device information only once
// during its operation. Therefore, after the app obtains the device information and sets it to the SDK, the SDK
// uses this value and no longer calls the system interface.
V2TIMManager.getInstance().callExperimentalAPI("setBuildInfo", buildInfoJson.toString(), new V2TIMValueCallback<Object>() {
@Override
public void onSuccess(Object o) {
LogUtil.i(TAG, "setBuildInfo success");
}
@Override
public void onError(int code, String desc) {
LogUtil.i(TAG, "setBuildInfo code:" + code + " desc:" + ErrorMessageConverter.convertIMError(code, desc));
}
});
} catch (JSONException e) {
e.printStackTrace();
}
}
}
package com.duben.roseplaylet.im;
import android.content.Context;
import android.text.TextUtils;
import com.duben.roseplaylet.common.AppConfig;
import com.duben.roseplaylet.utils.LogUtil;
import com.tencent.imsdk.BaseConstants;
import com.tencent.imsdk.v2.V2TIMConversationListener;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMSDKListener;
import com.tencent.qcloud.tuicore.TUILogin;
import com.tencent.qcloud.tuicore.interfaces.TUICallback;
import com.tencent.qcloud.tuicore.interfaces.TUILoginConfig;
import com.tencent.qcloud.tuikit.timcommon.util.ThreadUtils;
import java.util.ArrayList;
import java.util.List;
public class LoginWrapper {
private static final String TAG = LoginWrapper.class.getSimpleName();
private static class LoginWrapperHolder {
private static final LoginWrapper loginInstance = new LoginWrapper();
}
public static LoginWrapper getInstance() {
return LoginWrapperHolder.loginInstance;
}
private V2TIMSDKListener v2TIMSDKListener;
private V2TIMConversationListener v2TIMConversationListener;
private List<AppLoginListener> appLoginObservers = new ArrayList<>();
private LoginWrapper() {
initIMSDKObserver();
}
private void initIMSDKObserver() {
if (v2TIMSDKListener == null) {
v2TIMSDKListener = new V2TIMSDKListener() {
@Override
public void onConnecting() {
for (AppLoginListener listener : appLoginObservers) {
listener.onConnecting();
}
}
@Override
public void onConnectSuccess() {
for (AppLoginListener listener : appLoginObservers) {
listener.onConnectSuccess();
}
tryToAutoLogin();
}
@Override
public void onConnectFailed(int code, String error) {
for (AppLoginListener listener : appLoginObservers) {
listener.onConnectFailed(code, error);
}
}
@Override
public void onUserSigExpired() {
for (AppLoginListener listener : appLoginObservers) {
listener.onUserSigExpired();
}
}
};
}
if (v2TIMConversationListener == null) {
v2TIMConversationListener = new V2TIMConversationListener() {
@Override
public void onSyncServerStart() {
for (AppLoginListener listener : appLoginObservers) {
listener.onSyncServerStart();
}
}
@Override
public void onSyncServerFinish() {
for (AppLoginListener listener : appLoginObservers) {
listener.onSyncServerFinish();
}
}
@Override
public void onSyncServerFailed() {
for (AppLoginListener listener : appLoginObservers) {
listener.onSyncServerFailed();
}
}
};
}
V2TIMManager.getInstance().addIMSDKListener(v2TIMSDKListener);
V2TIMManager.getConversationManager().addConversationListener(v2TIMConversationListener);
}
public void addAppLoginObserver(final AppLoginListener observer) {
if (observer == null) {
return;
}
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
if (!appLoginObservers.contains(observer)) {
appLoginObservers.add(observer);
}
}
});
}
public void removeLoginObserver(AppLoginListener observer) {
if (observer == null) {
return;
}
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
appLoginObservers.remove(observer);
}
});
}
public void loginIMSDK(Context context, int sdkAppID, String userID, String userSig, final TUILoginConfig config, TUICallback tuiCallback) {
TUILogin.login(context, sdkAppID, userID, userSig, config, new TUICallback() {
@Override
public void onError(final int code, final String desc) {
UserInfo.getInstance().setLastLoginCode(code);
if (tuiCallback != null) {
tuiCallback.onError(code, desc);
}
}
@Override
public void onSuccess() {
if (config == null || false == config.isInitLocalStorageOnly()) {
UserInfo.getInstance().setLastLoginCode(BaseConstants.ERR_SUCC);
}
if (tuiCallback != null) {
tuiCallback.onSuccess();
}
}
});
}
private void tryToAutoLogin() {
int loginStatus = V2TIMManager.getInstance().getLoginStatus();
int lastLoginCode = UserInfo.getInstance().getLastLoginCode();
UserInfo userInfo = UserInfo.getInstance();
if (loginStatus == V2TIMManager.V2TIM_STATUS_LOGOUT && !TextUtils.isEmpty(userInfo.getUserId()) && userInfo.isAutoLogin()) {
if (lastLoginCode >= BaseConstants.ERR_SDK_NET_ENCODE_FAILED && lastLoginCode <= BaseConstants.ERR_SDK_NET_SEND_REMAINING_TIMEOUT_NO_NETWORK) {
LogUtil.i(TAG, "onConnectSuccess, login IMSDK");
loginIMSDK(TIMAppService.getAppContext(), AppConfig.IM_SDK_APPID, userInfo.getUserId(), userInfo.getUserSig(), TUIUtils.getLoginConfig(),
new TUICallback() {
@Override
public void onSuccess() {
// do nothing
}
@Override
public void onError(int errorCode, String errorMessage) {
UserInfo.getInstance().setLastLoginCode(errorCode);
LogUtil.e(TAG, "tryToAutoLogin error:" + errorCode);
if (errorCode < BaseConstants.ERR_SDK_NET_ENCODE_FAILED
|| errorCode > BaseConstants.ERR_SDK_NET_SEND_REMAINING_TIMEOUT_NO_NETWORK) {
if (AppConfig.IM_UI_STYLE == AppConfig.IM_UI_STYLE_CLASSIC) {
// MainActivity.finishMainActivity();
} else {
// MainMinimalistActivity.finishMainActivity();
}
TIMAppService.getInstance().startLoginActivity();
}
}
});
}
}
}
public abstract static class AppLoginListener {
public void onConnecting() {}
public void onConnectSuccess() {}
public void onConnectFailed(int code, String error) {}
public void onUserSigExpired() {}
public void onSyncServerStart() {}
public void onSyncServerFinish() {}
public void onSyncServerFailed() {}
}
}
package com.duben.roseplaylet.im;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.duben.roseplaylet.R;
import com.duben.roseplaylet.common.AppConfig;
import com.duben.roseplaylet.utils.LogUtil;
import com.google.auto.service.AutoService;
import com.tencent.qcloud.tuicore.ServiceInitializer;
import com.tencent.qcloud.tuicore.TUILogin;
import com.tencent.qcloud.tuicore.annotations.TUIInitializerDependency;
import com.tencent.qcloud.tuicore.annotations.TUIInitializerID;
import com.tencent.qcloud.tuicore.interfaces.ITUIService;
import com.tencent.qcloud.tuicore.interfaces.TUICallback;
import com.tencent.qcloud.tuicore.interfaces.TUIInitializer;
import com.tencent.qcloud.tuicore.interfaces.TUILoginListener;
import com.tencent.qcloud.tuicore.util.ToastUtil;
@AutoService(TUIInitializer.class)
@TUIInitializerDependency("TIMCommon")
@TUIInitializerID("TIMAppService")
public class TIMAppService implements TUIInitializer, ITUIService {
public static final String TAG = TIMAppService.class.getSimpleName();
private static TIMAppService instance;
public static TIMAppService getInstance() {
return instance;
}
public Context mContext;
private BroadcastReceiver languageChangedReceiver;
private BroadcastReceiver themeChangedReceiver;
private InitSetting initSetting;
@Override
public void init(Context context) {
instance = this;
mContext = context;
initSetting = new InitSetting(mContext);
initSetting.init();
initThemeAndLanguageChangedReceiver();
initLoginStatusListener();
}
public void initLoginStatusListener() {
TUILogin.addLoginListener(loginStatusListener);
}
private final TUILoginListener loginStatusListener = new TUILoginListener() {
@Override
public void onKickedOffline() {
// ToastUtil.toastLongMessage(getAppContext().getString(R.string.repeat_login_tip));
logout();
}
@Override
public void onUserSigExpired() {
// ToastUtil.toastLongMessage(getAppContext().getString(R.string.expired_login_tip));
TUILogin.logout(new TUICallback() {
@Override
public void onSuccess() {
logout();
}
@Override
public void onError(int errorCode, String errorMessage) {
logout();
}
});
}
};
public void logout() {
LogUtil.i(TAG, "logout");
UserInfo.getInstance().cleanUserInfo();
// Intent intent = new Intent(getAppContext(), LoginForDevActivity.class);
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// intent.putExtra("LOGOUT", true);
// getAppContext().startActivity(intent);
if (AppConfig.IM_SDK_APPID == AppConfig.IM_UI_STYLE_CLASSIC) {
// MainActivity.finishMainActivity();
} else {
// MainMinimalistActivity.finishMainActivity();
}
}
private void initThemeAndLanguageChangedReceiver() {
languageChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
initSetting.setPermissionRequestContent();
}
};
themeChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
CustomConfigHelper.initConversationDefaultAvatar();
}
};
// IntentFilter languageFilter = new IntentFilter();
// languageFilter.addAction(Constant.DEMO_LANGUAGE_CHANGED_ACTION);
// LocalBroadcastManager.getInstance(mContext).registerReceiver(languageChangedReceiver, languageFilter);
//
// IntentFilter themeFilter = new IntentFilter();
// themeFilter.addAction(Constant.DEMO_THEME_CHANGED_ACTION);
// LocalBroadcastManager.getInstance(mContext).registerReceiver(themeChangedReceiver, themeFilter);
}
public void registerPushManually() {
if (initSetting == null) {
initSetting = new InitSetting(mContext);
}
initSetting.registerPushManually();
}
public void initBeforeLogin(int sdkappid) {
if (initSetting == null) {
initSetting = new InitSetting(mContext);
}
initSetting.initBeforeLogin(sdkappid);
}
public void startLoginActivity() {
// Intent intent = new Intent(mContext, LoginForDevActivity.class);
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// mContext.startActivity(intent);
}
public static Context getAppContext() {
return ServiceInitializer.getAppContext();
}
}
package com.duben.roseplaylet.im;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import com.duben.roseplaylet.common.AppConfig;
import com.duben.roseplaylet.im.push.OfflineMessageDispatcher;
import com.duben.roseplaylet.utils.LogUtil;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.qcloud.tuicore.TUIConfig;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuicore.interfaces.TUILoginConfig;
import com.tencent.qcloud.tuicore.push.OfflinePushExtInfo;
import com.tencent.qcloud.tuicore.util.TUIBuild;
import com.tencent.qcloud.tuikit.timcommon.BuildConfig;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class TUIUtils {
private static final String TAG = TUIUtils.class.getSimpleName();
public static String offlineData = null;
private static boolean hasTryToLogin = false;
public static void startActivity(String activityName, Bundle param) {
TUICore.startActivity(activityName, param);
}
public static void startChat(String chatId, String chatName, int chatType) {
Bundle bundle = new Bundle();
bundle.putString(TUIConstants.TUIChat.CHAT_ID, chatId);
bundle.putString(TUIConstants.TUIChat.CHAT_NAME, chatName);
bundle.putInt(TUIConstants.TUIChat.CHAT_TYPE, chatType);
if (AppConfig.IM_UI_STYLE == AppConfig.IM_UI_STYLE_CLASSIC) {
if (chatType == V2TIMConversation.V2TIM_C2C) {
TUICore.startActivity(TUIConstants.TUIChat.C2C_CHAT_ACTIVITY_NAME, bundle);
} else if (chatType == V2TIMConversation.V2TIM_GROUP) {
TUICore.startActivity(TUIConstants.TUIChat.GROUP_CHAT_ACTIVITY_NAME, bundle);
}
} else {
if (chatType == V2TIMConversation.V2TIM_C2C) {
TUICore.startActivity("TUIC2CChatMinimalistActivity", bundle);
} else if (chatType == V2TIMConversation.V2TIM_GROUP) {
TUICore.startActivity("TUIGroupChatMinimalistActivity", bundle);
}
}
}
public static boolean isZh(Context context) {
Locale locale = null;
if (TUIBuild.getVersionInt() < Build.VERSION_CODES.N) {
locale = context.getResources().getConfiguration().locale;
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
locale = context.getResources().getConfiguration().getLocales().get(0);
}
}
String language = locale.getLanguage();
return language.endsWith("zh");
}
public static int getCurrentVersionCode(Context context) {
try {
return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
} catch (PackageManager.NameNotFoundException ignored) {
LogUtil.e(TAG, "getCurrentVersionCode exception= " + ignored);
}
return 0;
}
public static void handleOfflinePush(Intent intent, HandleOfflinePushCallBack callBack) {
Context context = TIMAppService.getAppContext();
if (V2TIMManager.getInstance().getLoginStatus() == V2TIMManager.V2TIM_STATUS_LOGOUT) {
if (TUIConfig.getTUIHostType() == TUIConfig.TUI_HOST_TYPE_RTCUBE) {
LogUtil.e(TAG, "rtcube not logined");
Map<String, Object> param = new HashMap<>();
param.put(TUIConstants.TIMAppKit.OFFLINE_PUSH_INTENT_DATA, intent);
TUICore.notifyEvent(TUIConstants.TIMAppKit.NOTIFY_RTCUBE_EVENT_KEY, TUIConstants.TIMAppKit.NOTIFY_RTCUBE_LOGIN_SUB_KEY, param);
return;
}
Intent intentAction = new Intent();
intentAction.setAction("com.tencent.qloud.splash");
intentAction.addCategory("android.intent.category.LAUNCHER");
intentAction.addCategory("android.intent.category.DEFAULT");
if (intent != null) {
intentAction.putExtras(intent);
}
intentAction.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentAction);
if (callBack != null) {
callBack.onHandleOfflinePush(false);
}
return;
}
final OfflinePushExtInfo offlinePushExtInfo = OfflineMessageDispatcher.parseOfflineMessage(intent);
if (offlinePushExtInfo != null) {
if (callBack != null) {
callBack.onHandleOfflinePush(true);
}
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null) {
manager.cancelAll();
}
String senderId = offlinePushExtInfo.getBusinessInfo().getSenderId();
if (offlinePushExtInfo.getBusinessInfo().getChatAction() == OfflinePushExtInfo.REDIRECT_ACTION_CHAT) {
if (TextUtils.isEmpty(senderId)) {
return;
}
TUIUtils.startChat(senderId, offlinePushExtInfo.getBusinessInfo().getSenderNickName(), offlinePushExtInfo.getBusinessInfo().getChatType());
}
}
}
public static void handleOfflinePush(String ext, HandleOfflinePushCallBack callBack) {
LogUtil.d(TAG, "handleOfflinePush ext = " + ext);
final OfflinePushExtInfo offlinePushExtInfo = OfflineMessageDispatcher.getOfflinePushExtInfo(ext);
if (offlinePushExtInfo == null) {
return;
}
Context context = TIMAppService.getAppContext();
if (V2TIMManager.getInstance().getLoginStatus() == V2TIMManager.V2TIM_STATUS_LOGOUT && !hasTryToLogin) {
hasTryToLogin = true;
if (TUIConfig.getTUIHostType() == TUIConfig.TUI_HOST_TYPE_RTCUBE) {
offlineData = ext;
TUICore.notifyEvent(TUIConstants.TIMAppKit.NOTIFY_RTCUBE_EVENT_KEY, TUIConstants.TIMAppKit.NOTIFY_RTCUBE_LOGIN_SUB_KEY, null);
return;
}
Intent intentAction = new Intent();
intentAction.setAction("com.tencent.qloud.splash");
intentAction.addCategory("android.intent.category.LAUNCHER");
intentAction.addCategory("android.intent.category.DEFAULT");
if (!TextUtils.isEmpty(ext)) {
intentAction.putExtra(TUIConstants.TIMPush.NOTIFICATION_EXT_KEY, ext);
}
intentAction.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentAction);
if (callBack != null) {
callBack.onHandleOfflinePush(false);
}
return;
}
if (callBack != null) {
callBack.onHandleOfflinePush(true);
}
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null) {
manager.cancelAll();
}
String senderId = offlinePushExtInfo.getBusinessInfo().getSenderId();
if (offlinePushExtInfo.getBusinessInfo().getChatAction() == OfflinePushExtInfo.REDIRECT_ACTION_CHAT) {
if (TextUtils.isEmpty(senderId)) {
return;
}
TUIUtils.startChat(senderId, offlinePushExtInfo.getBusinessInfo().getSenderNickName(), offlinePushExtInfo.getBusinessInfo().getChatType());
}
}
public static TUILoginConfig getLoginConfig() {
TUILoginConfig config = new TUILoginConfig();
if (BuildConfig.DEBUG) {
config.setLogLevel(TUILoginConfig.TUI_LOG_DEBUG);
}
return config;
}
}
package com.duben.roseplaylet.im;
import android.content.SharedPreferences;
import com.duben.roseplaylet.common.Constant;
import com.google.gson.Gson;
import com.tencent.imsdk.BaseConstants;
import java.io.Serializable;
public class UserInfo implements Serializable {
private final static String PER_USER_MODEL = "per_user_model";
private static UserInfo sUserInfo;
private int sdkAppId;
private String zone;
private String phone;
private String token;
private String userId;
private String userSig;
private String name;
private String avatar;
private boolean autoLogin;
private boolean debugLogin = false;
private int lastLoginCode = BaseConstants.ERR_SUCC;
public synchronized static UserInfo getInstance() {
if (sUserInfo == null) {
SharedPreferences shareInfo = TIMAppService.getAppContext().getSharedPreferences(Constant.USERINFO, 0);
String json = shareInfo.getString(PER_USER_MODEL, "");
sUserInfo = new Gson().fromJson(json, UserInfo.class);
if (sUserInfo == null) {
sUserInfo = new UserInfo();
}
}
return sUserInfo;
}
private UserInfo() {}
public void setUserInfo(UserInfo info) {
SharedPreferences shareInfo = TIMAppService.getAppContext().getSharedPreferences(Constant.USERINFO, 0);
SharedPreferences.Editor editor = shareInfo.edit();
editor.putString(PER_USER_MODEL, new Gson().toJson(info));
editor.commit();
}
public int getSdkAppId() {
return sdkAppId;
}
public void setSdkAppId(int sdkAppId) {
this.sdkAppId = sdkAppId;
}
public String getUserSig() {
return this.userSig;
}
public void setUserSig(String userSig) {
this.userSig = userSig;
setUserInfo(this);
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
setUserInfo(this);
}
public String getUserId() {
return this.userId;
}
public void setUserId(String userId) {
this.userId = userId;
setUserInfo(this);
}
public String getToken() {
return this.token;
}
public void setToken(String token) {
this.token = token;
setUserInfo(this);
}
public String getZone() {
return this.zone;
}
public void setZone(String zone) {
this.zone = zone;
setUserInfo(this);
}
public String getPhone() {
return this.phone;
}
public void setPhone(String userPhone) {
this.phone = userPhone;
setUserInfo(this);
}
public Boolean isAutoLogin() {
return this.autoLogin;
}
public void setAutoLogin(boolean autoLogin) {
this.autoLogin = autoLogin;
setUserInfo(this);
}
public String getAvatar() {
return this.avatar;
}
public void setAvatar(String url) {
this.avatar = url;
setUserInfo(this);
}
public void setDebugLogin(boolean debugLogin) {
this.debugLogin = debugLogin;
setUserInfo(this);
}
public boolean isDebugLogin() {
return debugLogin;
}
public int getLastLoginCode() {
return lastLoginCode;
}
public void setLastLoginCode(int lastLoginCode) {
this.lastLoginCode = lastLoginCode;
setUserInfo(this);
}
public void cleanUserInfo() {
sdkAppId = 0;
zone = "";
token = "";
userId = "";
userSig = "";
name = "";
avatar = "";
autoLogin = false;
lastLoginCode = BaseConstants.ERR_SUCC;
setUserInfo(this);
}
}
package com.duben.roseplaylet.im.push;
public interface HandleOfflinePushCallBack {
void onHandleOfflinePush(boolean hasLogged);
}
\ No newline at end of file
package com.duben.roseplaylet.im.push;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;
import com.duben.roseplaylet.R;
import com.duben.roseplaylet.im.BrandUtil;
import com.duben.roseplaylet.im.TIMAppService;
import com.duben.roseplaylet.utils.LogUtil;
import com.google.gson.Gson;
import com.tencent.qcloud.tuicore.push.OfflinePushExtBusinessInfo;
import com.tencent.qcloud.tuicore.push.OfflinePushExtInfo;
import com.tencent.qcloud.tuicore.util.ToastUtil;
import java.util.Map;
import java.util.Set;
public class OfflineMessageDispatcher {
private static final String TAG = OfflineMessageDispatcher.class.getSimpleName();
private static final String OEMMessageKey = "ext";
private static final String XIAOMIMessageKey = "key_message";
public static OfflinePushExtInfo parseOfflineMessage(Intent intent) {
LogUtil.i(TAG, "intent: " + intent);
if (intent == null) {
return null;
}
LogUtil.i(TAG, "parse OEM push");
Bundle bundle = intent.getExtras();
LogUtil.i(TAG, "bundle: " + bundle);
if (bundle == null) {
LogUtil.i(TAG, "bundle is null");
return null;
} else {
String ext = bundle.getString(OEMMessageKey);
LogUtil.i(TAG, "push custom data ext: " + ext);
if (TextUtils.isEmpty(ext)) {
if (BrandUtil.isBrandXiaoMi()) {
ext = getXiaomiMessage(bundle);
return getOfflinePushExtInfo(ext);
} else if (BrandUtil.isBrandOppo()) {
ext = getOPPOMessage(bundle);
return getOPPOOfflinePushExtInfo(ext);
}
LogUtil.i(TAG, "ext is null");
return null;
} else {
return getOfflinePushExtInfo(ext);
}
}
}
private static String getXiaomiMessage(Bundle bundle) {
Map extra = null;
try {
Object objectMessage = bundle.getSerializable(XIAOMIMessageKey);
extra = (Map) objectMessage.getClass().getMethod("getExtra").invoke(objectMessage);
} catch (Exception e) {
LogUtil.e(TAG, "getXiaomiMessage e = " + e);
}
if (extra == null) {
LogUtil.e(TAG, "getXiaomiMessage is null");
return "";
}
LogUtil.i(TAG, "getXiaomiMessage ext: " + extra.get("ext").toString());
return extra.get("ext").toString();
}
private static String getOPPOMessage(Bundle bundle) {
Set<String> set = bundle.keySet();
if (set != null) {
for (String key : set) {
Object value = bundle.get(key);
LogUtil.i(TAG, "push custom data key: " + key + " value: " + value);
if (TextUtils.equals("entity", key)) {
return value.toString();
}
}
}
return null;
}
public static OfflinePushExtInfo getOfflinePushExtInfo(String ext) {
if (TextUtils.isEmpty(ext)) {
return null;
}
OfflinePushExtInfo offlinePushExtInfo = null;
try {
offlinePushExtInfo = new Gson().fromJson(ext, OfflinePushExtInfo.class);
} catch (Exception e) {
LogUtil.w(TAG, "getOfflinePushExtInfo: " + e.getMessage());
}
if (offlinePushExtInfo == null) {
return null;
}
// getCustomData example
/*byte[] byteData = offlinePushExtInfo.getEntity().getCustomData();
String customString = "";
if (byteData != null && byteData.length > 0) {
try {
customString = new String(byteData, "UTF-8");
} catch (UnsupportedEncodingException e) {
LogUtil.w(TAG, "getCustomData e: " + e);
}
}
LogUtil.e(TAG, "customString = " + customString);
ChatInfo chatInfo = null;
try{
chatInfo = new Gson().fromJson(customString, ChatInfo.class);
} catch (Exception e) {
LogUtil.w(TAG, "getCustomData fromJson e: " + e);
}*/
return OfflinePushExtInfoValidCheck(offlinePushExtInfo);
}
private static OfflinePushExtInfo getOPPOOfflinePushExtInfo(String ext) {
if (TextUtils.isEmpty(ext)) {
return null;
}
OfflinePushExtInfo offlinePushExtInfo = new OfflinePushExtInfo();
OfflinePushExtBusinessInfo bean = null;
try {
bean = new Gson().fromJson(ext, OfflinePushExtBusinessInfo.class);
} catch (Exception e) {
LogUtil.w(TAG, "getOPPOOfflinePushExtInfo: " + e.getMessage());
}
if (bean == null) {
return null;
}
offlinePushExtInfo.setBusinessInfo(bean);
return OfflinePushExtInfoValidCheck(offlinePushExtInfo);
}
private static OfflinePushExtInfo OfflinePushExtInfoValidCheck(OfflinePushExtInfo offlinePushExtInfo) {
if (offlinePushExtInfo == null || offlinePushExtInfo.getBusinessInfo() == null) {
return null;
}
int version = offlinePushExtInfo.getBusinessInfo().getVersion();
int action = offlinePushExtInfo.getBusinessInfo().getChatAction();
if (version != 1 || (action != OfflinePushExtInfo.REDIRECT_ACTION_CHAT && action != OfflinePushExtInfo.REDIRECT_ACTION_CALL)) {
PackageManager packageManager = TIMAppService.getAppContext().getPackageManager();
String label = String.valueOf(packageManager.getApplicationLabel(TIMAppService.getAppContext().getApplicationInfo()));
ToastUtil.toastLongMessage(
TIMAppService.getAppContext().getString(R.string.app_name) + label + TIMAppService.getAppContext().getString(R.string.app_name));
LogUtil.e(TAG, "unknown version: " + version + " or action: " + action);
return null;
}
return offlinePushExtInfo;
}
}
package com.duben.roseplaylet.im.push;
import android.content.Context;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.duben.roseplaylet.common.AppConfig;
import com.duben.roseplaylet.common.Constant;
import com.duben.roseplaylet.im.TUIUtils;
import com.duben.roseplaylet.utils.LogUtil;
import com.google.gson.Gson;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuicore.interfaces.ITUINotification;
import com.tencent.qcloud.tuicore.interfaces.TUIServiceCallback;
import com.tencent.qcloud.tuikit.tuichat.util.OfflinePushInfoUtils;
import java.util.HashMap;
import java.util.Map;
public class OfflinePushAPIDemo {
public static final String TAG = OfflinePushAPIDemo.class.getSimpleName();
/**
* Register offline push service, called when IM account login is successful.Calling this interface does not require filling parameters into the
* component's PrivateConstants.
*
* @note json:
* {
* // huawei
* "huaweiPushBussinessId": "",
* "huaweiBadgeClassName": "",
* launcher interface
*
* // xiaomi
* "xiaomiPushBussinessId": "",
* "xiaomiPushAppId": "",
* "xiaomiPushAppKey": "",
*
* // meizu
* "meizuPushBussinessId": "",
* "meizuPushAppId": "",
* "meizuPushAppKey": "",
*
* // vivo
* "vivoPushBussinessId": "",
*
* // google
* "fcmPushBussinessId": "",
*
* // oppo
* "oppoPushBussinessId": "",
* "oppoPushAppKey": "",
* "oppoPushAppSecret": "",
*
* // honor
* "honorPushBussinessId": "",
* }
*
*/
public void registerPush(Context context) {
OfflinePushParamBean offlinePushParamBean = new OfflinePushParamBean();
String huaweiBussinessId, xiaomiBussinessId, meizuBussinessId, vivoBussinessId, oppoBussinessId;
String fcmBussinessId, honorBussinessId;
int callbackMode = OfflinePushConfigs.getOfflinePushConfigs().getClickNotificationCallbackMode();
Log.d(TAG, "OfflinePush callback mode:" + callbackMode);
if (callbackMode == OfflinePushConfigs.CLICK_NOTIFICATION_CALLBACK_NOTIFY ||
callbackMode == OfflinePushConfigs.CLICK_NOTIFICATION_CALLBACK_BROADCAST) {
if (TextUtils.equals(AppConfig.IM_FLAVOR_VERSION, Constant.FLAVOR_INTERNATIONAL)) {
huaweiBussinessId = "";
xiaomiBussinessId = "";
meizuBussinessId = "";
vivoBussinessId = "";
oppoBussinessId = "";
fcmBussinessId = "";
honorBussinessId = "";
} else {
huaweiBussinessId = "";
xiaomiBussinessId = "";
meizuBussinessId = "";
vivoBussinessId = "";
oppoBussinessId = "";
fcmBussinessId = "";
honorBussinessId = "";
}
} else {
if (TextUtils.equals(AppConfig.IM_FLAVOR_VERSION, Constant.FLAVOR_INTERNATIONAL)) {
huaweiBussinessId = "";
xiaomiBussinessId = "";
meizuBussinessId = "";
vivoBussinessId = "";
oppoBussinessId = "";
fcmBussinessId = "";
honorBussinessId = "";
} else {
huaweiBussinessId = "";
xiaomiBussinessId = "";
meizuBussinessId = "";
vivoBussinessId = "";
oppoBussinessId = "";
fcmBussinessId = "";
honorBussinessId = "";
}
}
offlinePushParamBean.setHuaweiPushBussinessId(huaweiBussinessId);
offlinePushParamBean.setHuaweiBadgeClassName("com.tencent.qcloud.tim.demo.SplashActivity");
offlinePushParamBean.setXiaomiPushBussinessId(xiaomiBussinessId);
offlinePushParamBean.setXiaomiPushAppId("");
offlinePushParamBean.setXiaomiPushAppKey("");
offlinePushParamBean.setMeizuPushBussinessId(meizuBussinessId);
offlinePushParamBean.setMeizuPushAppId("");
offlinePushParamBean.setMeizuPushAppKey("");
offlinePushParamBean.setVivoPushBussinessId(vivoBussinessId);
offlinePushParamBean.setFcmPushBussinessId(fcmBussinessId);
offlinePushParamBean.setFcmPushChannelId(OfflinePushInfoUtils.FCM_PUSH_CHANNEL_ID);
offlinePushParamBean.setFcmPushChannelSoundName(OfflinePushInfoUtils.PRIVATE_RING_NAME);
offlinePushParamBean.setOppoPushBussinessId(oppoBussinessId);
offlinePushParamBean.setOppoPushAppKey("");
offlinePushParamBean.setOppoPushAppSecret("");
offlinePushParamBean.setHonorPushBussinessId(honorBussinessId);
String jsonStr = new Gson().toJson(offlinePushParamBean);
if (TextUtils.isEmpty(jsonStr)) {
LogUtil.e(TAG, "registerPush json is null");
return;
}
LogUtil.d(TAG, "registerPush json = " + jsonStr);
Map<String, Object> param = new HashMap<>();
param.put(TUIConstants.TIMPush.SET_CUSTOM_CONFIG_JSON_KEY, jsonStr);
TUICore.callService(TUIConstants.TIMPush.SERVICE_NAME, TUIConstants.TIMPush.METHOD_SET_CUSTOM_CONFIG_JSON, param);
Map<String, Object> registerParam = new HashMap<>();
param.put(TUIConstants.TIMPush.CONTEXT, context);
TUICore.callService(TUIConstants.TIMPush.SERVICE_NAME, TUIConstants.TIMPush.METHOD_REGISTER_PUSH, registerParam, new TUIServiceCallback() {
@Override
public void onServiceCallback(int errorCode, String errorMessage, Bundle bundle) {
LogUtil.d(TAG, "registerPush errorCode = " + errorCode + ", errorMessage = " + errorMessage);
}
});
}
/**
* When the IM console sets the click follow-up action to "use push component callback to jump",After the push is successful, register NotifyEvent through
* TUICore, and click the notification bar event will be returned through the TUICore.onNotifyEvent callback.
*/
public void registerNotifyEvent() {
TUICore.registerEvent(TUIConstants.TIMPush.EVENT_NOTIFY, TUIConstants.TIMPush.EVENT_NOTIFY_NOTIFICATION, new ITUINotification() {
@Override
public void onNotifyEvent(String key, String subKey, Map<String, Object> param) {
Log.d(TAG, "onNotifyEvent key = " + key + "subKey = " + subKey);
if (TUIConstants.TIMPush.EVENT_NOTIFY.equals(key)) {
if (TUIConstants.TIMPush.EVENT_NOTIFY_NOTIFICATION.equals(subKey)) {
if (param != null) {
String extString = (String) param.get(TUIConstants.TIMPush.NOTIFICATION_EXT_KEY);
TUIUtils.handleOfflinePush(extString, null);
}
}
}
}
});
}
/**
* When the IM console sets the click follow-up action to "use push component callback to jump",After the push is successful, register the broadcast
* receiver, click the notification bar event to return by sending the broadcast callback. IntentFilter
* TUIConstants.TIMPush.NOTIFICATION_BROADCAST_ACTION.
*/
public void registerNotificationReceiver(Context context, OfflinePushLocalReceiver localReceiver) {
LogUtil.d(TAG, "registerNotificationReceiver ");
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TUIConstants.TIMPush.NOTIFICATION_BROADCAST_ACTION);
intentFilter.addAction(TUIConstants.TIMPush.BROADCAST_IM_LOGIN_AFTER_APP_WAKEUP);
LocalBroadcastManager.getInstance(context).registerReceiver(localReceiver, intentFilter);
}
}
package com.duben.roseplaylet.im.push;
public class OfflinePushConfigs {
private static OfflinePushConfigs offlinePushConfigs;
public static final int REGISTER_PUSH_MODE_AUTO = 0;
public static final int REGISTER_PUSH_MODE_API = 1;
public static final int CLICK_NOTIFICATION_CALLBACK_INTENT = 0;
public static final int CLICK_NOTIFICATION_CALLBACK_NOTIFY = 1;
public static final int CLICK_NOTIFICATION_CALLBACK_BROADCAST = 2;
private int registerPushMode = 0;
private int clickNotificationCallbackMode = 0;
public static OfflinePushConfigs getOfflinePushConfigs() {
if (offlinePushConfigs == null) {
offlinePushConfigs = new OfflinePushConfigs();
}
return offlinePushConfigs;
}
/*
* Demo integrates two push registration methods to obtain the push service registration method that the application is using:
*
* REGISTER_PUSH_MODE_AUTO,After the component monitors the account login successfully, to register the push service automatically, you need to manually
* configure the push parameters to the PrivateConstants of the push component; REGISTER_PUSH_MODE_API,Manual registration of offline push service, called
* when the IM account is successfully logged in, see the interface description for push parameters;
*/
public int getRegisterPushMode() {
return registerPushMode;
}
public void setRegisterPushMode(int registerPushMode) {
this.registerPushMode = registerPushMode;
}
/*
* Demo integrates three ways to click the notification bar to jump to the interface to get the jumping method the application is using:
*
* CLICK_NOTIFICATION_CALLBACK_INTENT,Configure the jump parameters in the IM console according to the specifications, click the notification bar to jump
* to the configuration interface, parse the transparent transmission parameters and perform interface redirection; CLICK_NOTIFICATION_CALLBACK_NOTIFY,In
* the IM console configuration jump parameter, select "Use push component callback to jump", and click the notification bar event registration callback to
* receive; CLICK_NOTIFICATION_CALLBACK_BROADCAST,In the IM console configuration jump parameter, select "Use push component callback to jump", and click
* the notification bar event to register to receive the broadcast;
*/
public int getClickNotificationCallbackMode() {
return clickNotificationCallbackMode;
}
public void setClickNotificationCallbackMode(int clickNotificationCallbackMode) {
this.clickNotificationCallbackMode = clickNotificationCallbackMode;
}
}
package com.duben.roseplaylet.im.push;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import com.duben.roseplaylet.im.TUIUtils;
import com.duben.roseplaylet.utils.LogUtil;
import com.tencent.qcloud.tuicore.TUIConstants;
import java.util.HashMap;
import java.util.Map;
public class OfflinePushLocalReceiver extends BroadcastReceiver {
public static final String TAG = OfflinePushLocalReceiver.class.getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "BROADCAST_PUSH_RECEIVER intent = " + intent);
if (intent != null) {
String action = intent.getAction();
if (TextUtils.equals(TUIConstants.TIMPush.NOTIFICATION_BROADCAST_ACTION, action)) {
String ext = intent.getStringExtra(TUIConstants.TIMPush.NOTIFICATION_EXT_KEY);
TUIUtils.handleOfflinePush(ext, null);
} else if (TextUtils.equals(TUIConstants.TIMPush.BROADCAST_IM_LOGIN_AFTER_APP_WAKEUP, action)) {
Bundle receivedBundle = intent.getExtras();
if (receivedBundle != null) {
Map<String, String> receivedMap = new HashMap<>();
for (String key : receivedBundle.keySet()) {
String value = receivedBundle.getString(key);
receivedMap.put(key, value);
Log.d(TAG, "key = " + key + ", value = " + value);
}
} else {
LogUtil.e(TAG, "receivedBundle is null");
}
}
} else {
LogUtil.e(TAG, "onReceive intent is null");
}
}
}
package com.duben.roseplaylet.im.push;
public class OfflinePushParamBean {
public String huaweiPushBussinessId, huaweiBadgeClassName;
public String xiaomiPushBussinessId, xiaomiPushAppId, xiaomiPushAppKey;
public String meizuPushBussinessId, meizuPushAppId, meizuPushAppKey;
public String vivoPushBussinessId;
public String fcmPushBussinessId;
public String oppoPushBussinessId, oppoPushAppKey, oppoPushAppSecret;
public String honorPushBussinessId;
public String fcmPushChannelId, fcmPushChannelSoundName;
// huawei
public String getHuaweiPushBussinessId() {
return huaweiPushBussinessId;
}
public void setHuaweiPushBussinessId(String huaweiPushBussinessId) {
this.huaweiPushBussinessId = huaweiPushBussinessId;
}
public String getHuaweiBadgeClassName() {
return huaweiBadgeClassName;
}
public void setHuaweiBadgeClassName(String huaweiBadgeClassName) {
this.huaweiBadgeClassName = huaweiBadgeClassName;
}
// xiaomi
public String getXiaomiPushBussinessId() {
return xiaomiPushBussinessId;
}
public void setXiaomiPushBussinessId(String xiaomiPushBussinessId) {
this.xiaomiPushBussinessId = xiaomiPushBussinessId;
}
public String getXiaomiPushAppId() {
return xiaomiPushAppId;
}
public void setXiaomiPushAppId(String xiaomiPushAppId) {
this.xiaomiPushAppId = xiaomiPushAppId;
}
public String getXiaomiPushAppKey() {
return xiaomiPushAppKey;
}
public void setXiaomiPushAppKey(String xiaomiPushAppKey) {
this.xiaomiPushAppKey = xiaomiPushAppKey;
}
// meizu
public String getMeizuPushBussinessId() {
return meizuPushBussinessId;
}
public void setMeizuPushBussinessId(String meizuPushBussinessId) {
this.meizuPushBussinessId = meizuPushBussinessId;
}
public String getMeizuPushAppId() {
return meizuPushAppId;
}
public void setMeizuPushAppId(String meizuPushAppId) {
this.meizuPushAppId = meizuPushAppId;
}
public String getMeizuPushAppKey() {
return meizuPushAppKey;
}
public void setMeizuPushAppKey(String meizuPushAppKey) {
this.meizuPushAppKey = meizuPushAppKey;
}
// vivo
public String getVivoPushBussinessId() {
return vivoPushBussinessId;
}
public void setVivoPushBussinessId(String vivoPushBussinessId) {
this.vivoPushBussinessId = vivoPushBussinessId;
}
// google
public String getFcmPushBussinessId() {
return fcmPushBussinessId;
}
public void setFcmPushBussinessId(String fcmPushBussinessId) {
this.fcmPushBussinessId = fcmPushBussinessId;
}
public String getFcmPushChannelId() {
return fcmPushChannelId;
}
public void setFcmPushChannelId(String fcmPushChannelId) {
this.fcmPushChannelId = fcmPushChannelId;
}
public String getFcmPushChannelSoundName() {
return fcmPushChannelSoundName;
}
public void setFcmPushChannelSoundName(String fcmPushChannelSoundName) {
this.fcmPushChannelSoundName = fcmPushChannelSoundName;
}
// oppo
public String getOppoPushAppKey() {
return oppoPushAppKey;
}
public void setOppoPushAppKey(String oppoPushAppKey) {
this.oppoPushAppKey = oppoPushAppKey;
}
public String getOppoPushAppSecret() {
return oppoPushAppSecret;
}
public void setOppoPushAppSecret(String oppoPushAppSecret) {
this.oppoPushAppSecret = oppoPushAppSecret;
}
public String getOppoPushBussinessId() {
return oppoPushBussinessId;
}
public void setOppoPushBussinessId(String oppoPushBussinessId) {
this.oppoPushBussinessId = oppoPushBussinessId;
}
// honor
public String getHonorPushBussinessId() {
return honorPushBussinessId;
}
public void setHonorPushBussinessId(String honorPushBussinessId) {
this.honorPushBussinessId = honorPushBussinessId;
}
}
package com.duben.roseplaylet.manager
import android.content.Context
import com.amap.api.maps.MapsInitializer
/**
* ShareSdk
*/
object AmapManager {
fun initMap(context: Context) {
MapsInitializer.updatePrivacyShow(context, true, true)
MapsInitializer.updatePrivacyAgree(context, true)
}
}
\ No newline at end of file
package com.duben.roseplaylet.manager;
import com.duben.roseplaylet.MintsApplication;
import com.duben.roseplaylet.common.AppConfig;
import com.duben.roseplaylet.im.LoginWrapper;
import com.duben.roseplaylet.im.TIMAppService;
import com.duben.roseplaylet.im.TUIUtils;
import com.duben.roseplaylet.mvp.model.VedioBean;
import com.duben.roseplaylet.mvp.presenters.TrackPresenter;
import com.duben.roseplaylet.utils.LogUtil;
import com.tencent.qcloud.tuicore.interfaces.TUICallback;
import com.tencent.qcloud.tuicore.interfaces.TUILoginConfig;
import com.tencent.qcloud.tuicore.util.ToastUtil;
import java.util.HashMap;
......
......@@ -56,6 +56,7 @@ public class UserManager {
private static final String VIP_FOREVER = "VIP_FOREVER";
private static final String VIP_DATE = "VIP_DATE";
private static final String CODE_ID = "codeId";
private static final String SHARE_CODE = "share_code";
// 匹配用户 = true
private static final String NEW_FLAG = "new_flag";
......@@ -107,6 +108,7 @@ public class UserManager {
ps.put(VIP_FLAG, false);
}
ps.put(SHARE_CODE, user.getShareCode());
ps.put(VIP_FOREVER, user.isForever());
ps.put(REAL_NAME, user.getNickName());
ps.put(HEAD, user.getHead());
......@@ -224,6 +226,14 @@ public class UserManager {
ps.put(VIP_FLAG, vipFlag);
}
public String getShareCode() {
if (ps == null) {
return null;
}
return ps.getString(SHARE_CODE, "");
}
public void userLogout() {
if (ps != null) {
ps.remove(USER_ID);
......
package com.duben.roseplaylet.manager.map;
import com.amap.api.location.AMapLocation;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.services.core.LatLonPoint;
/**
* Created by Xie JiaBin on 2019/12/23.
*/
public class MyMapUtils {
/**
* 把LatLng对象转化为LatLonPoint对象
*/
public static LatLonPoint convertToLatLonPoint(LatLng latlon) {
return new LatLonPoint(latlon.latitude, latlon.longitude);
}
/**
* 把LatLonPoint对象转化为LatLon对象
*/
public static LatLng convertToLatLng(LatLonPoint latLonPoint) {
return new LatLng(latLonPoint.getLatitude(), latLonPoint.getLongitude());
}
/**********************************************************移动地图**************************************/
public static void animMove(AMap aMap, LatLng latLng) {
aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));
}
public static void animMove(AMap aMap, LatLonPoint point) {
aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(convertToLatLng(point), 15));
}
public static void animMove(AMap aMap, AMapLocation location) {
aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 18));
}
}
package com.duben.roseplaylet.manager.map;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.services.core.PoiItem;
import java.util.ArrayList;
import java.util.List;
/**
* Poi图层类。在高德地图API里,如果要显示Poi,可以用此类来创建Poi图层。如不满足需求,也可以自己创建自定义的Poi图层。
*/
public class PoiOverlay {
private List<PoiItem> mPois;
private AMap mAMap;
private ArrayList<Marker> mPoiMarks = new ArrayList<Marker>();
/**
* 通过此构造函数创建Poi图层。
*
* @param amap 地图对象。
* @param pois 要在地图上添加的poi。列表中的poi对象详见搜索服务模块的基础核心包(com.amap.api.services.core)中的类<strong> <a href="../../../../../../Search/com/amap/api/services/core/PoiItem.html" title="com.amap.api.services.core中的类">PoiItem</a></strong>。
*/
public PoiOverlay(AMap amap, List<PoiItem> pois) {
mAMap = amap;
mPois = pois;
}
/**
* 添加Marker到地图中。
*/
public void addToMap() {
try {
for (int i = 0; i < mPois.size(); i++) {
Marker marker = mAMap.addMarker(getMarkerOptions(i));
marker.setObject(i);
mPoiMarks.add(marker);
}
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* 去掉PoiOverlay上所有的Marker。
*/
public void removeFromMap() {
for (Marker mark : mPoiMarks) {
mark.remove();
}
}
/**
* 移动镜头到当前的视角。
*/
public void zoomToSpan() {
try {
if (mPois != null && mPois.size() > 0) {
if (mAMap == null)
return;
if (mPois.size() == 1) {
mAMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(mPois.get(0).getLatLonPoint().getLatitude(),
mPois.get(0).getLatLonPoint().getLongitude()), 18f));
} else {
LatLngBounds bounds = getLatLngBounds();
mAMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 30));
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private LatLngBounds getLatLngBounds() {
LatLngBounds.Builder b = LatLngBounds.builder();
for (int i = 0; i < mPois.size(); i++) {
b.include(new LatLng(mPois.get(i).getLatLonPoint().getLatitude(),
mPois.get(i).getLatLonPoint().getLongitude()));
}
return b.build();
}
private MarkerOptions getMarkerOptions(int index) {
return new MarkerOptions()
.position(
new LatLng(mPois.get(index).getLatLonPoint()
.getLatitude(), mPois.get(index)
.getLatLonPoint().getLongitude()))
.title(getTitle(index)).snippet(getSnippet(index))
.icon(getBitmapDescriptor(index));
}
/**
* 给第几个Marker设置图标,并返回更换图标的图片。如不用默认图片,需要重写此方法。
*
* @param index 第几个Marker。
* @return 更换的Marker图片。
*/
protected BitmapDescriptor getBitmapDescriptor(int index) {
return null;
}
/**
* 返回第index的Marker的标题。
*
* @param index 第几个Marker。
* @return marker的标题。
*/
protected String getTitle(int index) {
return mPois.get(index).getTitle();
}
/**
* 返回第index的Marker的详情。
*
* @param index 第几个Marker。
* @return marker的详情。
*/
protected String getSnippet(int index) {
return mPois.get(index).getSnippet();
}
/**
* 从marker中得到poi在list的位置。
*
* @param marker 一个标记的对象。
* @return 返回该marker对应的poi在list的位置。
*/
public int getPoiIndex(Marker marker) {
for (int i = 0; i < mPoiMarks.size(); i++) {
if (mPoiMarks.get(i).equals(marker)) {
return i;
}
}
return -1;
}
/**
* 返回第index的poi的信息。
*
* @param index 第几个poi。
* @return poi的信息。poi对象详见搜索服务模块的基础核心包(com.amap.api.services.core)中的类 <strong><a href="../../../../../../Search/com/amap/api/services/core/PoiItem.html" title="com.amap.api.services.core中的类">PoiItem</a></strong>。
*/
public PoiItem getPoiItem(int index) {
if (index < 0 || index >= mPois.size()) {
return null;
}
return mPois.get(index);
}
}
package com.duben.roseplaylet.manager.map;
import android.view.View;
import android.widget.TextView;
import com.amap.api.maps.AMap;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.services.core.PoiItem;
import com.duben.roseplaylet.MintsApplication;
import com.duben.roseplaylet.R;
import java.util.List;
public class ViewPoiOverlay extends PoiOverlay {
public ViewPoiOverlay(AMap aMap, List<PoiItem> list) {
super(aMap, list);
}
@Override
protected BitmapDescriptor getBitmapDescriptor(int index) {
View view = null;
view = View.inflate(MintsApplication.getContext(), R.layout.custom_view, null);
TextView textView = ((TextView) view.findViewById(R.id.title));
textView.setText(getTitle(index));
return BitmapDescriptorFactory.fromView(view);
}
}
\ No newline at end of file
package com.duben.roseplaylet.mvp.model
import java.util.ArrayList
data class CosumerAddressEntity(
var options1Items: MutableList<ProvinceCosumer>? = null,
var options2Items: MutableList<ArrayList<String>>? = null,
) : java.io.Serializable
package com.duben.roseplaylet.mvp.model;
import com.contrarywind.interfaces.IPickerViewData;
import java.util.List;
/**
*
* @author: 小嵩
* @date: 2017/3/16 15:36
*/
public class JsonBean implements IPickerViewData {
/**
* name : 省份
* city : [{"name":"北京市","area":["东城区","西城区","崇文区","宣武区","朝阳区"]}]
*/
private String name;
private List<CityBean> city;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<CityBean> getCityList() {
return city;
}
public void setCityList(List<CityBean> city) {
this.city = city;
}
// 实现 IPickerViewData 接口,
// 这个用来显示在PickerView上面的字符串,
// PickerView会通过IPickerViewData获取getPickerViewText方法显示出来。
@Override
public String getPickerViewText() {
return this.name;
}
public static class CityBean {
/**
* name : 城市
* area : ["东城区","西城区","崇文区","昌平区"]
*/
private String name;
private List<String> area;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getArea() {
return area;
}
public void setArea(List<String> area) {
this.area = area;
}
}
}
package com.duben.roseplaylet.mvp.model
import java.util.ArrayList
data class MainMultiItemEntity(
var beans: List<String>?= null,
var options1Items: MutableList<JsonBean>? = null,
var options2Items: MutableList<ArrayList<String>>? = null,
var options3Items: MutableList<ArrayList<ArrayList<String>>>? = null,
var itemType: Int = 0,
) : java.io.Serializable
package com.duben.roseplaylet.mvp.model;
import com.contrarywind.interfaces.IPickerViewData;
/**
* Created by Sai on 15/11/22.
*/
public class ProvinceCosumer implements IPickerViewData {
private long id;
private String name;
private String description;
private String others;
public ProvinceCosumer(long id, String name, String description, String others){
this.id = id;
this.name = name;
this.description = description;
this.others = others;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getOthers() {
return others;
}
public void setOthers(String others) {
this.others = others;
}
//这个用来显示在PickerView上面的字符串,PickerView会通过getPickerViewText方法获取字符串显示出来。
@Override
public String getPickerViewText() {
return name;
}
}
......@@ -21,6 +21,15 @@ public class UserBean implements Serializable {
private long expireTime;// vip到期时间 0-非vip
private long pk_id;// 用户id
private long createTime;// 用户id
private String shareCode;// 用户id
public String getShareCode() {
return shareCode;
}
public void setShareCode(String shareCode) {
this.shareCode = shareCode;
}
public String getToken() {
return token;
......
package com.duben.roseplaylet.mvp.presenters
import com.duben.library.net.neterror.BaseSubscriber
import com.duben.library.net.neterror.Throwable
import com.duben.roseplaylet.manager.AppHttpManager
import com.duben.roseplaylet.mvp.model.BannerList
import com.duben.roseplaylet.mvp.model.BaseResponse
import com.duben.roseplaylet.mvp.views.SquareView
class SquarePresenter : BasePresenter<SquareView>() {
fun autoList() {
AppHttpManager.getInstance(loanApplication)
.call(loanService.autoList(), object : BaseSubscriber<BaseResponse<BannerList>>() {
override fun onCompleted() {
if (isLinkView) return
view.hideLoading()
}
override fun onNext(baseResponse: BaseResponse<BannerList>) {
if (isLinkView) return
view.hideLoading()
val code = baseResponse.status
val message = baseResponse.message
when (code) {
200 -> view.autoListSuc(baseResponse.data)
else -> {
view.autoListFail()
view.showToast(message)
}
}
}
override fun onError(e: Throwable?) {
if (isLinkView) return
view.hideLoading()
view.showToast(e?.message)
view.autoListFail()
}
})
}
fun topTabs() {
AppHttpManager.getInstance(loanApplication)
.call(loanService.topTabs(),
object : BaseSubscriber<BaseResponse<BannerList>>() {
override fun onCompleted() {
if (isLinkView) return
}
override fun onError(e: Throwable) {
if (isLinkView) return
}
override fun onNext(baseResponse: BaseResponse<BannerList>) {
if (isLinkView) return
val code = baseResponse.status
val message = baseResponse.message
when (code) {
200 -> {
view.topTabsSuc(baseResponse.data)
}
else -> {
view.showToast(message)
}
}
}
})
}
}
\ No newline at end of file
......@@ -8,12 +8,18 @@ import com.duben.library.net.neterror.Throwable;
import com.duben.roseplaylet.MintsApplication;
import com.duben.roseplaylet.common.AppConfig;
import com.duben.roseplaylet.common.DeviceInfo;
import com.duben.roseplaylet.im.LoginWrapper;
import com.duben.roseplaylet.im.TIMAppService;
import com.duben.roseplaylet.im.TUIUtils;
import com.duben.roseplaylet.manager.AppHttpManager;
import com.duben.roseplaylet.manager.UserManager;
import com.duben.roseplaylet.mvp.model.BaseResponse;
import com.duben.roseplaylet.mvp.model.UserBean;
import com.duben.roseplaylet.utils.DeviceUuidFactory;
import com.duben.roseplaylet.utils.LogUtil;
import com.google.gson.JsonObject;
import com.tencent.qcloud.tuicore.interfaces.TUICallback;
import com.tencent.qcloud.tuicore.interfaces.TUILoginConfig;
import java.util.HashMap;
......@@ -42,15 +48,35 @@ public class TrackPresenter extends BaseTrackPresenter {
case 200: {
UserManager.getInstance().saveUserInfo(baseResponse.getData());
firstShowVedio();
// firstShowVedio();
saveTerminalInfo();
initUserLocalData();
}
}
}
});
}
private void initUserLocalData() {
UserManager instance = UserManager.getInstance();
TUILoginConfig tuiLoginConfig = TUIUtils.getLoginConfig();
tuiLoginConfig.setInitLocalStorageOnly(true);
LoginWrapper.getInstance().loginIMSDK(MintsApplication.getContext(), AppConfig.IM_SDK_APPID, instance.getUserID(), instance.getUserID(), tuiLoginConfig, new TUICallback() {
@Override
public void onSuccess() {
TIMAppService.getInstance().registerPushManually();
}
@Override
public void onError(final int errorCode, final String errorMessage) {
LogUtil.i("LoginWrapper ", "imLogin errorCode = " + errorCode + ", errorInfo = " + errorMessage);
}
});
}
public void getMyInfo() {
HashMap<String, Object> vo = new HashMap<>();
vo.put("os", "android");
......
package com.duben.roseplaylet.mvp.views
import com.duben.roseplaylet.mvp.model.BannerList
interface SquareView : BaseView {
fun autoListSuc(list: BannerList)
fun autoListFail()
fun topTabsSuc(data: BannerList?)
}
\ No newline at end of file
package com.duben.roseplaylet.ui.activitys
import android.view.View
import com.duben.roseplaylet.R
import com.duben.roseplaylet.ui.activitys.base.BaseActivity
import com.duben.library.utils.nodoubleclick.AntiShake
import kotlinx.android.synthetic.main.header_layout.*
class ChatActivity : BaseActivity(), View.OnClickListener {
override fun getContentViewLayoutID() = R.layout.activity_chat
override fun isApplyKitKatTranslucency() = false
override fun initViewsAndEvents() {
initListener()
}
override fun onClick(v: View?) {
if (AntiShake.check(v?.id)) return
when (v?.id) {
R.id.iv_left_icon -> finish()
}
}
private fun initListener() {
iv_left_icon.setOnClickListener(this)
}
}
......@@ -15,10 +15,7 @@ import com.duben.roseplaylet.R
import com.duben.roseplaylet.common.AppConfig
import com.duben.roseplaylet.common.Constant
import com.duben.roseplaylet.ui.activitys.base.BaseActivity
import com.duben.roseplaylet.ui.fragment.MainFragment
import com.duben.roseplaylet.ui.fragment.MyFragment
import com.duben.roseplaylet.ui.fragment.RecommendFragment
import com.duben.roseplaylet.ui.fragment.VipEnjoyFragment
import com.duben.roseplaylet.ui.fragment.*
import com.duben.roseplaylet.ui.widgets.DialogListener
import com.duben.roseplaylet.ui.widgets.PhoneDialog
......@@ -33,14 +30,15 @@ class MainActivity : BaseActivity(), View.OnClickListener {
private var tabTvVideo: TextView? = null
private var tabTvSquare: TextView? = null
private var tabTvInvite: ImageView? = null
private var tabTvInvite: TextView? = null
private var tabTvMsg: TextView? = null
private var tabTvMy: TextView? = null
// 底部标签切换的Fragment
private var mainFragment: Fragment? = null
private var messageFragment: Fragment? = null
private var messageFragment: Fragment? = null
private var squareFragment: Fragment? = null
private var inviteFragment: Fragment? = null
private var msgFragment: Fragment? = null
private var myFragment: Fragment? = null
......@@ -167,10 +165,10 @@ class MainActivity : BaseActivity(), View.OnClickListener {
*/
fun clickTab2Layout() {
AppConfig.fragmentClickFlag = Constant.FRAGMENT_CLICK_TWO
if (recommendFragment == null) {
recommendFragment = RecommendFragment()
if (squareFragment == null) {
squareFragment = SquareFragment()
}
addOrShowFragment(supportFragmentManager.beginTransaction(), recommendFragment!!)
addOrShowFragment(supportFragmentManager.beginTransaction(), squareFragment!!)
tabTvVideo?.isSelected = false
tabTvSquare?.isSelected = true
tabTvInvite?.isSelected = false
......@@ -183,10 +181,10 @@ class MainActivity : BaseActivity(), View.OnClickListener {
*/
fun clickTab3Layout() {
AppConfig.fragmentClickFlag = Constant.FRAGMENT_CLICK_THREE
if (vipEnjoyFragment == null) {
vipEnjoyFragment = VipEnjoyFragment.newInstance()
if (inviteFragment == null) {
inviteFragment = InviteFragment()
}
addOrShowFragment(supportFragmentManager.beginTransaction(), vipEnjoyFragment!!)
addOrShowFragment(supportFragmentManager.beginTransaction(), inviteFragment!!)
tabTvVideo?.isSelected = false
tabTvSquare?.isSelected = false
tabTvInvite?.isSelected = true
......@@ -199,10 +197,10 @@ class MainActivity : BaseActivity(), View.OnClickListener {
*/
fun clickTab4Layout() {
AppConfig.fragmentClickFlag = Constant.FRAGMENT_CLICK_FOUR
if (myFragment == null) {
myFragment = MyFragment()
if (msgFragment == null) {
msgFragment = MessageFragment()
}
addOrShowFragment(supportFragmentManager.beginTransaction(), myFragment!!)
addOrShowFragment(supportFragmentManager.beginTransaction(), msgFragment!!)
tabTvVideo?.isSelected = false
tabTvSquare?.isSelected = false
tabTvInvite?.isSelected = false
......@@ -214,7 +212,7 @@ class MainActivity : BaseActivity(), View.OnClickListener {
* 点击第五个tab
*/
fun clickTab5Layout() {
AppConfig.fragmentClickFlag = Constant.FRAGMENT_CLICK_FOUR
AppConfig.fragmentClickFlag = Constant.FRAGMENT_CLICK_FIVE
if (myFragment == null) {
myFragment = MyFragment()
}
......
......@@ -2,18 +2,18 @@ package com.duben.roseplaylet.ui.activitys
import android.annotation.SuppressLint
import android.os.Bundle
import android.text.TextUtils
import android.view.KeyEvent
import android.view.View
import com.duben.roseplaylet.R
import com.duben.roseplaylet.ad.AdManager
import com.duben.roseplaylet.ad.splash.SplashManager
import com.duben.roseplaylet.common.AppConfig
import com.duben.roseplaylet.common.Constant
import com.duben.roseplaylet.common.Constant.PRIVACY_URL
import com.duben.roseplaylet.common.Constant.REGISTER_URL
import com.duben.roseplaylet.manager.LocalVedioManager
import com.duben.roseplaylet.im.LoginWrapper
import com.duben.roseplaylet.im.TIMAppService
import com.duben.roseplaylet.im.TUIUtils
import com.duben.roseplaylet.manager.TrackManager
import com.duben.roseplaylet.manager.UserManager
import com.duben.roseplaylet.ui.activitys.base.BaseActivity
import com.duben.roseplaylet.ui.widgets.CycleProgress
import com.duben.roseplaylet.ui.widgets.DialogListener
......@@ -21,9 +21,11 @@ import com.duben.roseplaylet.ui.widgets.PowerDialog
import com.duben.roseplaylet.ui.widgets.PowerDialog2
import com.duben.roseplaylet.ui.widgets.countdowntimer.CountDownTimerSupport
import com.duben.roseplaylet.ui.widgets.countdowntimer.OnCountDownTimerListener
import com.duben.roseplaylet.utils.AppPreferencesManager
import com.duben.roseplaylet.utils.AppPreferencesManager.get
import com.duben.roseplaylet.utils.LogUtil
import com.tencent.qcloud.tuicore.interfaces.TUICallback
import com.tencent.qcloud.tuicore.interfaces.TUILoginConfig
import com.tencent.qcloud.tuicore.util.ToastUtil
import java.util.*
/**
......@@ -94,11 +96,11 @@ class SplashActivity : BaseActivity() {
timer = CountDownTimerSupport(AD_TIME_OUT.toLong(), 1000)
timer!!.setOnCountDownTimerListener(object : OnCountDownTimerListener {
override fun onTick(millisUntilFinished: Long) {
LogUtil.d("SplashNewActivity-->", "111-->"+millisUntilFinished)
LogUtil.d("SplashNewActivity-->", "111-->" + millisUntilFinished)
// 第一次安装时,延迟加载开屏广告,因为广告sdk还未初始化完成
val firstSplash = get().getBoolean(Constant.FIRST_SPLASH, true)
if (firstSplash && millisUntilFinished == (AD_TIME_OUT - 1000).toLong()) {
LogUtil.d("SplashNewActivity-->", "222-->"+millisUntilFinished)
LogUtil.d("SplashNewActivity-->", "222-->" + millisUntilFinished)
SplashManager.preLoadAd(this@SplashActivity)
get().put(Constant.FIRST_SPLASH, false)
}
......
......@@ -51,7 +51,7 @@ class UserInfoActivity : BaseActivity(), View.OnClickListener, UserInfoView {
}
private fun initListener() {
iv_left_icon.setOnClickListener(this)
// iv_left_icon.setOnClickListener(this)
}
override fun onDestroy() {
......
......@@ -8,8 +8,7 @@ import com.duben.roseplaylet.ui.fragment.MovieFragment
class HomeVideoPageAdapter(
private val data: List<HotStyleTypesBean>,
fragment: Fragment
) :
FragmentStateAdapter(fragment) {
) : FragmentStateAdapter(fragment) {
private val fragments = mutableMapOf<Int, Fragment>()
......@@ -20,7 +19,7 @@ class HomeVideoPageAdapter(
override fun getItemCount() = data.size
override fun createFragment(position: Int): Fragment {
val newFragment = MovieFragment.newInstance(data[position].typeId,position)
val newFragment = MovieFragment.newInstance(data[position].typeId, position)
fragments[position] = newFragment
return newFragment
}
......
package com.duben.roseplaylet.ui.adapter
import android.app.Activity
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bigkoo.pickerview.builder.OptionsPickerBuilder
import com.bigkoo.pickerview.listener.OnOptionsSelectChangeListener
import com.bigkoo.pickerview.view.OptionsPickerView
import com.duben.roseplaylet.R
import com.duben.roseplaylet.mvp.model.CosumerAddressEntity
import com.duben.roseplaylet.mvp.model.MainMultiItemEntity
import com.duben.roseplaylet.mvp.model.ProvinceCosumer
import com.duben.roseplaylet.utils.AddressData
import com.duben.roseplaylet.utils.ToastUtil
import java.util.*
class MenuAdapter(private val act: Activity, private val dataBean: MainMultiItemEntity) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
const val TYPE_CITY = 0
const val TYPE_NONE = 1
}
lateinit var context: Context
lateinit var mOnItemClickListener: OnItemClickListener
private var checkItemPosition = 0
private var cityHolder: CityHolder? = null
private var localCosumerAddress: CosumerAddressEntity? = null
private var mOptions1 = 0
private var mOptions2 = 0
private val optionsPickerView: OptionsPickerView<Any>?
get() {
val pvCustomOptions = OptionsPickerBuilder(
act
) { options1, option2, options3, v ->
}
.setLayoutRes(
R.layout.pickerview_custom_options
) { v ->
v.findViewById<View>(R.id.tv_add).setOnClickListener {
localCosumerAddress?.let {
val province = it.options1Items!!.get(mOptions1).name
val city = it.options2Items!!.get(mOptions1).get(mOptions2)
// ToastUtil.show(context, " options1=${province} options2=${city}")
mOnItemClickListener.onItemClick("${city}", 0)
}
}
v.findViewById<View>(R.id.tv_cancel).setOnClickListener {
mOnItemClickListener.onItemClick("城市不限", 0)
}
}
.setDecorView(cityHolder?.frameRoot) //非dialog模式下,设置ViewGroup, pickerView将会添加到这个ViewGroup中
.setOutSideColor(0x00000000)
// .setTextColorCenter(R.color.main_mints)
.setOutSideCancelable(false)
.setSelectOptions(mOptions1, mOptions2)
.setOptionsSelectChangeListener(object : OnOptionsSelectChangeListener {
override fun onOptionsSelectChanged(
options1: Int,
options2: Int,
options3: Int
) {
mOptions1 = options1
mOptions2 = options2
}
})
.build<Any>()
return pvCustomOptions
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
context = parent.context
if (viewType == TYPE_CITY) {
localCosumerAddress = AddressData.getLocalCosumerAddress()
return CityHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_city, parent, false)
)
} else {
return ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_menu, parent, false)
)
}
}
override fun getItemViewType(position: Int): Int {
return dataBean.itemType
}
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
if (viewHolder is CityHolder) {
cityHolder = viewHolder as CityHolder
val pvCustomOptions = optionsPickerView
pvCustomOptions?.setPicker(
localCosumerAddress?.options1Items as List<ProvinceCosumer>,
localCosumerAddress?.options2Items as List<MutableList<String>>
)
pvCustomOptions?.show()
} else {
val holder = viewHolder as ViewHolder
val dataList = dataBean.beans
holder.tvMenu.text = (dataList!!.get(position))
holder.itemView.setOnClickListener {
mOnItemClickListener.onItemClick(dataList!![position], position)
}
if (checkItemPosition == position) {
holder.tvMenu.setTextColor(context.getResources().getColor(R.color.color_ff33b5e5));
} else {
holder.tvMenu.setTextColor(context.getResources().getColor(R.color.black));
}
}
}
override fun getItemCount(): Int {
return if (dataBean.itemType == TYPE_CITY) 1 else dataBean.beans?.size!!
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val tvMenu: TextView = view.findViewById(R.id.tv_menu)
}
inner class CityHolder(view: View) : RecyclerView.ViewHolder(view) {
val frameRoot: FrameLayout = view.findViewById(R.id.frame_root)
}
interface OnItemClickListener {
fun onItemClick(title: String, position: Int)
}
fun setOnItemClickListener(listener: OnItemClickListener) {
mOnItemClickListener = listener
}
fun setCheckItem(position: Int) {
checkItemPosition = position
notifyDataSetChanged()
}
}
\ No newline at end of file
package com.duben.roseplaylet.ui.adapter
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.duben.roseplaylet.R
import com.duben.roseplaylet.mvp.model.VedioBean
class SquareAdapter : BaseQuickAdapter<VedioBean, BaseViewHolder>(R.layout.item_square) {
override fun convert(holder: BaseViewHolder, item: VedioBean) {
}
}
\ No newline at end of file
package com.duben.roseplaylet.ui.adapter
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.duben.roseplaylet.mvp.model.HotStyleTypesBean
import com.duben.roseplaylet.ui.fragment.MovieFragment
import com.duben.roseplaylet.ui.fragment.SquareListFragment
class SquarePageAdapter(
private val data: List<String>,
fragment: Fragment
) : FragmentStateAdapter(fragment) {
private val fragments = mutableMapOf<Int, Fragment>()
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItemCount() = data.size
override fun createFragment(position: Int): Fragment {
val newFragment = SquareListFragment.newInstance()
fragments[position] = newFragment
return newFragment
}
override fun containsItem(itemId: Long): Boolean {
data.forEach {
if (it.toLong() == itemId) {
return true
}
}
return false
}
fun getFragments(): MutableMap<Int, Fragment> {
return fragments
}
}
\ No newline at end of file
package com.duben.roseplaylet.ui.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.duben.roseplaylet.R
import com.duben.roseplaylet.manager.LocalVedioManager
import com.duben.roseplaylet.mvp.model.BannerList
import com.duben.roseplaylet.mvp.model.VedioBean
import com.duben.roseplaylet.mvp.presenters.FollowPresenter
import com.duben.roseplaylet.mvp.views.FollowView
import com.duben.roseplaylet.ui.activitys.MainActivity
import com.duben.roseplaylet.ui.adapter.FollowAdapter
import com.duben.roseplaylet.ui.fragment.base.BaseFragment
import kotlinx.android.synthetic.main.fragment_follow_video.*
/**
* @author Assen
* @date 2023/7/5
* @desc 主页 -> 推荐 —> 追剧
*/
class FollowVideoFragment : BaseFragment(), FollowView {
private val followPresenter by lazy { FollowPresenter() }
private val datas = arrayListOf<VedioBean>()
private var followAdapter: FollowAdapter? = null
companion object {
fun newInstance(): Fragment {
val args = Bundle()
val fragment = FollowVideoFragment()
fragment.arguments = args
return fragment
}
}
override fun onResume() {
super.onResume()
followPresenter.getCollectList()
}
override fun initViewsAndEvents() {
followPresenter.attachView(this)
initRecy()
}
override fun getContentViewLayoutID() = R.layout.fragment_follow_video
private fun initRecy() {
val emptyView =
LayoutInflater.from(requireContext()).inflate(R.layout.item_follow_empty, null)
emptyView.findViewById<View>(R.id.btn).setOnClickListener {
// 去剧场
(requireActivity() as MainActivity).changeRecommendTab(1)
}
rv_follow.layoutManager = GridLayoutManager(requireContext(), 3)
followAdapter = FollowAdapter(requireActivity())
followAdapter?.setEmptyView(emptyView)
followAdapter?.setNewInstance(datas)
followAdapter?.setOnItemLongClickListener { adapter, view, position ->
datas[position].isChecked = true
followAdapter?.setEditStyle(true)
showEditView(false)
return@setOnItemLongClickListener false
}
followAdapter?.setOnItemClickListener { adapter, view, position ->
if (followAdapter?.getEditStyle() == true) return@setOnItemClickListener
LocalVedioManager.startVedioDetailActivityForType(
requireActivity(),
datas[position]
)
}
rv_follow.adapter = followAdapter
}
fun getAdapter(): FollowAdapter? {
return followAdapter
}
override fun onDetach() {
super.onDetach()
followPresenter.detachView()
}
private fun showEditView(show: Boolean) {
(requireActivity() as MainActivity).showEditView(show)
}
private fun hideEditView(hide: Boolean) {
(requireActivity() as MainActivity).hideEditView(hide)
}
override fun getCollectListSuc(bannerList: BannerList) {
datas.clear()
if (bannerList.list.isNotEmpty()) {
datas.addAll(bannerList.list)
followAdapter?.setNewInstance(datas)
showEditView(true)
} else {
hideEditView(true)
}
followAdapter?.setEditStyle(false)
}
override fun getCollectListFail() {
showEditView(false)
}
override fun cancelCollectSuc() {
followPresenter.getCollectList()
(requireActivity() as MainActivity).showEditView(true)
}
override fun cancelCollectFail() {
}
fun delete() {
followAdapter?.let {
val strArr = arrayListOf<String>()
for (datum in it.data) {
if (datum.isChecked) {
strArr.add("" + datum.vedioId)
}
}
followPresenter.cancelCollect(strArr)
}
}
}
\ No newline at end of file
......@@ -59,10 +59,8 @@ class MainFragment : LazyLoadBaseFragment(), HomeView, View.OnClickListener, OnR
private var vpAdapter: HomeVideoPageAdapter? = null
private var topAdapter: TopAdapter? = null
private var recommendVedioBean: RecoBean? = null
private var countDownTimer: SimpleCountDownTimer? = null
private var alipayTime = 0
private val homePresenter by lazy { HomePresenter() }
private val userManager by lazy { UserManager.getInstance() }
......
......@@ -86,7 +86,7 @@ class MyFragment : LazyLoadBaseFragment(), MyView, View.OnClickListener {
override fun onFragmentResume() {
super.onFragmentResume()
if (AppConfig.fragmentClickFlag == Constant.FRAGMENT_CLICK_FOUR) {
if (AppConfig.fragmentClickFlag == Constant.FRAGMENT_CLICK_FIVE) {
if (AntiShake.check(ll_my_record?.id)) return
if(userManager.vipFlag){
......
package com.duben.roseplaylet.ui.fragment
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.duben.roseplaylet.R
import com.duben.roseplaylet.common.AppConfig
import com.duben.roseplaylet.common.Constant
import com.duben.roseplaylet.mvp.model.*
import com.duben.roseplaylet.mvp.presenters.SquarePresenter
import com.duben.roseplaylet.mvp.views.SquareView
import com.duben.roseplaylet.ui.adapter.*
import com.duben.roseplaylet.ui.fragment.base.LazyLoadBaseFragment
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.android.synthetic.main.fragment_square.*
import java.lang.reflect.Field
class SquareFragment : LazyLoadBaseFragment(), SquareView {
private val squarePresenter by lazy { SquarePresenter() }
private val bannerList = mutableListOf<BannerBean>()
private val tabsData = mutableListOf<String>()
private var vpAdapter: SquarePageAdapter? = null
override fun getContentViewLayoutID() = R.layout.fragment_square
override fun initViewsAndEvents() {
initVp()
}
override fun onFragmentFirstVisible() {
super.onFragmentFirstVisible()
squarePresenter.attachView(this)
}
override fun onFragmentResume() {
super.onFragmentResume()
if (AppConfig.fragmentClickFlag == Constant.FRAGMENT_CLICK_TWO) {
banner?.start()
squarePresenter.topTabs()
}
}
override fun onDestroy() {
super.onDestroy()
squarePresenter.detachView()
}
private fun initVp() {
tabsData.addAll(arrayOf("活跃", "附近", "新人"))
vpAdapter = SquarePageAdapter(tabsData, this)
vp2.adapter = vpAdapter
vp2.desensitization()
TabLayoutMediator(tablayout, vp2) { tab, position ->
// 初始化Tab
tab.id = position
if (tabsData.size > 0) {
tab.customView = getTabView(tabsData[position])
}
}.attach()
tablayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
updateTab(tab, true)
MainFragment.mSelectTabIndex = tab!!.id
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
updateTab(tab, false)
}
override fun onTabReselected(tab: TabLayout.Tab?) {}
})
vp2.offscreenPageLimit = 100
}
private fun updateTab(tab: TabLayout.Tab?, isSelected: Boolean) {
tab?.customView?.let {
val text = it.findViewById<TextView>(R.id.item_tv)
if (isSelected) {
text.setTextColor(ContextCompat.getColor(requireContext(), R.color.red))
} else {
text.setTextColor(ContextCompat.getColor(requireContext(), R.color.color_8D8F90))
}
}
}
private fun getTabView(text: String): View {
val view = LayoutInflater.from(requireContext()).inflate(R.layout.item_video_tab, null)
view.findViewById<TextView>(R.id.item_tv).text = text
return view
}
override fun topTabsSuc(data: BannerList?) {
if (data != null && data.list != null && data.list.size > 0) {
bannerList.clear()
for (i in 0 until data.list.size) {
val bean = BannerBean()
bean.title = data.list[i].topTabsReamrk
bean.imageRes = data.list[i].typeImg
bannerList.add(bean)
}
banner.addBannerLifecycleObserver(this)
.setAdapter(ImageTitleAdapter(bannerList))
.setOnBannerListener { data2, position ->
val banner = data.list[position]
if (banner.createType == 4) {
} else {
// TODO
}
}
}
}
override fun autoListSuc(data: BannerList) {
}
override fun autoListFail() {
}
fun ViewPager2.desensitization() {
//动态设置ViewPager2 灵敏度
try {
val recyclerViewField: Field = ViewPager2::class.java.getDeclaredField("mRecyclerView")
recyclerViewField.isAccessible = true
val recyclerView = recyclerViewField.get(this) as RecyclerView
val touchSlopField: Field = RecyclerView::class.java.getDeclaredField("mTouchSlop")
touchSlopField.isAccessible = true
val touchSlop = touchSlopField.get(recyclerView) as Int
touchSlopField.set(recyclerView, touchSlop * 3) //6 is empirical value
} catch (ignore: java.lang.Exception) {
}
}
}
\ No newline at end of file
package com.duben.roseplaylet.ui.fragment
import android.os.Bundle
import android.view.LayoutInflater
import androidx.fragment.app.Fragment
import com.duben.roseplaylet.R
import com.duben.roseplaylet.ad.express.MainExpressManager
import com.duben.roseplaylet.common.Constant
import com.duben.roseplaylet.mvp.model.*
import com.duben.roseplaylet.ui.fragment.base.LazyLoadBaseFragment
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener
import com.duben.roseplaylet.common.AppConfig
import com.duben.roseplaylet.mvp.presenters.SquarePresenter
import com.duben.roseplaylet.mvp.views.SquareView
import com.duben.roseplaylet.ui.adapter.SquareAdapter
import kotlinx.android.synthetic.main.fragment_square_list.*
class SquareListFragment : LazyLoadBaseFragment(), SquareView, OnLoadMoreListener {
companion object {
private const val SQUARE_TYPE = "SQUARE_TYPE"
fun newInstance(): Fragment {
val args = Bundle()
val fragment = SquareListFragment()
fragment.arguments = args
return fragment
}
}
private val squarePresenter by lazy { SquarePresenter() }
private var hotPage = 1 // 分页
private var hotPageSize = Constant.PAGE_SIZE // 分页
private lateinit var squareAdapter: SquareAdapter
override fun getContentViewLayoutID() = R.layout.fragment_square_list
override fun initViewsAndEvents() {
squarePresenter.attachView(this)
initRecy()
initListener()
arguments?.let {}
}
override fun onResume() {
super.onResume()
hotPageSize = 15
onRefresh()
}
override fun onDestroy() {
super.onDestroy()
squarePresenter.detachView()
}
fun onRefresh() {
if (AppConfig.fragmentClickFlag == Constant.FRAGMENT_CLICK_TWO) {
hotPage = 1
srl_square.resetNoMoreData()
squarePresenter.autoList()
}
}
override fun onLoadMore(refreshLayout: RefreshLayout) {
hotPage = ++hotPage
squarePresenter.autoList()
}
private fun initRecy() {
squareAdapter = SquareAdapter()
squareAdapter.animationEnable = false
rcy_square_list.adapter = squareAdapter
val emptyView =
LayoutInflater.from(requireContext()).inflate(R.layout.item_empty_data, null)
squareAdapter.setEmptyView(emptyView)
}
private fun initListener() {
srl_square.setEnableRefresh(false)
srl_square.setOnLoadMoreListener(this)
}
override fun onDestroyView() {
super.onDestroyView()
MainExpressManager.instance.destroy()
}
override fun autoListSuc(data: BannerList) {
if (activity == null || requireActivity().isFinishing) {
srl_square?.finishRefresh(true)
return
}
if (::squareAdapter.isInitialized) {
if (hotPage == 1) {
srl_square.finishRefresh(true)
squareAdapter.setNewInstance(data.list)
} else {
if (data.list.size < hotPageSize) {
srl_square.finishLoadMoreWithNoMoreData()
} else {
srl_square.finishLoadMore()
}
squareAdapter.addData(data.list)
}
}
}
override fun autoListFail() {}
override fun topTabsSuc(data: BannerList?) {}
}
\ No newline at end of file
package com.duben.roseplaylet.ui.widgets;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.FrameLayout;
public class CornerView extends FrameLayout {
public CornerView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CornerView(Context context) {
super(context);
init();
}
private final RectF roundRect = new RectF();
private float rect_adius = 10;
private final Paint maskPaint = new Paint();
private final Paint zonePaint = new Paint();
private void init() {
maskPaint.setAntiAlias(true);
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
zonePaint.setAntiAlias(true);
zonePaint.setColor(Color.WHITE);
float density = getResources().getDisplayMetrics().density;
rect_adius = rect_adius * density;
}
public void setCorner(float adius) {
rect_adius = adius;
invalidate();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
int w = getWidth();
int h = getHeight();
roundRect.set(0, 0, w, h);
}
@Override
public void draw(Canvas canvas) {
canvas.saveLayer(roundRect, zonePaint, Canvas.ALL_SAVE_FLAG);
canvas.drawRoundRect(roundRect, rect_adius, rect_adius, zonePaint);
canvas.saveLayer(roundRect, maskPaint, Canvas.ALL_SAVE_FLAG);
super.draw(canvas);
canvas.restore();
}
}
package com.duben.roseplaylet.ui.widgets;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatTextView;
public class DrawableCenterTextView extends AppCompatTextView {
private String tempStringText="| |";
public DrawableCenterTextView(Context context) {
this(context, null);
}
public DrawableCenterTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DrawableCenterTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable[] drawables = getCompoundDrawables();
Drawable leftDrawable = drawables[0]; //drawableLeft
Drawable rightDrawable = drawables[2];//drawableRight
if (leftDrawable != null || rightDrawable != null) {
//1,获取text的width
float textWidth = getPaint().measureText(getText(), 0, getText().length());
//2,获取Drawable padding
int drawablePadding = getCompoundDrawablePadding();
int drawableWidth;
float bodyWidth;
if (leftDrawable != null) {
//3,获取drawable的宽度
drawableWidth = leftDrawable.getIntrinsicWidth();
} else {
drawableWidth = rightDrawable.getIntrinsicWidth();
}
//4,获取绘制区域的总宽度
bodyWidth = textWidth + drawablePadding + drawableWidth;
if (bodyWidth < getWidth()) {
if (leftDrawable != null)
setPadding(0, getPaddingTop(), 0, getPaddingBottom());
else
//图片居右设置padding
setPadding(0, getPaddingTop(), (int) (getWidth() - bodyWidth), getPaddingBottom());
canvas.translate((getWidth() - bodyWidth) / 2, 0);
}
}
super.onDraw(canvas);
}
}
package com.duben.roseplaylet.ui.widgets;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
public class ParentRecyclerView extends RecyclerView {
private boolean interceptFlag = false;
public ParentRecyclerView(@NonNull Context context) {
this(context, null);
}
public ParentRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ParentRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
//不拦截,继续分发下去
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
//当然这里可能要根据实际场景去处理下,不仅仅是返回false就结束了。
return false;
}
}
package com.duben.roseplaylet.utils
import android.content.Context
import com.duben.roseplaylet.mvp.model.CosumerAddressEntity
import com.duben.roseplaylet.mvp.model.JsonBean
import com.duben.roseplaylet.mvp.model.MainMultiItemEntity
import com.duben.roseplaylet.mvp.model.ProvinceCosumer
import com.google.gson.Gson
import org.json.JSONArray
object AddressData {
private var cosumerAddressEntity: CosumerAddressEntity? = null
/**
* 解析省市区
*/
fun getJsonData(context: Context): MainMultiItemEntity {
val data = MainMultiItemEntity()
try {
val options2Items = arrayListOf<ArrayList<String>>()
val options3Items = arrayListOf<ArrayList<ArrayList<String>>>()
//解析数据
val JsonData: String = GetJsonDataUtil().getJson(context, "province.json")
val jsonBean: ArrayList<JsonBean> = parseData(JsonData)
data.options1Items = jsonBean
for (i in jsonBean.indices) { //遍历省份
val cityList = ArrayList<String>() //该省的城市列表(第二级)
val province_AreaList = ArrayList<ArrayList<String>>() //该省的所有地区列表(第三极)
for (c in 0 until jsonBean[i].cityList.size) { //遍历该省份的所有城市
val cityName = jsonBean[i].cityList[c].name
cityList.add(cityName) //添加城市
val city_AreaList = ArrayList<String>() //该城市的所有地区列表
//如果无地区数据,建议添加空字符串,防止数据为null 导致三个选项长度不匹配造成崩溃
if (jsonBean[i].cityList[c].area == null
|| jsonBean[i].cityList[c].area.size == 0
) {
city_AreaList.add("")
} else {
city_AreaList.addAll(jsonBean[i].cityList[c].area);
}
// city_AreaList.addAll(jsonBean[i].cityList[c].area)
province_AreaList.add(city_AreaList) //添加该省所有地区数据
}
/**
* 添加城市数据
*/
options2Items.add(cityList)
/**
* 添加地区数据
*/
options3Items.add(province_AreaList)
}
data.options2Items = options2Items
data.options3Items = options3Items
} catch (e: Exception) {
e.printStackTrace()
}
return data
}
/**
* 解析省市
*/
fun getJsonDataForProvince(context: Context): MainMultiItemEntity {
val data = MainMultiItemEntity()
try {
//解析数据
data.options1Items = parseData(GetJsonDataUtil().getJson(context, "province.json"))
} catch (e: Exception) {
e.printStackTrace()
}
return data
}
private fun parseData(result: String?): ArrayList<JsonBean> { //Gson 解析
val detail = arrayListOf<JsonBean>()
try {
val data = JSONArray(result)
val gson = Gson()
for (i in 0 until data.length()) {
val entity = gson.fromJson(data.optJSONObject(i).toString(), JsonBean::class.java)
detail.add(entity)
}
} catch (e: Exception) {
e.printStackTrace()
}
return detail
}
fun setLocalCosumerAddress(item: ArrayList<JsonBean>) {
try {
cosumerAddressEntity = CosumerAddressEntity()
var options1Items = ArrayList<ProvinceCosumer>()
var options2Items = ArrayList<ArrayList<String>>()
for (i in 0 until item.size) {
val provinceTest =
ProvinceCosumer(
i.toLong(),
item[i].name,
"描述部分",
"其他数据"
)
val cityListTemp = arrayListOf<String>()
for (j in 0 until item[i].cityList.size) {
cityListTemp.add(item[i].cityList[j].name)
}
options1Items.add(provinceTest)
options2Items.add(cityListTemp)
}
cosumerAddressEntity?.options1Items = options1Items
cosumerAddressEntity?.options2Items = options2Items
} catch (e: Exception) {
e.printStackTrace()
}
}
fun getLocalCosumerAddress() = cosumerAddressEntity
}
\ No newline at end of file
package com.duben.roseplaylet.utils;
import android.content.Context;
import android.graphics.Point;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
public class DeviceUtils2 {
public static int getScreenHeight(Context context) {
DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) context.getApplicationContext().getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels;
}
public static Point getScreenSize(Context context){
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2){
return new Point(display.getWidth(), display.getHeight());
}else{
Point point = new Point();
display.getSize(point);
return point;
}
}
}
\ No newline at end of file
package com.duben.roseplaylet.utils;
import android.content.Context;
import android.content.res.AssetManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* <读取Json文件的工具类>
*
* @author: 小嵩
* @date: 2017/3/16 16:22
*/
public class GetJsonDataUtil {
public String getJson(Context context,String fileName) {
StringBuilder stringBuilder = new StringBuilder();
try {
AssetManager assetManager = context.getAssets();
BufferedReader bf = new BufferedReader(new InputStreamReader(
assetManager.open(fileName)));
String line;
while ((line = bf.readLine()) != null) {
stringBuilder.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return stringBuilder.toString();
}
}
/*
* 官网地站:http://www.mob.com
* 技术支持QQ: 4006852216
* 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复)
*
* Copyright (c) 2013年 mob.com. All rights reserved.
*/
package com.duben.roseplaylet.wxapi;
import android.content.Intent;
import android.widget.Toast;
import cn.sharesdk.wechat.utils.WXAppExtendObject;
import cn.sharesdk.wechat.utils.WXMediaMessage;
import cn.sharesdk.wechat.utils.WechatHandlerActivity;
/** 微信客户端回调activity示例 */
public class WXEntryActivity extends WechatHandlerActivity {
/**
* 处理微信发出的向第三方应用请求app message
* <p>
* 在微信客户端中的聊天页面有“添加工具”,可以将本应用的图标添加到其中
* 此后点击图标,下面的代码会被执行。Demo仅仅只是打开自己而已,但你可
* 做点其他的事情,包括根本不打开任何页面
*/
public void onGetMessageFromWXReq(WXMediaMessage msg) {
if (msg != null) {
Intent iLaunchMyself = getPackageManager().getLaunchIntentForPackage(getPackageName());
startActivity(iLaunchMyself);
}
}
/**
* 处理微信向第三方应用发起的消息
* <p>
* 此处用来接收从微信发送过来的消息,比方说本demo在wechatpage里面分享
* 应用时可以不分享应用文件,而分享一段应用的自定义信息。接受方的微信
* 客户端会通过这个方法,将这个信息发送回接收方手机上的本demo中,当作
* 回调。
* <p>
* 本Demo只是将信息展示出来,但你可做点其他的事情,而不仅仅只是Toast
*/
public void onShowMessageFromWXReq(WXMediaMessage msg) {
if (msg != null && msg.mediaObject != null
&& (msg.mediaObject instanceof WXAppExtendObject)) {
WXAppExtendObject obj = (WXAppExtendObject) msg.mediaObject;
Toast.makeText(this, obj.extInfo, Toast.LENGTH_SHORT).show();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="250">
<alpha
android:fromAlpha="0"
android:toAlpha="1"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="250">
<alpha
android:fromAlpha="1"
android:toAlpha="0"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="250">
<translate
android:fromYDelta="-100%p"
android:toYDelta="0"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="250">
<translate
android:fromYDelta="0"
android:toYDelta="-100%p"/>
</set>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="10dp"
android:height="10dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:fillColor="#666666"
android:pathData="M8,12c-0.3,0 -0.6,-0.1 -0.9,-0.3l-6.5,-5c-0.7,-0.5 -0.8,-1.4 -0.3,-2.1c0.5,-0.7 1.4,-0.8 2.1,-0.3L8,8.6l5.6,-4.3c0.7,-0.5 1.6,-0.4 2.1,0.3c0.5,0.7 0.4,1.6 -0.3,2.1l-6.5,5C8.6,11.9 8.3,12 8,12z" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="10dp"
android:height="10dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:fillColor="@android:color/holo_blue_light"
android:pathData="M8,4c0.3,0 0.6,0.1 0.9,0.3l6.5,5c0.7,0.5 0.8,1.4 0.3,2.1c-0.5,0.7 -1.4,0.8 -2.1,0.3L8,7.4l-5.6,4.3c-0.7,0.5 -1.6,0.4 -2.1,-0.3c-0.5,-0.7 -0.4,-1.6 0.3,-2.1l6.5,-5C7.4,4.1 7.7,4 8,4z" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="30dp" />
<solid android:color="#335A73" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充的颜色 -->
<solid android:color="#4bbdd5" />
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners android:radius="5dip" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充的颜色 -->
<solid android:color="#73a2f1" />
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners android:radius="5dip" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 填充的颜色 -->
<solid android:color="@color/red" />
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners android:radius="2dip" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/main_mints" />
<corners android:bottomRightRadius="5dip" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffffff" />
<corners android:radius="10dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<include layout="@layout/header_layout" />
<com.duben.roseplaylet.ui.widgets.ElasticScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</com.duben.roseplaylet.ui.widgets.ElasticScrollView>
</LinearLayout>
......@@ -59,7 +59,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="广场"
android:textColor="@color/item_text_sel2"
android:textColor="@color/item_text_sel"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
......@@ -77,7 +77,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="邀请有奖"
android:textColor="@color/item_text_sel2"
android:textColor="@color/item_text_sel"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
......@@ -95,7 +95,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="消息"
android:textColor="@color/item_text_sel2"
android:textColor="@color/item_text_sel"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_bg_market"
android:gravity="center"
android:paddingLeft="10dp"
android:paddingTop="4dp"
android:paddingRight="10dp"
android:paddingBottom="4dp"
android:text="望京公园"
android:textColor="@color/white"
android:textSize="14sp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="30dp"
android:background="@color/full_transparent">
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_marginBottom="30dp"
android:clipToPadding="false"
android:paddingStart="60dp"
android:paddingEnd="60dp"
app:layout_constraintBottom_toTopOf="@+id/linearLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_tab_friends"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="110dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/llDialogShareWx"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/ic_share_wx" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="微信"
android:textColor="@color/black"
android:textSize="14sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/llDialogShareQq"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_horizontal"
android:src="@mipmap/ic_wx_friends" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="朋友圈"
android:textColor="@color/black"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tvDialogShareTips"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:gravity="center"
android:text="取消"
android:textSize="12sp"
android:visibility="gone" />
<View style="@style/line_3" />
<TextView
android:id="@+id/tvDialogShareNext"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:text="取消"
android:textColor="@color/black"
android:textSize="18sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="68dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_follow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_gravity="center_horizontal"
android:background="@color/full_transparent"
android:overScrollMode="never" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_behavior=".ui.widgets.AppBarLayoutBehavior">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentScrim="@android:color/transparent"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" />
</FrameLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="wrap_content"
android:layout_height="38dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:paddingTop="-10dp"
app:tabBackground="@null"
app:tabIndicatorHeight="0dp"
app:tabMaxWidth="200dp"
app:tabMinWidth="20dp"
app:tabMode="scrollable"
app:tabPaddingEnd="6dp"
app:tabPaddingStart="6dp"
app:tabRippleColor="@null" />
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vp2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_behavior=".ui.widgets.AppBarLayoutBehavior">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentScrim="@android:color/transparent"
app:layout_scrollFlags="scroll|enterAlwaysCollapsed">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="160dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="wrap_content"
android:layout_height="38dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:paddingTop="-10dp"
app:tabBackground="@null"
app:tabIndicatorHeight="0dp"
app:tabMaxWidth="200dp"
app:tabMinWidth="20dp"
app:tabMode="scrollable"
app:tabPaddingEnd="6dp"
app:tabPaddingStart="6dp"
app:tabRippleColor="@null" />
</com.google.android.material.appbar.AppBarLayout>
<com.scwang.smartrefresh.layout.SmartRefreshLayout
android:id="@+id/srl_square"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srlAccentColor="@color/gray"
app:srlPrimaryColor="@color/white">
<com.scwang.smartrefresh.header.MaterialHeader
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rcy_square_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_F1F2F8"
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<com.scwang.smartrefresh.layout.footer.ClassicsFooter
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srlAccentColor="@color/black"
app:srlPrimaryColor="@color/white" />
</com.scwang.smartrefresh.layout.SmartRefreshLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/frame_root"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<TextView
android:id="@+id/tv_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:textColor="@color/black"
android:textSize="14dp" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.duben.roseplaylet.ui.widgets.CornerView
android:id="@+id/item_iv_bg"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_margin="6dp"
android:background="@drawable/shape_gold_card"
android:padding="6dp">
<com.duben.roseplaylet.ui.widgets.CircleImageView
android:id="@+id/item_iv_avatar"
android:layout_width="34dp"
android:layout_height="34dp"
android:layout_centerVertical="true"
app:layout_constraintBottom_toBottomOf="@+id/item_iv_qrcode"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:layout_toEndOf="@id/item_iv_avatar"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/item_iv_qrcode"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@+id/item_iv_avatar"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/item_tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:textColor="@color/black"
android:textSize="11sp" />
<TextView
android:id="@+id/item_tv_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:textSize="8sp" />
</LinearLayout>
<ImageView
android:id="@+id/item_iv_qrcode"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.duben.roseplaylet.ui.widgets.CornerView>
<CheckBox
android:id="@+id/item_cb_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:buttonTint="@color/color_FF9837"
android:clickable="false" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_recommend_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@color/white"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="@+id/iv_recommend_header"
android:layout_width="80dp"
android:layout_height="120dp"
android:src="@mipmap/ic_my_avat" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="8dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp">
<TextView
android:id="@+id/tv_recommend_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="张三"
android:textColor="#454A69"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_recommend_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:text="●在线"
android:textColor="@color/apk_uninstalled"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_recommend_vip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:layout_toEndOf="@+id/tv_recommend_name"
android:background="@drawable/shape_bg_reco3"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="VIP"
android:textColor="@color/white"
android:textSize="10sp" />
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_recommend_age"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:background="@drawable/shape_bg_reco2"
android:drawableLeft="@mipmap/ic_quit_yuan"
android:gravity="center"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:text="40"
android:textColor="@color/white"
android:textSize="13sp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginBottom="8dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_recommend_height"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginRight="6dp"
android:background="@drawable/shape_bg_reco1"
android:gravity="center"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:text="176cm"
android:textColor="@color/white"
android:textSize="13sp" />
<TextView
android:id="@+id/tv_recommend_city"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:background="@drawable/shape_bg_reco1"
android:gravity="center"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:singleLine="true"
android:text="四川 成都"
android:textColor="@color/white"
android:textSize="13sp" />
</LinearLayout>
<TextView
android:id="@+id/tv_recommend_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:drawableLeft="@mipmap/ic_quit_yuan"
android:gravity="center"
android:text="308.1km"
android:textColor="#454A69"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical">
<!--此部分需要完整复制过去,删减或者更改ID会导致初始化找不到内容而报空-->
<LinearLayout
android:id="@+id/optionspicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@android:color/white"
android:orientation="horizontal">
<com.contrarywind.view.WheelView
android:id="@+id/options1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.contrarywind.view.WheelView
android:id="@+id/options2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<com.contrarywind.view.WheelView
android:id="@+id/options3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/my_color_gray" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_cancel"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:text="城市不限"
android:textColor="@color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_add"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="@drawable/shape_blue_confirm"
android:gravity="center"
android:text="确定"
android:textColor="@color/white"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
......@@ -202,4 +202,19 @@
<attr name="quick_reachCapRound" format="boolean" />
</declare-styleable>
<declare-styleable name="DropDownMenu">
<attr name="ddFrameContentView" format="reference" />
<attr name="ddUnderlineColor" format="color" />
<attr name="ddUnderlineWidth" format="dimension" />
<attr name="ddTextSelectedColor" format="color" />
<attr name="ddTextUnselectedColor" format="color" />
<attr name="ddTextPadding" format="dimension" />
<attr name="ddMaskColor" format="color" />
<attr name="ddMenuTextSize" format="dimension" />
<attr name="ddMenuSelectedIcon" format="reference" />
<attr name="ddMenuUnselectedIcon" format="reference" />
<attr name="ddMenuIconSize" format="dimension" />
<attr name="ddMenuIconPadding" format="dimension" />
<attr name="ddMenuHeightPercent" format="float" />
</declare-styleable>
</resources>
\ No newline at end of file
......@@ -37,6 +37,7 @@
<color name="transparent90_white">#E5ffffff</color>
<color name="color_F1F2F8">#F1F2F8</color>
<color name="color_ff33b5e5">#ff33b5e5</color>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="bannerTitle" type="id" />
<item name="dd_tab_menu_view" type="id" />
<item name="dd_container_view" type="id" />
</resources>
\ No newline at end of file
......@@ -64,7 +64,15 @@
用户认可并同意:在未获得本公司正式书面公开许可之前,用户不得就其所获得之自动续费服务用于非本公司服务的其它领域,也不得直接或间接地对自动续费服务进行任何商业化(包括但不限于:转售、贩卖、等价置换等)的行为。一旦发现用户涉及上述之行为,本公司有权收回用户对自动续费服务的使用权而不对用户作出任何的赔偿,并保留进一步追究用户行为而导致本公司损失之权利。</string>
<!--内存页-->
<string name="demo_permission_mic_reason_title">%s申请获取麦克风权限</string>
<string name="demo_permission_mic_reason">为方便您发送语音消息,进行摄像和音视频通话、使用快速会议功能,请允许我们访问麦克风。</string>
<string name="demo_permission_camera_reason_title">%s申请获取相机权限</string>
<string name="demo_permission_camera_reason">为方便您拍摄照片或视频以发送给朋友、进行视频通话和使用快速会议功能,请允许我们访问摄像头。</string>
<string name="demo_permission_storage_reason_title">%s申请获取存储权限</string>
<string name="demo_permission_storage_reason">为方便您保存照片和视频到设备,请允许我们写入照片和视频到设备。</string>
<string name="demo_permission_mic_dialog_alert">在设置-应用-%s-权限中开启麦克风权限,以正常使用语音消息、摄像、音视频通话和快速会议功能</string>
<string name="demo_permission_camera_dialog_alert">在设置-应用-%s-权限中开启相机权限,以正常使用拍照、摄像、视频通话和快速会议功能</string>
<string name="demo_permission_storage_dialog_alert">在设置-应用-%s-权限中开启存储权限,以正常使用保存照片和视频功能</string>
</resources>
......@@ -90,5 +90,9 @@
<item name="android:background">#808080</item>
</style>
<style name="line_3">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">1px</item>
<item name="android:background">#E8E8F0</item>
</style>
</resources>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment