修改交友布局

This commit is contained in:
2025-08-26 19:34:44 +08:00
commit 8eb8ac5397
3152 changed files with 1442170 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
package com.xscm.moduleutil.utils;
public class ARouteConstants {
public static final String DYNAMIC_DETAIL = "/moduleCircle/DynamicDetailActivity";
public static final String CIRCLE_LIST = "/moduleCircle/DynamicListActivity";
public static final String USER_HOME_PAGE = "/modulevocal/UserHomepageActivity";
public static final String USER_ALBUM_DETAIL = "/modulevocal/AlbumDetailActivity";
public static final String CREATE_ALBUM = "/modulevocal/CreateAlbumActivity";
public static final String ROOM_DETAILS = "/moduleroom/RoomActivity";
public static final String MY_ROOM = "/modulevocal/MyRoomActivity";
public static final String MY_ROOM_DETAILS = "/modulevocal/RoomDetailsActivity";
public static final String ME = "/modulemain/MainActivity";
public static final String ROOM_ALLOWANCE = "/modulevocal/RoomAllowanceActivity"; //补贴明细
public static final String ROOM_ALLOWANCE_DETAIL = "/modulevocal/RoomAllowanceDetailActivity"; //补贴历史
public static final String CURRENCY = "/modulevocal/CurrencyExchangeActivity"; //补贴历史
public static final String CREATED_ROOM = "/modulevocal/CreatedRoomActivity"; //创建房间
public static final String WITHDRAWAL_ACTIVITY = "/modulevocal/WithdrawalActivity"; //提现
public static final String REAL_NAME_ACTIVITY ="/modulevocal/RealNameActivity"; //实名认证
public static final String REAL_NAME_ACTIVITY2 ="/app/RealNameActivity"; //实名认证
public static final String H5 ="/moduleutil/WebViewActivity"; //网页
public static final String GIFT_WALL ="/moduleroom/UserGiftWallFragment"; //实名认证
public static final String RECHARGE_ACTIVITY ="/modulevocal/RechargeActivity"; //实名认证
public static final String FRAGMENT_CIRCLE = "CirleListFragment";
public static final String FRAGMENT_GIFT_WALL = "UserGiftWallFragment";
public static final String FRAGMENT_ALBUM = "MyAlbumFragment";
}

View File

@@ -0,0 +1,19 @@
package com.xscm.moduleutil.utils;
import android.content.Intent;
/**
* Created by cxf on 2018/9/29.
*/
public abstract class ActivityResultCallback {
public abstract void onSuccess(Intent intent);
public void onFailure() {
}
public void onResult(int resultCode, Intent intent) {
}
}

View File

@@ -0,0 +1,84 @@
package com.xscm.moduleutil.utils;
import com.xscm.moduleutil.base.CommonAppContext;
import java.net.Proxy;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
public class ApiHelper {
private static final String TAG = "ApiHelper";
private static ApiHelper mInstance;
private Retrofit mRetrofit;
private OkHttpClient mHttpClient;
private ApiHelper() {
this(30, 30, 30);
}
public ApiHelper(int connTimeout, int readTimeout, int writeTimeout) {
try {
X509TrustManager trustAllCert = new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
};
SSLContext sslContext = null;
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{trustAllCert}, new SecureRandom());
OkHttpClient.Builder builder = new OkHttpClient.Builder()
// .addInterceptor(new WifiProxyInterceptor(MyApplication.getInstance()))
.proxy(Proxy.NO_PROXY)
.sslSocketFactory(sslContext.getSocketFactory(), trustAllCert)
.hostnameVerifier((hostname, session) -> true)
.connectTimeout(connTimeout, TimeUnit.SECONDS)
.readTimeout(readTimeout, TimeUnit.SECONDS)
.writeTimeout(writeTimeout, TimeUnit.SECONDS);
mHttpClient = builder.build();
buildRetrofit(CommonAppContext.getInstance().getCurrentEnvironment().getServerUrl());
} catch (KeyManagementException | NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public static ApiHelper getInstance() {
if (mInstance == null) {
mInstance = new ApiHelper();
}
return mInstance;
}
public ApiHelper buildRetrofit(String baseUrl) {
mRetrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(mHttpClient)
.build();
return this;
}
public <T> T createService(Class<T> serviceClass) {
return mRetrofit.create(serviceClass);
}
}

View File

@@ -0,0 +1,14 @@
package com.xscm.moduleutil.utils;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Streaming;
import retrofit2.http.Url;
public interface ApiInterface {
@Streaming //大文件时要加不然会OOM
@GET
Call<ResponseBody> downloadFile(@Url String fileUrl);
}

View File

@@ -0,0 +1,110 @@
// 在 moduleUtil 中创建 BackgroundManager.java
package com.xscm.moduleutil.utils;
import android.graphics.drawable.Drawable;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import java.util.ArrayList;
import java.util.List;
/**
*@author qx
*@data 2025/8/12
*@description: 背景图片的单例类
*/
public class BackgroundManager {
private static BackgroundManager instance;
private String backgroundUrl;
private Drawable backgroundDrawable;
private List<BackgroundUpdateListener> listeners = new ArrayList<>();
public static BackgroundManager getInstance() {
if (instance == null) {
synchronized (BackgroundManager.class) {
if (instance == null) {
instance = new BackgroundManager();
}
}
}
return instance;
}
public void setBackgroundUrl(String url) {
this.backgroundUrl = url;
loadBackground();
}
public String getBackgroundUrl() {
return backgroundUrl;
}
public Drawable getBackgroundDrawable() {
return backgroundDrawable;
}
private void loadBackground() {
if (backgroundUrl == null || backgroundUrl.isEmpty()) {
return;
}
// 这里使用一个临时的 ImageView 来加载图片
// 实际项目中可能需要使用 Application Context
// 为简化,这里直接加载到 drawable
}
public void loadBackgroundDrawable(android.content.Context context, BackgroundLoadCallback callback) {
if (backgroundUrl == null || backgroundUrl.isEmpty()) {
callback.onLoadFailed();
return;
}
Glide.with(context)
.asDrawable()
.load(backgroundUrl)
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
backgroundDrawable = resource;
callback.onLoadSuccess(resource);
notifyBackgroundUpdated(resource);
}
@Override
public void onLoadCleared(Drawable placeholder) {
callback.onLoadFailed();
}
@Override
public void onLoadFailed(Drawable errorDrawable) {
super.onLoadFailed(errorDrawable);
callback.onLoadFailed();
}
});
}
public void addListener(BackgroundUpdateListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
public void removeListener(BackgroundUpdateListener listener) {
listeners.remove(listener);
}
private void notifyBackgroundUpdated(Drawable drawable) {
for (BackgroundUpdateListener listener : listeners) {
listener.onBackgroundUpdated(drawable);
}
}
public interface BackgroundLoadCallback {
void onLoadSuccess(Drawable drawable);
void onLoadFailed();
}
public interface BackgroundUpdateListener {
void onBackgroundUpdated(Drawable drawable);
}
}

View File

@@ -0,0 +1,578 @@
package com.xscm.moduleutil.utils;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Build;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import androidx.annotation.ColorInt;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.drawerlayout.widget.DrawerLayout;
import com.blankj.utilcode.util.Utils;
import java.lang.reflect.Method;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2016/09/23
* desc : 栏相关工具类
* </pre>
*/
public final class BarUtils {
///////////////////////////////////////////////////////////////////////////
// status bar
///////////////////////////////////////////////////////////////////////////
private static final int DEFAULT_ALPHA = 112;
private static final String TAG_COLOR = "TAG_COLOR";
private static final String TAG_ALPHA = "TAG_ALPHA";
private static final int TAG_OFFSET = -123;
private BarUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/**
* 获取状态栏高度单位px
*
* @return 状态栏高度单位px
*/
public static int getStatusBarHeight() {
Resources resources = Utils.getApp().getResources();
int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
return resources.getDimensionPixelSize(resourceId);
}
/**
* 设置状态栏是否可见
*
* @param activity activity
* @param isVisible {@code true}: 可见<br>{@code false}: 不可见
*/
public static void setStatusBarVisibility(final Activity activity, final boolean isVisible) {
if (isVisible) {
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
/**
* 判断状态栏是否可见
*
* @param activity activity
* @return {@code true}: 可见<br>{@code false}: 不可见
*/
public static boolean isStatusBarVisible(final Activity activity) {
int flags = activity.getWindow().getAttributes().flags;
return (flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0;
}
/**
* 为 view 增加 MarginTop 为状态栏高度
*
* @param view view
*/
public static void addMarginTopEqualStatusBarHeight(@NonNull View view) {
Object haveSetOffset = view.getTag(TAG_OFFSET);
if (haveSetOffset != null && (Boolean) haveSetOffset) return;
MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
layoutParams.setMargins(layoutParams.leftMargin,
layoutParams.topMargin + getStatusBarHeight(),
layoutParams.rightMargin,
layoutParams.bottomMargin);
view.setTag(TAG_OFFSET, true);
}
/**
* 为 view 减少 MarginTop 为状态栏高度
*
* @param view view
*/
public static void subtractMarginTopEqualStatusBarHeight(@NonNull View view) {
Object haveSetOffset = view.getTag(TAG_OFFSET);
if (haveSetOffset == null || !(Boolean) haveSetOffset) return;
MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
layoutParams.setMargins(layoutParams.leftMargin,
layoutParams.topMargin - getStatusBarHeight(),
layoutParams.rightMargin,
layoutParams.bottomMargin);
view.setTag(TAG_OFFSET, false);
}
/**
* 设置状态栏颜色
*
* @param activity activity
* @param color 状态栏颜色值
*/
public static void setStatusBarColor(@NonNull final Activity activity,
@ColorInt final int color) {
setStatusBarColor(activity, color, DEFAULT_ALPHA, false);
}
/**
* 设置状态栏颜色
*
* @param activity activity
* @param color 状态栏颜色值
* @param alpha 状态栏透明度,此透明度并非颜色中的透明度
*/
public static void setStatusBarColor(@NonNull final Activity activity,
@ColorInt final int color,
@IntRange(from = 0, to = 255) final int alpha) {
setStatusBarColor(activity, color, alpha, false);
}
/**
* 设置状态栏颜色
*
* @param activity activity
* @param color 状态栏颜色值
* @param alpha 状态栏透明度,此透明度并非颜色中的透明度
* @param isDecor {@code true}: 设置在 DecorView 中<br>
* {@code false}: 设置在 ContentView 中
*/
public static void setStatusBarColor(@NonNull final Activity activity,
@ColorInt final int color,
@IntRange(from = 0, to = 255) final int alpha,
final boolean isDecor) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
hideAlphaView(activity);
transparentStatusBar(activity);
addStatusBarColor(activity, color, alpha, isDecor);
}
/**
* 设置状态栏透明度
*
* @param activity activity
*/
public static void setStatusBarAlpha(@NonNull final Activity activity) {
setStatusBarAlpha(activity, DEFAULT_ALPHA, false);
}
/**
* 设置状态栏透明度
*
* @param activity activity
*/
public static void setStatusBarAlpha(@NonNull final Activity activity,
@IntRange(from = 0, to = 255) final int alpha) {
setStatusBarAlpha(activity, alpha, false);
}
/**
* 设置状态栏透明度
*
* @param activity activity
* @param alpha 状态栏透明度
* @param isDecor {@code true}: 设置在 DecorView 中<br>
* {@code false}: 设置在 ContentView 中
*/
public static void setStatusBarAlpha(@NonNull final Activity activity,
@IntRange(from = 0, to = 255) final int alpha,
final boolean isDecor) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
hideColorView(activity);
transparentStatusBar(activity);
addStatusBarAlpha(activity, alpha, isDecor);
}
/**
* 设置状态栏颜色
*
* @param fakeStatusBar 伪造状态栏
* @param color 状态栏颜色值
*/
public static void setStatusBarColor(@NonNull final View fakeStatusBar,
@ColorInt final int color) {
setStatusBarColor(fakeStatusBar, color, DEFAULT_ALPHA);
}
/**
* 设置状态栏颜色
*
* @param fakeStatusBar 伪造状态栏
* @param color 状态栏颜色值
* @param alpha 状态栏透明度,此透明度并非颜色中的透明度
*/
public static void setStatusBarColor(@NonNull final View fakeStatusBar,
@ColorInt final int color,
@IntRange(from = 0, to = 255) final int alpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
fakeStatusBar.setVisibility(View.VISIBLE);
transparentStatusBar((Activity) fakeStatusBar.getContext());
ViewGroup.LayoutParams layoutParams = fakeStatusBar.getLayoutParams();
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.height = BarUtils.getStatusBarHeight();
fakeStatusBar.setBackgroundColor(getStatusBarColor(color, alpha));
}
/**
* 设置状态栏透明度
*
* @param fakeStatusBar 伪造状态栏
*/
public static void setStatusBarAlpha(@NonNull final View fakeStatusBar) {
setStatusBarAlpha(fakeStatusBar, DEFAULT_ALPHA);
}
/**
* 设置状态栏透明度
*
* @param fakeStatusBar 伪造状态栏
* @param alpha 状态栏透明度
*/
public static void setStatusBarAlpha(@NonNull final View fakeStatusBar,
@IntRange(from = 0, to = 255) final int alpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
fakeStatusBar.setVisibility(View.VISIBLE);
transparentStatusBar((Activity) fakeStatusBar.getContext());
ViewGroup.LayoutParams layoutParams = fakeStatusBar.getLayoutParams();
layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
layoutParams.height = BarUtils.getStatusBarHeight();
fakeStatusBar.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
}
/**
* 为 DrawerLayout 设置状态栏颜色
* <p>DrawLayout 需设置 {@code android:fitsSystemWindows="true"}</p>
*
* @param activity activity
* @param drawer drawerLayout
* @param fakeStatusBar 伪造状态栏
* @param color 状态栏颜色值
* @param isTop drawerLayout 是否在顶层
*/
public static void setStatusBarColor4Drawer(@NonNull final Activity activity,
@NonNull final DrawerLayout drawer,
@NonNull final View fakeStatusBar,
@ColorInt final int color,
final boolean isTop) {
setStatusBarColor4Drawer(activity, drawer, fakeStatusBar, color, DEFAULT_ALPHA, isTop);
}
/**
* 为 DrawerLayout 设置状态栏颜色
* <p>DrawLayout 需设置 {@code android:fitsSystemWindows="true"}</p>
*
* @param activity activity
* @param drawer drawerLayout
* @param fakeStatusBar 伪造状态栏
* @param color 状态栏颜色值
* @param alpha 状态栏透明度,此透明度并非颜色中的透明度
* @param isTop drawerLayout 是否在顶层
*/
public static void setStatusBarColor4Drawer(@NonNull final Activity activity,
@NonNull final DrawerLayout drawer,
@NonNull final View fakeStatusBar,
@ColorInt final int color,
@IntRange(from = 0, to = 255) final int alpha,
final boolean isTop) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
drawer.setFitsSystemWindows(false);
transparentStatusBar(activity);
setStatusBarColor(fakeStatusBar, color, isTop ? alpha : 0);
for (int i = 0, len = drawer.getChildCount(); i < len; i++) {
drawer.getChildAt(i).setFitsSystemWindows(false);
}
if (isTop) {
hideAlphaView(activity);
} else {
addStatusBarAlpha(activity, alpha, false);
}
}
/**
* 为 DrawerLayout 设置状态栏透明度
* <p>DrawLayout 需设置 {@code android:fitsSystemWindows="true"}</p>
*
* @param activity activity
* @param drawer drawerLayout
* @param fakeStatusBar 伪造状态栏
* @param isTop drawerLayout 是否在顶层
*/
public static void setStatusBarAlpha4Drawer(@NonNull final Activity activity,
@NonNull final DrawerLayout drawer,
@NonNull final View fakeStatusBar,
final boolean isTop) {
setStatusBarAlpha4Drawer(activity, drawer, fakeStatusBar, DEFAULT_ALPHA, isTop);
}
/**
* 为 DrawerLayout 设置状态栏透明度
* <p>DrawLayout 需设置 {@code android:fitsSystemWindows="true"}</p>
*
* @param activity activity
* @param drawer drawerLayout
* @param fakeStatusBar 伪造状态栏
* @param alpha 状态栏透明度
* @param isTop drawerLayout 是否在顶层
*/
public static void setStatusBarAlpha4Drawer(@NonNull final Activity activity,
@NonNull final DrawerLayout drawer,
@NonNull final View fakeStatusBar,
@IntRange(from = 0, to = 255) final int alpha,
final boolean isTop) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
drawer.setFitsSystemWindows(false);
transparentStatusBar(activity);
setStatusBarAlpha(fakeStatusBar, isTop ? alpha : 0);
for (int i = 0, len = drawer.getChildCount(); i < len; i++) {
drawer.getChildAt(i).setFitsSystemWindows(false);
}
if (isTop) {
hideAlphaView(activity);
} else {
addStatusBarAlpha(activity, alpha, false);
}
}
private static void addStatusBarColor(final Activity activity,
final int color,
final int alpha,
boolean isDecor) {
ViewGroup parent = isDecor ?
(ViewGroup) activity.getWindow().getDecorView() :
(ViewGroup) activity.findViewById(android.R.id.content);
View fakeStatusBarView = parent.findViewWithTag(TAG_COLOR);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(getStatusBarColor(color, alpha));
} else {
parent.addView(createColorStatusBarView(parent.getContext(), color, alpha));
}
}
private static void addStatusBarAlpha(final Activity activity,
final int alpha,
boolean isDecor) {
ViewGroup parent = isDecor ?
(ViewGroup) activity.getWindow().getDecorView() :
(ViewGroup) activity.findViewById(android.R.id.content);
View fakeStatusBarView = parent.findViewWithTag(TAG_ALPHA);
if (fakeStatusBarView != null) {
if (fakeStatusBarView.getVisibility() == View.GONE) {
fakeStatusBarView.setVisibility(View.VISIBLE);
}
fakeStatusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
} else {
parent.addView(createAlphaStatusBarView(parent.getContext(), alpha));
}
}
private static void hideColorView(final Activity activity) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View fakeStatusBarView = decorView.findViewWithTag(TAG_COLOR);
if (fakeStatusBarView == null) return;
fakeStatusBarView.setVisibility(View.GONE);
}
private static void hideAlphaView(final Activity activity) {
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
View fakeStatusBarView = decorView.findViewWithTag(TAG_ALPHA);
if (fakeStatusBarView == null) return;
fakeStatusBarView.setVisibility(View.GONE);
}
private static int getStatusBarColor(final int color, final int alpha) {
if (alpha == 0) return color;
float a = 1 - alpha / 255f;
int red = (color >> 16) & 0xff;
int green = (color >> 8) & 0xff;
int blue = color & 0xff;
red = (int) (red * a + 0.5);
green = (int) (green * a + 0.5);
blue = (int) (blue * a + 0.5);
return Color.argb(255, red, green, blue);
}
/**
* 绘制一个和状态栏一样高的颜色矩形
*/
private static View createColorStatusBarView(final Context context,
final int color,
final int alpha) {
View statusBarView = new View(context);
statusBarView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight()));
statusBarView.setBackgroundColor(getStatusBarColor(color, alpha));
statusBarView.setTag(TAG_COLOR);
return statusBarView;
}
/**
* 绘制一个和状态栏一样高的黑色透明度矩形
*/
private static View createAlphaStatusBarView(final Context context, final int alpha) {
View statusBarView = new View(context);
statusBarView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight()));
statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
statusBarView.setTag(TAG_ALPHA);
return statusBarView;
}
private static void transparentStatusBar(final Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
Window window = activity.getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
int option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
window.getDecorView().setSystemUiVisibility(option);
window.setStatusBarColor(Color.TRANSPARENT);
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
///////////////////////////////////////////////////////////////////////////
// action bar
///////////////////////////////////////////////////////////////////////////
/**
* 获取 ActionBar 高度
*
* @param activity activity
* @return ActionBar 高度
*/
public static int getActionBarHeight(@NonNull final Activity activity) {
TypedValue tv = new TypedValue();
if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
return TypedValue.complexToDimensionPixelSize(
tv.data, activity.getResources().getDisplayMetrics()
);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////
// notification bar
///////////////////////////////////////////////////////////////////////////
/**
* 设置通知栏是否可见
* <p>需添加权限
* {@code <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />}</p>
*
* @param isVisible {@code true}: 可见<br>{@code false}: 关闭
*/
public static void setNotificationBarVisibility(final boolean isVisible) {
String methodName;
if (isVisible) {
methodName = (Build.VERSION.SDK_INT <= 16) ? "expand" : "expandNotificationsPanel";
} else {
methodName = (Build.VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels";
}
invokePanels(methodName);
}
private static void invokePanels(final String methodName) {
try {
@SuppressLint("WrongConstant")
Object service = Utils.getApp().getSystemService("statusbar");
@SuppressLint("PrivateApi")
Class<?> statusBarManager = Class.forName("android.app.StatusBarManager");
Method expand = statusBarManager.getMethod(methodName);
expand.invoke(service);
} catch (Exception e) {
e.printStackTrace();
}
}
///////////////////////////////////////////////////////////////////////////
// navigation bar
///////////////////////////////////////////////////////////////////////////
/**
* 获取导航栏高度
*
* @return 导航栏高度
*/
public static int getNavBarHeight() {
Resources res = Utils.getApp().getResources();
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId != 0) {
return res.getDimensionPixelSize(resourceId);
} else {
return 0;
}
}
/**
* 设置导航栏是否可见
*
* @param activity activity
* @param isVisible {@code true}: 可见<br>{@code false}: 不可见
*/
public static void setNavBarVisibility(final Activity activity, boolean isVisible) {
if (isVisible) {
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
View decorView = activity.getWindow().getDecorView();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int visibility = decorView.getSystemUiVisibility();
decorView.setSystemUiVisibility(visibility & ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
}
/**
* 设置导航栏沉浸式
*
* @param activity activity
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public static void setNavBarImmersive(final Activity activity) {
View decorView = activity.getWindow().getDecorView();
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);
}
/**
* 判断导航栏是否可见
*
* @param activity activity
* @return {@code true}: 可见<br>{@code false}: 不可见
*/
public static boolean isNavBarVisible(final Activity activity) {
boolean isNoLimits = (activity.getWindow().getAttributes().flags
& WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) != 0;
if (isNoLimits) return false;
View decorView = activity.getWindow().getDecorView();
int visibility = decorView.getSystemUiVisibility();
return (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
}
public static void setAndroidNativeLightStatusBar(Activity activity, boolean dark) {
View decor = activity.getWindow().getDecorView();
if (dark) {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
}
}

View File

@@ -0,0 +1,46 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import com.google.android.material.bottomsheet.BottomSheetDialog;
public abstract class BaseBottomSheetDialog<VDM extends ViewDataBinding> extends BottomSheetDialog {
public Context mContext;
private Object object;
protected VDM mBinding;
public BaseBottomSheetDialog(@NonNull Context context) {
super(context);
this.mContext = context;
mBinding = DataBindingUtil.bind(LayoutInflater.from(context).inflate(getLayout(), null, false));
if (mBinding != null) {
setContentView(mBinding.getRoot());
((View) mBinding.getRoot().getParent()).setBackgroundColor(Color.parseColor("#00000000"));
}
initView();
initData();
}
public abstract int getLayout();
public abstract void initView();
public abstract void initData();
public void setTag(Object object) {
this.object = object;
}
public Object getTag() {
return object;
}
}

View File

@@ -0,0 +1,38 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.content.Intent;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuikit.tuichat.classicui.page.TUIC2CChatActivity;
public class ChatLauncher {
private static volatile ChatLauncher instance;
private ChatLauncher() {}
public static ChatLauncher getInstance() {
if (instance == null) {
synchronized (ChatLauncher.class) {
if (instance == null) {
instance = new ChatLauncher();
}
}
}
return instance;
}
/**
* 启动 C2C 聊天界面
* @param context 上下文
* @param chatId 聊天对象 ID用户 ID
*/
public void launchC2CChat(Context context, String chatId) {
Intent intent = new Intent(context, TUIC2CChatActivity.class);
intent.putExtra(TUIConstants.TUIChat.CHAT_ID, "u"+chatId);
intent.putExtra(TUIConstants.TUIChat.CHAT_TYPE, V2TIMConversation.V2TIM_C2C);
context.startActivity(intent);
}
}

View File

@@ -0,0 +1,113 @@
package com.xscm.moduleutil.utils;
import android.graphics.Color;
import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author qx
* @data 2025/8/13
* @description: 颜色的管理器,从服务器获取的颜色数据,进行更改,
* 这里是两个颜色,一个主题色,一个是按钮文字颜色
*/
public class ColorManager {
private static ColorManager instance;
private String primaryColor = "#6C49E4"; // 默认主题色
private String buttonColor = "#FFFFFF"; // 默认按钮色
// 监听器列表,用于通知颜色变化
private List<ColorChangeListener> listeners = new ArrayList<>();
public static ColorManager getInstance() {
if (instance == null) {
synchronized (ColorManager.class) {
if (instance == null) {
instance = new ColorManager();
}
}
}
return instance;
}
// 更新颜色配置
public void updateColors(String primary, String button) {
boolean changed = false;
if (primary != null && !primary.equals(this.primaryColor)) {
this.primaryColor = primary;
changed = true;
}
if (button != null && !button.equals(this.buttonColor)) {
this.buttonColor = button;
changed = true;
}
// 如果颜色有变化,通知所有监听者
if (changed) {
notifyColorChanged();
}
}
// 获取颜色值
public String getPrimaryColor() {
return primaryColor;
}
public String getButtonColor() {
return buttonColor;
}
// 解析颜色为int值
public int getPrimaryColorInt() {
try {
return Color.parseColor(primaryColor);
} catch (Exception e) {
return Color.parseColor("#6C49E4"); // 默认颜色
}
}
public int getButtonColorInt() {
try {
return Color.parseColor(buttonColor);
} catch (Exception e) {
return Color.parseColor("#FFFFFF"); // 默认颜色
}
}
// 颜色变化监听器接口
public interface ColorChangeListener {
void onColorChanged();
}
// 添加监听器
public void addColorChangeListener(ColorChangeListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
// 移除监听器
public void removeColorChangeListener(ColorChangeListener listener) {
listeners.remove(listener);
}
// 通知颜色变化
private void notifyColorChanged() {
for (ColorChangeListener listener : listeners) {
if (listener != null) {
listener.onColorChanged();
}
}
}
}

View File

@@ -0,0 +1,39 @@
package com.xscm.moduleutil.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by cxf on 2018/7/19.
*/
public class DateFormatUtil {
private static SimpleDateFormat sFormat;
private static SimpleDateFormat sFormat2;
private static SimpleDateFormat sFormat3;
private static SimpleDateFormat sFormat4;
static {
sFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
sFormat2 = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS");
sFormat3 = new SimpleDateFormat("MM.dd-HH:mm:ss");
sFormat4=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
public static String getCurTimeString() {
return sFormat.format(new Date());
}
public static String getVideoCurTimeString() {
return sFormat2.format(new Date());
}
public static String getCurTimeString2() {
return sFormat3.format(new Date());
}
public static String getCurTimeString3() {
return sFormat4.format(new Date());
}
}

View File

@@ -0,0 +1,188 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.view.View;
import androidx.annotation.NonNull;
import com.xscm.moduleutil.R;
import com.xscm.moduleutil.bean.DateBean;
import com.xscm.moduleutil.databinding.MeDialogDateSelectBinding;
import com.xscm.moduleutil.widget.picker.PickerView;
import java.util.ArrayList;
import java.util.List;
/**
* 日期选择
*/
public class DateSelectDialog extends BaseBottomSheetDialog<MeDialogDateSelectBinding> {
private int year = 0;
private int month = 0;
private OnSelectDate mOnSelectDate;
private List<DateBean> yearList;
private List<DateBean> monthList;
private List<DateBean> dayList;
public DateSelectDialog(@NonNull Context context) {
super(context);
}
@Override
public int getLayout() {
return R.layout.me_dialog_date_select;
}
@Override
public void initView() {
this.setCancelable(false);
this.setCanceledOnTouchOutside(false);
mBinding.tvCancel.setOnClickListener(this::onClick);
mBinding.tvConfirm.setOnClickListener(this::onClick);
}
@Override
public void initData() {
setYear();
mBinding.pickerViewYear.setSelectedItemPosition(yearList.size());
setMonth(TimeUtils.getYear());
mBinding.pickerViewMonth.setSelectedItemPosition(monthList.size());
setDay(TimeUtils.getYear(), TimeUtils.getMonth());
mBinding.pickerViewDay.setSelectedItemPosition(dayList.size());
}
public void setData(String y, String m, String d) {
int yIndex = 0;
for (int i = 0; i < yearList.size(); i++) {
DateBean dateBean = yearList.get(i);
if (dateBean.getText().equals(y)) {
yIndex = i;
}
}
mBinding.pickerViewYear.setSelectedItemPosition(yIndex);
monthList = getMonth(Integer.parseInt(y));
int mIndex = 0;
for (int i = 0; i < monthList.size(); i++) {
DateBean dateBean = monthList.get(i);
if (dateBean.getText().equals(m)) {
mIndex = i;
}
}
mBinding.pickerViewMonth.setSelectedItemPosition(mIndex);
dayList = getDay(Integer.parseInt(y), Integer.parseInt(m));
int dIndex = 0;
for (int i = 0; i < dayList.size(); i++) {
DateBean dateBean = dayList.get(i);
if (dateBean.getText().equals(d)) {
dIndex = i;
}
}
mBinding.pickerViewDay.setSelectedItemPosition(dIndex);
}
private void setDay(int year, int month) {
dayList = getDay(year, month);
mBinding.pickerViewDay.setItems(dayList, new PickerView.OnItemSelectedListener<DateBean>() {
@Override
public void onItemSelected(DateBean item) {
}
});
mBinding.pickerViewDay.notifyDataSetChanged();
}
private void setMonth(int year) {
monthList = getMonth(year);
mBinding.pickerViewMonth.setItems(monthList, new PickerView.OnItemSelectedListener<DateBean>() {
@Override
public void onItemSelected(DateBean item) {
month = item.getDate();
setDay(year, month);
}
});
mBinding.pickerViewMonth.notifyDataSetChanged();
}
private void setYear() {
yearList = getYear();
mBinding.pickerViewYear.setItems(yearList, new PickerView.OnItemSelectedListener<DateBean>() {
@Override
public void onItemSelected(DateBean item) {
year = item.getDate();
setMonth(year);
}
});
mBinding.pickerViewYear.notifyDataSetChanged();
}
private List<DateBean> getDay(int year, int month) {
int day = TimeUtils.getDaysByYearMonth(year, month);
if (year == TimeUtils.getYear() && month == TimeUtils.getMonth()) {
day = TimeUtils.getDay();
}
List<DateBean> dayList = new ArrayList<>();
for (int i = 1; i <= day; i++) {
if (i <= 9) {
dayList.add(new DateBean("0" + i, i));
} else {
dayList.add(new DateBean(String.valueOf(i), i));
}
}
return dayList;
}
private List<DateBean> getMonth(int year) {
List<DateBean> mothList = new ArrayList<>();
int month = 12;
if (year == TimeUtils.getYear()) {
month = TimeUtils.getMonth();
}
for (int i = 1; i <= month; i++) {
if (i <= 9) {
mothList.add(new DateBean("0" + i, i));
} else {
mothList.add(new DateBean(String.valueOf(i), i));
}
}
return mothList;
}
private List<DateBean> getYear() {
int year = TimeUtils.getYear();
List<DateBean> yearList = new ArrayList<>();
for (int i = 1900; i <= year; i++) {
yearList.add(new DateBean(String.valueOf(i), i));
}
return yearList;
}
public void onClick(View view) {
dismiss();
if (view.getId() == R.id.tv_confirm) {
if (mOnSelectDate != null) {
DateBean year = mBinding.pickerViewYear.getSelectedItem(DateBean.class);
DateBean month = mBinding.pickerViewMonth.getSelectedItem(DateBean.class);
DateBean day = mBinding.pickerViewDay.getSelectedItem(DateBean.class);
mOnSelectDate.selectDate(year.getText(), month.getText(), day.getText());
}
}
}
public void setmOnSelectDate(OnSelectDate mOnSelectDate) {
this.mOnSelectDate = mOnSelectDate;
}
public interface OnSelectDate {
void selectDate(String year, String month, String day);
}
}

View File

@@ -0,0 +1,28 @@
package com.xscm.moduleutil.utils;
import android.os.Build;
import android.provider.Settings;
import com.xscm.moduleutil.widget.CommonAppConfig;
import com.xscm.moduleutil.base.CommonAppContext;
public class DeviceUtils {
public static String getDeviceId() {
String s = StringUtil.contact(
Settings.System.getString(CommonAppContext.getInstance().getContentResolver(), Settings.System.ANDROID_ID),
Build.SERIAL,
Build.FINGERPRINT,
String.valueOf(Build.TIME),
Build.USER,
Build.HOST,
Build.getRadioVersion(),
Build.HARDWARE,
CommonAppConfig.PACKAGE_NAME1
);
return Md5Utils.getMD5(s);
}
}

View File

@@ -0,0 +1,56 @@
package com.xscm.moduleutil.utils;
import android.app.Activity;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.blankj.utilcode.util.ActivityUtils;
import com.xscm.moduleutil.widget.dialog.CommonDialog;
public class DialogUtils {
public static void showNoBalance() {
Activity activity = ActivityUtils.getTopActivity();
if (!(activity instanceof FragmentActivity)) {
return;
}
CommonDialog commonDialog = new CommonDialog(activity);
commonDialog.setContent("您的余额已不足,请及时充值");
commonDialog.setLeftText("再想想");
commonDialog.setRightText("去充值");
commonDialog.setmOnClickListener(new CommonDialog.OnClickListener() {
@Override
public void onLeftClick() {
}
@Override
public void onRightClick() {
// DialogFragment navigation = (DialogFragment) ARouter.getInstance().build(ARouteConstants.RECHARGE_DIALOG).navigation();
// navigation.show(((FragmentActivity) activity).getSupportFragmentManager(), "RechargeDialogFragment");
}
});
commonDialog.show();
}
public static void showDialogFragment(Object object) {
showDialogFragment(object, null);
}
public static void showDialogFragment(Object object, FragmentManager fragmentManager) {
if (object instanceof DialogFragment) {
Activity topActivity = ActivityUtils.getTopActivity();
if (fragmentManager == null && topActivity instanceof FragmentActivity) {
fragmentManager = ((FragmentActivity) topActivity).getSupportFragmentManager();
}
if (fragmentManager != null && !fragmentManager.isStateSaved()) {
((DialogFragment) object).show(fragmentManager, object.getClass().getSimpleName());
} else {
ActivityUtils.finishActivity(topActivity);
}
}
}
}

View File

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

View File

@@ -0,0 +1,11 @@
package com.xscm.moduleutil.utils;
public interface DownloadListener {
void onStart();
void onProgress(int currentLength);
void onFinish(String localPath);
void onFailure();
}

View File

@@ -0,0 +1,276 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Log;
import com.alibaba.android.arouter.utils.TextUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.ThreadUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class DownloadUtil {
private static final String TAG = DownloadUtil.class.getCanonicalName();
private static final Handler HANDLER = new Handler(Looper.getMainLooper());
protected ApiInterface mApi;
private Call<ResponseBody> mCall;
private File mFile;
private Thread mThread;
private String mApkPath; //下载到本地的视频路径
private Context mContext;
// private static final String PATH_APK = Environment.getExternalStorageDirectory() + "/qipao/apk";
private static final String PATH_APK = "/qipao/apk";
private static final String PATH_AUDIO = Environment.getExternalStorageDirectory() + "/qipao/audio";
public DownloadUtil(Context context) {
this.mContext = context;
if (mApi == null) {
//初始化网络请求接口
mApi = ApiHelper.getInstance().createService(ApiInterface.class);
mApkPath = new File(mContext.getFilesDir(), PATH_APK).getAbsolutePath();
}
}
public void downloadVoiceFile(String url, final DownloadListener downloadListener) {
String name = url;
//通过Url得到文件并创建本地文件
if (FileUtils.createOrExistsDir(PATH_AUDIO)) {
int i = name.lastIndexOf('/');//一定是找最后一个'/'出现的位置
if (i != -1) {
name = System.currentTimeMillis() + name.substring(i);
}
}
File file = new File(PATH_AUDIO, name);
Call<ResponseBody> download = ApiHelper.getInstance().createService(ApiInterface.class).downloadFile(url);
download.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response != null && response.isSuccessful()) {
ThreadUtils.executeByCached(new ThreadUtils.SimpleTask<Boolean>() {
@Nullable
@Override
public Boolean doInBackground() throws Throwable {
return writeResponseBodyToDisk(response.body(), file, downloadListener);
}
@Override
public void onSuccess(@Nullable Boolean result) {
if (result != null && result) {
System.out.println("下载成功请查看");
} else {
System.out.println("下载失败,请稍后重试");
}
}
});
} else {
System.out.println("服务器返回错误");
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
System.out.println("网络不可用");
}
});
}
/**
* 下载到本地
*
* @param body 内容
* @param file
* @param downloadListener
* @return 成功或者失败
*/
private boolean writeResponseBodyToDisk(ResponseBody body, File file, DownloadListener downloadListener) {
try {
//创建一个文件
if (FileUtils.isFileExists(file) || !FileUtils.createOrExistsFile(file)) {
return false;
}
//初始化输入流
InputStream inputStream = null;
//初始化输出流
OutputStream outputStream = null;
try {
//设置每次读写的字节
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
//请求返回的字节流
inputStream = body.byteStream();
//创建输出流
outputStream = new FileOutputStream(file);
//进行读取操作
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
//进行写入操作
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
}
//刷新
outputStream.flush();
HANDLER.post(new Runnable() {
@Override
public void run() {
downloadListener.onFinish(file.getAbsolutePath()); //下载完成
}
});
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
if (inputStream != null) {
//关闭输入流
inputStream.close();
}
if (outputStream != null) {
//关闭输出流
outputStream.close();
}
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public void downloadFile(String url, final DownloadListener downloadListener) {
String name = url;
//通过Url得到文件并创建本地文件
if (FileUtils.createOrExistsDir(PATH_APK)) {
int i = name.lastIndexOf('/');//一定是找最后一个'/'出现的位置
if (i != -1) {
name = System.currentTimeMillis() + name.substring(i);
mApkPath = PATH_APK
+ name;
}
}
if (TextUtils.isEmpty(mApkPath)) {
Log.e(TAG, "downloadApk: 存储路径为空了");
return;
}
//建立一个文件
mFile = new File(mApkPath);
if (FileUtils.createFileByDeleteOldFile(mFile)) {
if (mApi == null) {
Log.e(TAG, "downloadApk: 下载接口为空了");
return;
}
mCall = mApi.downloadFile(url);
mCall.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call, @NonNull final Response<ResponseBody> response) {
//下载文件放在子线程
mThread = new Thread() {
@Override
public void run() {
super.run();
//保存到本地
writeFile2Disk(response, mFile, downloadListener);
}
};
mThread.start();
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
downloadListener.onFailure(); //下载失败
}
});
} else {
downloadListener.onFinish(mApkPath); //下载完成
}
}
private void writeFile2Disk(Response<ResponseBody> response, File file, DownloadListener downloadListener) {
HANDLER.post(new Runnable() {
@Override
public void run() {
downloadListener.onStart();
}
});
long currentLength = 0;
OutputStream os = null;
InputStream is = response.body().byteStream(); //获取下载输入流
long totalLength = response.body().contentLength();
try {
os = new FileOutputStream(file); //输出流
int len;
byte[] buff = new byte[1024];
while ((len = is.read(buff)) != -1) {
os.write(buff, 0, len);
currentLength += len;
Log.e(TAG, "当前进度: " + currentLength);
long finalCurrentLength = currentLength;
HANDLER.post(new Runnable() {
@Override
public void run() {
//计算当前下载百分比,并经由回调传出
downloadListener.onProgress((int) (100 * finalCurrentLength / totalLength));
}
});
//当百分比为100时下载结束调用结束回调并传出下载后的本地路径
if ((int) (100 * currentLength / totalLength) == 100) {
HANDLER.post(new Runnable() {
@Override
public void run() {
downloadListener.onFinish(mApkPath); //下载完成
}
});
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close(); //关闭输出流
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close(); //关闭输入流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

View File

@@ -0,0 +1,245 @@
package com.xscm.moduleutil.utils;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.blankj.utilcode.util.ScreenUtils;
public class FastBlurUtil {
public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {
Bitmap bitmap;
if (canReuseInBitmap) {
bitmap = sentBitmap;
} else {
bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
}
if (radius < 1) {
return (null);
}
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
int wm = w - 1;
int hm = h - 1;
int wh = w * h;
int div = radius + radius + 1;
int r[] = new int[wh];
int g[] = new int[wh];
int b[] = new int[wh];
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
int vmin[] = new int[Math.max(w, h)];
int divsum = (div + 1) >> 1;
divsum *= divsum;
int dv[] = new int[256 * divsum];
for (i = 0; i < 256 * divsum; i++) {
dv[i] = (i / divsum);
}
yw = yi = 0;
int[][] stack = new int[div][3];
int stackpointer;
int stackstart;
int[] sir;
int rbs;
int r1 = radius + 1;
int routsum, goutsum, boutsum;
int rinsum, ginsum, binsum;
for (y = 0; y < h; y++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
for (i = -radius; i <= radius; i++) {
p = pix[yi + Math.min(wm, Math.max(i, 0))];
sir = stack[i + radius];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rbs = r1 - Math.abs(i);
rsum += sir[0] * rbs;
gsum += sir[1] * rbs;
bsum += sir[2] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
}
stackpointer = radius;
for (x = 0; x < w; x++) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (y == 0) {
vmin[x] = Math.min(x + radius + 1, wm);
}
p = pix[yw + vmin[x]];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[(stackpointer) % div];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi++;
}
yw += w;
}
for (x = 0; x < w; x++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
yp = -radius * w;
for (i = -radius; i <= radius; i++) {
yi = Math.max(0, yp) + x;
sir = stack[i + radius];
sir[0] = r[yi];
sir[1] = g[yi];
sir[2] = b[yi];
rbs = r1 - Math.abs(i);
rsum += r[yi] * rbs;
gsum += g[yi] * rbs;
bsum += b[yi] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
if (i < hm) {
yp += w;
}
}
yi = x;
stackpointer = radius;
for (y = 0; y < h; y++) {
// Preserve alpha channel: ( 0xff000000 & pix[yi] )
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (x == 0) {
vmin[y] = Math.min(y + r1, hm) * w;
}
p = x + vmin[y];
sir[0] = r[p];
sir[1] = g[p];
sir[2] = b[p];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[stackpointer];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi += w;
}
}
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
return (bitmap);
}
public static Drawable getForegroundDrawable(Bitmap musicPicRes) {
/*得到屏幕的宽高比,以便按比例切割图片一部分*/
final float widthHeightSize = (float) (ScreenUtils.getScreenWidth()
* 1.0 / ScreenUtils.getScreenHeight() * 1.0);
Bitmap bitmap = musicPicRes;
int cropBitmapWidth = (int) (widthHeightSize * bitmap.getHeight());
int cropBitmapWidthX = (int) ((bitmap.getWidth() - cropBitmapWidth) / 2.0);
/*切割部分图片*/
Bitmap cropBitmap = Bitmap.createBitmap(bitmap, cropBitmapWidthX, 0, cropBitmapWidth,
bitmap.getHeight());
/*缩小图片*/
Bitmap scaleBitmap = Bitmap.createScaledBitmap(cropBitmap, bitmap.getWidth() / 50, bitmap
.getHeight() / 50, false);
/*模糊化*/
final Bitmap blurBitmap = FastBlurUtil.doBlur(scaleBitmap, 8, true);
final Drawable foregroundDrawable = new BitmapDrawable(blurBitmap);
/*加入灰色遮罩层,避免图片过亮影响其他控件*/
foregroundDrawable.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY);
return foregroundDrawable;
}
}

View File

@@ -0,0 +1,38 @@
package com.xscm.moduleutil.utils;
/**
* 悬浮窗辅助类
*/
public class FloatWindowHelper {
private static ActionListener sActionListener;
public static void setActionListener(ActionListener actionListener) {
sActionListener = actionListener;
}
public static boolean checkVoice(boolean enterLive) {
if (sActionListener != null) {
return sActionListener.checkVoice(enterLive);
}
return true;
}
public static void setFloatWindowVisible(boolean visible) {
if (sActionListener != null) {
sActionListener.setFloatWindowVisible(visible);
}
}
public interface ActionListener {
/**
* 是否可以播放声音
*/
boolean checkVoice(boolean enterLive);
/**
* 设置隐藏和显示
*/
void setFloatWindowVisible(boolean visible);
}
}

View File

@@ -0,0 +1,153 @@
package com.xscm.moduleutil.utils;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.view.View;
import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.ScreenUtils;
import com.xscm.moduleutil.widget.animator.ExplosionField;
public class GiftAnimatorUtil {
public static ObjectAnimator tada(View view) {
return tada(view, 1f);
}
public static void tadaAnim(View view) {
ObjectAnimator tada = tada(view, 1f);
tada.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
new ExplosionField(view.getContext()).explode(view, new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setVisibility(GONE);
}
});
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
tada.start();
}
public static void anim(View view, float oX, float oY) {
if (SpUtil.getOpenEffect() == 0) {
return;
}
view.setVisibility(VISIBLE);
view.setTranslationX(0);
view.setTranslationY(0);
ObjectAnimator tada = tada(view);
PropertyValuesHolder objectAnimatorY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, ScreenUtils.getScreenHeight(), oY);
int x = ScreenUtils.getScreenWidth() / 2;
PropertyValuesHolder objectAnimatorX = PropertyValuesHolder.ofFloat(View.TRANSLATION_X, x, oX);
ObjectAnimator valueAnimator = ObjectAnimator.ofPropertyValuesHolder(view, objectAnimatorY, objectAnimatorX).
setDuration(500);
AnimatorSet set = new AnimatorSet();
set.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
if (Math.abs(view.getY() - oY) < ConvertUtils.dp2px(50)) {
new ExplosionField(view.getContext()).explode(view, new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setVisibility(GONE);
}
});
} else {
view.setVisibility(GONE);
}
}
@Override
public void onAnimationCancel(Animator animator) {
view.setVisibility(GONE);
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
set.playSequentially(valueAnimator, tada);
set.start();
}
public static ObjectAnimator tada(View view, float shakeFactor) {
PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofKeyframe(View.SCALE_X,
Keyframe.ofFloat(0f, 1f),
Keyframe.ofFloat(.1f, .9f),
Keyframe.ofFloat(.2f, .9f),
Keyframe.ofFloat(.3f, 1.1f),
Keyframe.ofFloat(.4f, 1.1f),
Keyframe.ofFloat(.5f, 1.1f),
Keyframe.ofFloat(.6f, 1.1f),
Keyframe.ofFloat(.7f, 1.1f),
Keyframe.ofFloat(.8f, 1.1f),
Keyframe.ofFloat(.9f, 1.1f),
Keyframe.ofFloat(1f, 1f)
);
PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofKeyframe(View.SCALE_Y,
Keyframe.ofFloat(0f, 1f),
Keyframe.ofFloat(.1f, .9f),
Keyframe.ofFloat(.2f, .9f),
Keyframe.ofFloat(.3f, 1.1f),
Keyframe.ofFloat(.4f, 1.1f),
Keyframe.ofFloat(.5f, 1.1f),
Keyframe.ofFloat(.6f, 1.1f),
Keyframe.ofFloat(.7f, 1.1f),
Keyframe.ofFloat(.8f, 1.1f),
Keyframe.ofFloat(.9f, 1.1f),
Keyframe.ofFloat(1f, 1f)
);
PropertyValuesHolder pvhRotate = PropertyValuesHolder.ofKeyframe(View.ROTATION,
Keyframe.ofFloat(0f, 0f),
Keyframe.ofFloat(.1f, -3f * shakeFactor),
Keyframe.ofFloat(.2f, -3f * shakeFactor),
Keyframe.ofFloat(.3f, 3f * shakeFactor),
Keyframe.ofFloat(.4f, -3f * shakeFactor),
Keyframe.ofFloat(.5f, 3f * shakeFactor),
Keyframe.ofFloat(.6f, -3f * shakeFactor),
Keyframe.ofFloat(.7f, 3f * shakeFactor),
Keyframe.ofFloat(.8f, -3f * shakeFactor),
Keyframe.ofFloat(.9f, 3f * shakeFactor),
Keyframe.ofFloat(1f, 0)
);
return ObjectAnimator.ofPropertyValuesHolder(view, pvhScaleX, pvhScaleY, pvhRotate).
setDuration(1000);
}
}

View File

@@ -0,0 +1,325 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.BitmapImageViewTarget;
import com.luck.picture.lib.engine.ImageEngine;
import com.xscm.moduleutil.R;
/**
* @authorluck
* @date2019-11-13 17:02
* @describeGlide加载引擎
*/
public class GlideEngine implements ImageEngine {
/**
* 加载图片
*
* @param context
* @param url
* @param imageView
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
Glide.with(context)
.load(url)
.into(imageView);
}
@Override
public void loadImage(Context context, ImageView imageView, String url, int maxWidth, int maxHeight) {
Glide.with(context).load(url).into(imageView);
}
@Override
public void loadAlbumCover(Context context, String url, ImageView imageView) {
Glide.with(context)
.asBitmap()
.load(url)
.override(180, 180)
.centerCrop()
.sizeMultiplier(0.5f)
.apply(new RequestOptions().placeholder(R.mipmap.default_image))
.into(new BitmapImageViewTarget(imageView) {
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable circularBitmapDrawable =
RoundedBitmapDrawableFactory.
create(context.getResources(), resource);
circularBitmapDrawable.setCornerRadius(8);
imageView.setImageDrawable(circularBitmapDrawable);
}
});
}
@Override
public void loadGridImage(Context context, String url, ImageView imageView) {
Glide.with(context)
.load(url)
.override(200, 200)
.centerCrop()
.apply(new RequestOptions().placeholder(R.mipmap.default_image))
.into(imageView);
}
// /**
// * 加载网络图片适配长图方案
// * # 注意:此方法只有加载网络图片才会回调
// *
// * @param context
// * @param url
// * @param imageView
// * @param longImageView
// * @param callback 网络图片加载回调监听 {link after version 2.5.1 Please use the #OnImageCompleteCallback#}
// */
// @Override
// public void loadImage(@NonNull Context context, @NonNull String url,
// @NonNull ImageView imageView,
// SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) {
// Glide.with(context)
// .asBitmap()
// .load(url)
// .into(new ImageViewTarget<Bitmap>(imageView) {
// @Override
// public void onLoadStarted(@Nullable Drawable placeholder) {
// super.onLoadStarted(placeholder);
// if (callback != null) {
// callback.onShowLoading();
// }
// }
//
// @Override
// public void onLoadFailed(@Nullable Drawable errorDrawable) {
// super.onLoadFailed(errorDrawable);
// if (callback != null) {
// callback.onHideLoading();
// }
// }
//
// @Override
// protected void setResource(@Nullable Bitmap resource) {
// if (callback != null) {
// callback.onHideLoading();
// }
// if (resource != null) {
// boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
// resource.getHeight());
// longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
// imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
// if (eqLongImage) {
// // 加载长图
// longImageView.setQuickScaleEnabled(true);
// longImageView.setZoomEnabled(true);
// longImageView.setDoubleTapZoomDuration(100);
// longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
// longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
// longImageView.setImage(ImageSource.bitmap(resource),
// new ImageViewState(0, new PointF(0, 0), 0));
// } else {
// // 普通图片
// imageView.setImageBitmap(resource);
// }
// }
// }
// });
// }
// /**
// * 加载网络图片适配长图方案
// * # 注意:此方法只有加载网络图片才会回调
// *
// * @param context
// * @param url
// * @param imageView
// * @param longImageView
// * @ 已废弃
// */
// @Override
// public void loadImage(@NonNull Context context, @NonNull String url,
// @NonNull ImageView imageView,
// SubsamplingScaleImageView longImageView) {
// Glide.with(context)
// .asBitmap()
// .load(url)
// .into(new ImageViewTarget<Bitmap>(imageView) {
// @Override
// protected void setResource(@Nullable Bitmap resource) {
// if (resource != null) {
// boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
// resource.getHeight());
// longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
// imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
// if (eqLongImage) {
// // 加载长图
// longImageView.setQuickScaleEnabled(true);
// longImageView.setZoomEnabled(true);
// longImageView.setDoubleTapZoomDuration(100);
// longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
// longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
// longImageView.setImage(ImageSource.bitmap(resource),
// new ImageViewState(0, new PointF(0, 0), 0));
// } else {
// // 普通图片
// imageView.setImageBitmap(resource);
// }
// }
// }
// });
// }
// /**
// * 加载相册目录
// *
// * @param context 上下文
// * @param url 图片路径
// * @param imageView 承载图片ImageView
// */
// @Override
// public void loadFolderImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
// Glide.with(context)
// .asBitmap()
// .load(url)
// .override(180, 180)
// .centerCrop()
// .sizeMultiplier(0.5f)
// .apply(new RequestOptions().placeholder(com.luck.picture.lib.R.drawable.picture_image_placeholder))
// .into(new BitmapImageViewTarget(imageView) {
// @Override
// protected void setResource(Bitmap resource) {
// RoundedBitmapDrawable circularBitmapDrawable =
// RoundedBitmapDrawableFactory.
// create(context.getResources(), resource);
// circularBitmapDrawable.setCornerRadius(8);
// imageView.setImageDrawable(circularBitmapDrawable);
// }
// });
// }
// /**
// * 加载gif
// *
// * @param context 上下文
// * @param url 图片路径
// * @param imageView 承载图片ImageView
// */
// @Override
// public void loadAsGifImage(@NonNull Context context, @NonNull String url,
// @NonNull ImageView imageView) {
// Glide.with(context)
// .asGif()
// .load(url)
// .into(imageView);
// }
// /**
// * 加载图片列表图片
// *
// * @param context 上下文
// * @param url 图片路径
// * @param imageView 承载图片ImageView
// */
// @Override
// public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
// Glide.with(context)
// .load(url)
// .override(200, 200)
// .centerCrop()
// .apply(new RequestOptions().placeholder(com.luck.picture.lib.R.drawable.ps_ic_placeholder))
// .into(imageView);
// }
@Override
public void pauseRequests(Context context) {
}
@Override
public void resumeRequests(Context context) {
}
// /**
// * 加载网络图片适配长图方案
// * # 注意:此方法只有加载网络图片才会回调
// *
// * @param context
// * @param url
// * @param imageView
// * @param longImageView
// * @param callback 网络图片加载回调监听 {link after version 2.5.1 Please use the #OnImageCompleteCallback#}
// */
// @Override
// public void loadImage(@NonNull Context context, @NonNull String url,
// @NonNull ImageView imageView,
// SubsamplingScaleImageView longImageView, OnImageCompleteCallback callback) {
// Glide.with(context)
// .asBitmap()
// .load(url)
// .into(new ImageViewTarget<Bitmap>(imageView) {
// @Override
// public void onLoadStarted(@Nullable Drawable placeholder) {
// super.onLoadStarted(placeholder);
// if (callback != null) {
// callback.onShowLoading();
// }
// }
//
// @Override
// public void onLoadFailed(@Nullable Drawable errorDrawable) {
// super.onLoadFailed(errorDrawable);
// if (callback != null) {
// callback.onHideLoading();
// }
// }
//
// @Override
// protected void setResource(@Nullable Bitmap resource) {
// if (callback != null) {
// callback.onHideLoading();
// }
// if (resource != null) {
// boolean eqLongImage = MediaUtils.isLongImg(resource.getWidth(),
// resource.getHeight());
// longImageView.setVisibility(eqLongImage ? View.VISIBLE : View.GONE);
// imageView.setVisibility(eqLongImage ? View.GONE : View.VISIBLE);
// if (eqLongImage) {
// // 加载长图
// longImageView.setQuickScaleEnabled(true);
// longImageView.setZoomEnabled(true);
// longImageView.setPanEnabled(true);
// longImageView.setDoubleTapZoomDuration(100);
// longImageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP);
// longImageView.setDoubleTapZoomDpi(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
// longImageView.setImage(ImageSource.bitmap(resource),
// new ImageViewState(0, new PointF(0, 0), 0));
// } else {
// // 普通图片
// imageView.setImageBitmap(resource);
// }
// }
// }
// });
// }
private static GlideEngine instance;
public static GlideEngine createGlideEngine() {
if (null == instance) {
synchronized (GlideEngine.class) {
if (null == instance) {
instance = new GlideEngine();
}
}
}
return instance;
}
}

View File

@@ -0,0 +1,101 @@
package com.xscm.moduleutil.utils;
//import com.blankj.utilcode.util.LogUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.xscm.moduleutil.http.BaseModelTypeAdapterFactory;
import com.xscm.moduleutil.utils.logger.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class GsonUtils {
private static Gson GSON ;
// private static Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static final JsonParser PARSER = new JsonParser();
public static Gson getGSON() {
if (GSON == null) {
GSON = new GsonBuilder()
.serializeNulls() // 序列化 null 值
.registerTypeAdapterFactory(new BaseModelTypeAdapterFactory())
.create();
}
return GSON;
}
/**
* Object 转 json
*
* @param object object
* @return object
*/
public static String GsonString(Object object) {
return GSON.toJson(object);
}
public static <T> T GsonToBean(String gsonString, Class<T> cls) {
return GSON.fromJson(gsonString, cls);
}
/**
* 转成map的
*
* @param gsonString str
* @return map
*/
public static Map<String, Object> GsonToMaps(String gsonString) {
return GSON.fromJson(gsonString, new TypeToken<Map<String, Object>>() {
}.getType());
}
/**
* 将json 格式化输出
*
* @param str str
* @return str
*/
public static String GsonToString(String str) {
try {
return GSON.toJson(PARSER.parse(str));
} catch (JsonSyntaxException e) {
e.printStackTrace();
return str;
}
}
/**
* json字符串转成list
* 解决泛型问题
* 备注:
* List<T> list=gson.fromJson(gsonString, new TypeToken<List<T>>() {}.getType());
* 该方法会报泛型类型擦除问题
*
* @param gsonString
* @param cls
* @param <T>
* @return
*/
public static <T> List<T> GsonToList(String gsonString, Class<T> cls) {
List<T> list = new ArrayList<T>();
try {
if (GSON != null) {
JsonArray array = new JsonParser().parse(gsonString).getAsJsonArray();
for (final JsonElement elem : array) {
list.add(GSON.fromJson(elem, cls));
}
}
} catch (Exception e) {
Logger.e("非法json字符串", e);
}
return list;
}
}

View File

@@ -0,0 +1,50 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.xscm.moduleutil.R;
/**
* Copyright (c) 1
*
*/
public class ImageLoader {
public static void loadHead(Context context, ImageView view, String url) {
RequestOptions options = RequestOptions.circleCropTransform();
Glide.with(context).load(url).apply(options).error(com.xscm.moduleutil.R.mipmap.default_avatar).placeholder(R.mipmap.default_avatar).diskCacheStrategy(DiskCacheStrategy.ALL).into(view);
}
public static void loadHead(ImageView view, String url) {
RequestOptions options = RequestOptions.circleCropTransform();
Glide.with(view).load(url).apply(options).error(R.mipmap.default_avatar).placeholder(R.mipmap.default_avatar).diskCacheStrategy(DiskCacheStrategy.ALL).into(view);
}
public static void loadImage(ImageView view, String url) {
Glide.with(view).load(url).error(R.mipmap.default_image).placeholder(R.mipmap.default_image).diskCacheStrategy(DiskCacheStrategy.ALL).into(view);
}
public static void loadImage(Context context, ImageView view, String url) {
Glide.with(context).load(url).error(R.mipmap.default_image).placeholder(R.mipmap.default_image).diskCacheStrategy(DiskCacheStrategy.ALL).into(view);
}
public static void loadIcon(Context context, ImageView view, String url) {
if (TextUtils.isEmpty(url)) {
view.setVisibility(View.GONE);
} else {
view.setVisibility(View.VISIBLE);
}
Glide.with(context).load(url).diskCacheStrategy(DiskCacheStrategy.ALL).into(view);
}
}

View File

@@ -0,0 +1,571 @@
package com.xscm.moduleutil.utils;
import static android.view.View.GONE;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.Utils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.request.FutureTarget;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.bumptech.glide.signature.ObjectKey;
import com.opensource.svgaplayer.SVGADrawable;
import com.opensource.svgaplayer.SVGAImageView;
import com.opensource.svgaplayer.SVGAParser;
import com.opensource.svgaplayer.SVGAVideoEntity;
import com.xscm.moduleutil.R;
import com.xscm.moduleutil.utils.logger.Logger;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* <p> 图片加载工具类</p>
*
* @name ImageUtils
*/
public class ImageUtils {
public static final int ANIM = -1;
/**
* 默认加载
*/
public static void loadImageView(String path, ImageView mImageView) {
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
/**
* 默认加载
*/
public static void loadIcon(String path, ImageView mImageView) {
mImageView.setVisibility(TextUtils.isEmpty(path) ? GONE : View.VISIBLE);
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
/**
* 加载爵位动图
*/
public static void loadVipWebp(String path, ImageView mImageView) {
loadSample(path, mImageView, ConvertUtils.dp2px(200), ConvertUtils.dp2px(200));
}
/**
* 采样
*
* @param path
* @param mImageView
* @param width
* @param height
*/
public static void loadSample(String path, ImageView mImageView, int width, int height) {
RequestOptions options = new RequestOptions().override(width, height).diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(mImageView).load(path).apply(options).into(mImageView);
}
/**
* 默认加载
*/
public static void loadDecorationAvatar(String path, SVGAImageView mImageView) {
if (path.endsWith(".svga")) {
try {
SVGAParser.Companion.shareParser().decodeFromURL(new URL(path), new SVGAParser.ParseCompletion() {
@Override
public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) {
if (mImageView != null) {
SVGADrawable svgaDrawable = new SVGADrawable(svgaVideoEntity);
mImageView.setImageDrawable(svgaDrawable);
mImageView.startAnimation();
}
}
@Override
public void onError() {
Logger.e("loadDecorationAvatar error");
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
}
} else {
if (mImageView.isAnimating()) {
mImageView.stopAnimation();
}
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
}
private static Map<Integer, SVGAVideoEntity> svgaCache = new HashMap<>();
// TODO: 2025/8/22 播放svga
public static void loadDecorationAvatar2(int resourceId, SVGAImageView mImageView) {
// 从资源文件夹加载SVGA文件
if (resourceId != 0) {
// 检查缓存
SVGAVideoEntity cachedEntity = svgaCache.get(resourceId);
if (cachedEntity != null) {
// 使用缓存的实体
SVGADrawable svgaDrawable = new SVGADrawable(cachedEntity);
mImageView.setImageDrawable(svgaDrawable);
mImageView.startAnimation();
return;
}
try {
// 没有缓存,正常加载
SVGAParser parser = SVGAParser.Companion.shareParser();
InputStream inputStream = mImageView.getContext().getResources().openRawResource(resourceId);
parser.decodeFromAssets("heart_line_31.svga", new SVGAParser.ParseCompletion() {
@Override
public void onComplete(@NotNull SVGAVideoEntity svgaVideoEntity) {
if (mImageView != null) {
// 缓存实体
svgaCache.put(resourceId, svgaVideoEntity);
SVGADrawable svgaDrawable = new SVGADrawable(svgaVideoEntity);
mImageView.setImageDrawable(svgaDrawable);
mImageView.startAnimation();
}
}
@Override
public void onError() {
Logger.e("loadDecorationAvatar2 error, resourceId: " + resourceId);
}
});
} catch (Exception e) {
Logger.e("loadDecorationAvatar2 exception, resourceId: " + resourceId, e);
}
} else {
Logger.e("Resource ID is 0 or invalid");
}
}
public static void loadHeadCC(String path, ImageView mImageView) {
Glide.with(mImageView).load(path).error(R.mipmap.default_avatar).placeholder(R.mipmap.default_avatar).centerCrop().diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
public static void loadCompressImg(String path, ImageView mImageView, int width, int height) {
Glide.with(mImageView)
.load(path)
.centerCrop()
.override(width, height).diskCacheStrategy(DiskCacheStrategy.ALL)
.into(mImageView);
}
public static void loadCenterCrop(String path, ImageView mImageView) {
Glide.with(mImageView).load(path).centerCrop().diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
public static void loadRes(int path, ImageView mImageView) {
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
/**
* 加载图片(优先使用本地缓存,无缓存则下载)
*
* @param context 上下文
* @param url 图片 URL
* @param imageView 目标 ImageView
*/
public static void loadImageWithCache(Context context, String url, ImageView imageView) {
if (TextUtils.isEmpty(url)) return;
// 去掉动态参数,提取稳定 URL
String stableUrl = url.split("\\?")[0];
String signature = Md5Utils.getMD5String(stableUrl); // 使用 MD5 生成唯一签名
// Glide 加载配置
Glide.with(context)
.load(stableUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL) // 缓存所有版本
.signature(new ObjectKey(signature)) // 使用签名确保缓存一致
.placeholder(R.mipmap.room_bj) // 加载中占位图
.error(R.mipmap.room_bj) // 加载失败占位图
.centerCrop()
.into(imageView);
}
public static boolean isImageCached(Context context, String url) {
FutureTarget<File> future = Glide.with(context)
.downloadOnly()
.load(url)
.submit();
try {
File cacheFile = future.get();
return cacheFile != null && cacheFile.exists();
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static void loadImageBlurBg(String url, ImageView imageView) {
RequestOptions options = new RequestOptions().centerCrop().placeholder(R.mipmap.room_bg).error(R.mipmap.room_bg).diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(imageView).asBitmap().apply(options).load(url).into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
try {
Drawable foregroundDrawable = FastBlurUtil.getForegroundDrawable(resource);
imageView.setImageDrawable(foregroundDrawable);
} catch (Exception e) {
imageView.setImageResource(R.mipmap.room_bg);
}
}
});
}
public static void loadCoverBlurBg(Context context, String url, LinearLayout linearLayout) {
RequestOptions options = new RequestOptions().centerCrop().placeholder(R.mipmap.default_avatar).error(R.mipmap.default_avatar).diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(context).asBitmap().apply(options).load(url).into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
try {
setUpCoverBg(linearLayout, resource);
} catch (Exception e) {
linearLayout.setBackgroundResource(R.mipmap.index_bg_hot);
}
}
});
}
private static void setUpCoverBg(LinearLayout linearLayout, Bitmap resource) {
// Palette.from(resource).generate(new Palette.PaletteAsyncListener() {
// @Override
// public void onGenerated(Palette palette) {
// //记得判空
// if (palette == null) return;
// //palette取色不一定取得到某些特定的颜色这里通过取多种颜色来避免取不到颜色的情况
// if (palette.getDarkVibrantColor(Color.TRANSPARENT) != Color.TRANSPARENT) {
// createLinearGradientBitmap(linearLayout, resource, palette.getDarkVibrantColor(Color.TRANSPARENT), palette.getVibrantColor(Color.TRANSPARENT));
// } else if (palette.getDarkMutedColor(Color.TRANSPARENT) != Color.TRANSPARENT) {
// createLinearGradientBitmap(linearLayout, resource, palette.getDarkMutedColor(Color.TRANSPARENT), palette.getMutedColor(Color.TRANSPARENT));
// } else {
// createLinearGradientBitmap(linearLayout, resource, palette.getLightMutedColor(Color.TRANSPARENT), palette.getLightVibrantColor(Color.TRANSPARENT));
// }
// }
// });
}
//创建线性渐变背景色
private static void createLinearGradientBitmap(LinearLayout ivBg, Bitmap bgBitmap, int darkColor, int color) {
int bgColors[] = new int[2];
bgColors[0] = darkColor;
bgColors[1] = color;
if (bgBitmap == null) {
bgBitmap = Bitmap.createBitmap(ivBg.getWidth(), ivBg.getHeight(), Bitmap.Config.ARGB_4444);
}
Canvas mCanvas = new Canvas();
Paint mPaint = new Paint();
mCanvas.setBitmap(bgBitmap);
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
LinearGradient gradient = new LinearGradient(0, 0, 0, bgBitmap.getHeight(), bgColors[0], bgColors[1], Shader.TileMode.CLAMP);
mPaint.setShader(gradient);
RectF rectF = new RectF(0, 0, bgBitmap.getWidth(), bgBitmap.getHeight());
mCanvas.drawRoundRect(rectF, 16, 16, mPaint);
// mCanvas.drawRect(rectF, mPaint);
ivBg.setBackground(new BitmapDrawable(bgBitmap));
}
public static void loadRoomBg(String url, ImageView imageView) {
RequestOptions options = new RequestOptions().centerCrop().placeholder(R.mipmap.room_bg).error(R.mipmap.room_bg).diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(imageView).load(url).apply(options).into(imageView);
}
/**
* 设置加载中以及加载失败图片
*/
public static void loadImageWithLoading(String path, ImageView mImageView, int lodingImage, int errorRes) {
Glide.with(mImageView).load(path).placeholder(lodingImage).
error(errorRes).diskCacheStrategy(DiskCacheStrategy.ALL).into(mImageView);
}
/**
* 加载为bitmap
*
* @param path 图片地址
* @param listener 回调
*/
public static void loadBitmap(String path, final onLoadBitmap listener) {
Glide.with(Utils.getApp()).asBitmap().load(path).into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
listener.onReady(resource);
}
});
}
public static void loadGift(ImageView view, int res) {
if (res == ANIM) {
try {
AnimationDrawable background = (AnimationDrawable) view.getBackground();
if (background != null) {
background.start();
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
Glide.with(view.getContext()).asGif().load(res).into(view);
}
}
public static void loadIconByHeight(String path, ImageView mImageView) {
mImageView.setVisibility(TextUtils.isEmpty(path) ? GONE : View.VISIBLE);
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
mImageView.setImageDrawable(resource);
ViewGroup.LayoutParams layoutParams = mImageView.getLayoutParams();
layoutParams.width = (int) (layoutParams.height * 1f / resource.getIntrinsicHeight() * resource.getIntrinsicWidth());
mImageView.setLayoutParams(layoutParams);
}
});
}
public static void loadIconByHeight1(String path, ImageView mImageView,int height) {
mImageView.setVisibility(TextUtils.isEmpty(path) ? GONE : View.VISIBLE);
Glide.with(mImageView).load(path).diskCacheStrategy(DiskCacheStrategy.ALL).into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
mImageView.setImageDrawable(resource);
ViewGroup.LayoutParams layoutParams = mImageView.getLayoutParams();
layoutParams.width = (int) (layoutParams.height * 1f / resource.getIntrinsicHeight() * resource.getIntrinsicWidth());
layoutParams.height = height;
mImageView.setLayoutParams(layoutParams);
}
});
}
/**
* 加载网络图片并高斯模糊,失败时加载默认图片并同样模糊
*/
public static void loadBlurredImageWithDefault(String url, ImageView imageView, int defaultResId, int radius) {
if (imageView == null) return;
Glide.with(imageView.getContext())
.asBitmap()
.load(url)
.error(defaultResId) // 加载失败时显示默认图片
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
// 对网络图或默认图都进行模糊处理
Bitmap blurred = com.blankj.utilcode.util.ImageUtils.stackBlur(resource, radius);
imageView.setImageBitmap(blurred);
}
@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
// 如果 errorDrawable 不为空,也可以直接用它生成 Bitmap
if (errorDrawable instanceof BitmapDrawable) {
Bitmap bitmap = ((BitmapDrawable) errorDrawable).getBitmap();
Bitmap blurred = com.blankj.utilcode.util.ImageUtils.stackBlur(bitmap, radius);
imageView.setImageBitmap(blurred);
} else {
// 如果不是 BitmapDrawable尝试从资源中加载 Bitmap
Bitmap defaultBitmap = BitmapFactory.decodeResource(imageView.getResources(), defaultResId);
if (defaultBitmap != null) {
Bitmap blurred = com.blankj.utilcode.util.ImageUtils.stackBlur(defaultBitmap, radius);
imageView.setImageBitmap(blurred);
}
}
}
});
}
/**
* 加载bitmap回调
*/
public interface onLoadBitmap {
void onReady(Bitmap resource);
}
public static void loadOneTimeGif(Context context, Object model, final ImageView imageView) {
Glide.with(context).asGif().load(model).listener(new RequestListener<GifDrawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
try {
Field gifStateField = GifDrawable.class.getDeclaredField("state");
gifStateField.setAccessible(true);
Class gifStateClass = Class.forName("com.bumptech.glide.load.resource.gif.GifDrawable$GifState");
Field gifFrameLoaderField = gifStateClass.getDeclaredField("frameLoader");
gifFrameLoaderField.setAccessible(true);
Class gifFrameLoaderClass = Class.forName("com.bumptech.glide.load.resource.gif.GifFrameLoader");
Field gifDecoderField = gifFrameLoaderClass.getDeclaredField("gifDecoder");
gifDecoderField.setAccessible(true);
Class gifDecoderClass = Class.forName("com.bumptech.glide.gifdecoder.GifDecoder");
Object gifDecoder = gifDecoderField.get(gifFrameLoaderField.get(gifStateField.get(resource)));
Method getDelayMethod = gifDecoderClass.getDeclaredMethod("getDelay", int.class);
getDelayMethod.setAccessible(true);
//设置只播放一次
resource.setLoopCount(1);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return false;
}
}).into(imageView);
}
// public static String getImagePath() {
// String path = Constants.IMAGE_PATH;
// File file = new File(path);
// if (file.mkdirs()) {
// return path;
// } else {
// return path;
// }
// }
public static String getUrl(String url) {
// url = EncodeUtils.htmlDecode(url).toString();
// if (!TextUtils.isEmpty(url) && !url.contains("http"))
// url = BuildConfig.BASE_URL + url;
return url;
}
public static void preload(String url) {
// Glide.with(BaseApplication.getInstance()).download(url).preload();
}
public static void preloadImgConstants() {
// try {
// ImgConstants constants = new ImgConstants();
// Field[] fields = ImgConstants.class.getDeclaredFields();
// for (Field field : fields) {
// preload(field.get(constants).toString());
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
}
/**
* 将 assets 中的文件复制到指定路径
*
* @param assetName assets 中的文件名,例如:"my_file.txt"
* @param savePath 要保存的目录路径,例如:"/data/data/your.package/files/"
* @param saveName 保存后的文件名
*/
public static void copyAssetToFile(String assetName, String savePath, String saveName) {
InputStream myInput = null;
FileOutputStream myOutput = null;
try {
// 打开 assets 中的文件输入流
myInput = Utils.getApp().getAssets().open(assetName);
// 创建目标目录(如果不存在)
File dir = new File(savePath);
if (!dir.exists()) {
dir.mkdirs();
}
// 创建目标文件
File outFile = new File(savePath + saveName);
if (outFile.exists()) {
outFile.delete(); // 如果已存在,先删除
}
// 创建输出流
myOutput = new FileOutputStream(outFile);
// 缓冲区读写
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// 刷新输出流
myOutput.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流
try {
if (myInput != null) {
myInput.close();
}
if (myOutput != null) {
myOutput.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,58 @@
package com.xscm.moduleutil.utils;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class KeyWordUtil {
/**
* 关键字高亮变色
*
* @param color 变化的色值
* @param text 文字
* @param keyword 文字中的关键字
* @return 结果SpannableString
*/
public static SpannableString matcherSearchTitle(int color, String text, String keyword) {
SpannableString s = new SpannableString(text);
keyword=escapeExprSpecialWord(keyword);
text=escapeExprSpecialWord(text);
if (text.contains(keyword)&&!TextUtils.isEmpty(keyword)){
try {
Pattern p = Pattern.compile(keyword);
Matcher m = p.matcher(s);
while (m.find()) {
int start = m.start();
int end = m.end();
s.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}catch (Exception e){
}
}
return s;
}
/**
* 转义正则特殊字符 $()*+.[]?\^{},|
*
* @param keyword
* @return keyword
*/
public static String escapeExprSpecialWord(String keyword) {
if (!TextUtils.isEmpty(keyword)) {
String[] fbsArr = { "\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|" };
for (String key : fbsArr) {
if (keyword.contains(key)) {
keyword = keyword.replace(key, "\\" + key);
}
}
}
return keyword;
}
}

View File

@@ -0,0 +1,152 @@
package com.xscm.moduleutil.utils;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import androidx.core.os.ConfigurationCompat;
import androidx.core.os.LocaleListCompat;
import com.xscm.moduleutil.base.CommonAppContext;
import com.xscm.moduleutil.widget.Constants;
import java.util.Locale;
/**
* Created by cxf on 2019/6/5.
*/
public class LanguageUtil {
private static LanguageUtil instance;
private String mLanguage;
public LanguageUtil() {
mLanguage = SpUtil.getInstance().getStringValue(SpUtil.LANGUAGE);
// if (TextUtils.isEmpty(mLanguage)) {
getSystemLanguage();
// }
}
public static LanguageUtil getInstance() {
if (instance == null) {
synchronized (LanguageUtil.class) {
if (instance == null) {
instance = new LanguageUtil();
}
}
}
return instance;
}
/**
* 判断系统语言是否是中文
*/
private void getSystemLanguage() {
String lang = Constants.LANG_ZH;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
LocaleListCompat listCompat = ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration());
if (listCompat.size() > 0) {
Locale locale = listCompat.get(0);
if (locale != null) {
String localeName = locale.toString();
if (localeName.startsWith("en")) {
lang = Constants.LANG_EN;
} else {
lang = Constants.LANG_ZH;
}
}
}
} else {
Locale locale = Locale.getDefault();
if (locale != null) {
String localeName = locale.toString();
if (localeName.startsWith("en")) {
lang = Constants.LANG_EN;
} else {
lang = Constants.LANG_ZH;
}
}
}
setLanguage(lang);
}
/**
* 设置语言
*/
private static void setConfiguration() {
Locale targetLocale = getLanguageLocale();
Resources resources = CommonAppContext.getInstance().getResources();
Configuration configuration = resources.getConfiguration();
configuration.setLocale(targetLocale);
DisplayMetrics dm = resources.getDisplayMetrics();
resources.updateConfiguration(configuration, dm);//语言更换生效的代码!
}
public static Locale getLanguageLocale() {
String lang = LanguageUtil.getInstance().getLanguage();
if (!TextUtils.isEmpty(lang)) {
if (Constants.LANG_ZH.equals(lang)) {
return Locale.SIMPLIFIED_CHINESE;
} else if (Constants.LANG_EN.equals(lang)) {
return Locale.US;
}
}
return Locale.SIMPLIFIED_CHINESE;
}
public void updateLanguage(String language) {
setLanguage(language);
setConfiguration();
}
public static Context attachBaseContext(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return createConfigurationResources(context);
} else {
setConfiguration();
return context;
}
}
@TargetApi(Build.VERSION_CODES.N)
private static Context createConfigurationResources(Context context) {
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
Locale locale = getLanguageLocale();
configuration.setLocale(locale);
return context.createConfigurationContext(configuration);
}
public String getLanguage() {
if (TextUtils.isEmpty(mLanguage)) {
mLanguage = SpUtil.getInstance().getStringValue(SpUtil.LANGUAGE);
if (TextUtils.isEmpty(mLanguage)) {
getSystemLanguage();
}
}
return mLanguage;
}
public void setLanguage(String language) {
mLanguage = language;
SpUtil.getInstance().setStringValue(SpUtil.LANGUAGE, language);
}
public static boolean isZh() {
return Constants.LANG_ZH.equals(LanguageUtil.getInstance().getLanguage());
}
public static boolean isEn() {
return Constants.LANG_EN.equals(LanguageUtil.getInstance().getLanguage());
}
}

View File

@@ -0,0 +1,112 @@
package com.xscm.moduleutil.utils;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class LocationUtils {
private static final String TAG = "LocationUtils";
private FusedLocationProviderClient fusedLocationClient;
public interface LocationCallbackInterface {
void onLocationReceived(double latitude, double longitude, String city);
void onFailed(String errorMessage);
}
public LocationUtils(Context context) {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
}
private void getLastLocation() {
}
public void getLastLocation(Context context,LocationCallbackInterface callback) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// 请求定位权限
ActivityCompat.requestPermissions(
(Activity) context,
new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
},
1001 // 自定义常量,比如 1001
);
return;
}
fusedLocationClient.getLastLocation()
.addOnSuccessListener(location -> {
if (location != null) {
// 获取城市名称
String city = getCityName(context, location.getLatitude(), location.getLongitude());
callback.onLocationReceived(location.getLatitude(), location.getLongitude(), city);
} else {
callback.onFailed("无法获取位置");
}
})
.addOnFailureListener(e -> callback.onFailed("定位失败:" + e.getMessage()));
}
public void requestLocationUpdates(Context context,LocationCallbackInterface callback) {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(10000); // 每10秒更新一次
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
callback.onFailed("定位权限未授予");
return;
}
fusedLocationClient.requestLocationUpdates(locationRequest, new LocationCallback() {
@Override
public void onLocationResult(@NonNull LocationResult locationResult) {
if (locationResult == null) {
callback.onFailed("无位置更新");
return;
}
for (android.location.Location location : locationResult.getLocations()) {
String city = getCityName(context, location.getLatitude(), location.getLongitude());
callback.onLocationReceived(location.getLatitude(), location.getLongitude(), city);
}
}
}, Looper.getMainLooper());
}
private String getCityName(Context context, double latitude, double longitude) {
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
if (addresses != null && !addresses.isEmpty()) {
Address address = addresses.get(0);
return address.getLocality(); // 城市名
}
} catch (IOException e) {
Log.e(TAG, "地理编码失败", e);
}
return "未知城市";
}
}

View File

@@ -0,0 +1,196 @@
package com.xscm.moduleutil.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Md5Utils {
private final static String[] strDigits = {"0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
protected static char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
protected static MessageDigest messagedigest = null;
/**
* MessageDigest初始化
*
* @author 高焕杰
*/
static {
try {
messagedigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
System.err.println("MD5FileUtil messagedigest初始化失败");
e.printStackTrace();
}
}
public Md5Utils() {
}
private static String byteToArrayString(byte bByte) {
int iRet = bByte;
if (iRet < 0) {
iRet += 256;
}
int iD1 = iRet / 16;
int iD2 = iRet % 16;
return strDigits[iD1] + strDigits[iD2];
}
private static String byteToString(byte[] bByte) {
StringBuffer sBuffer = new StringBuffer();
for (int i = 0; i < bByte.length; i++) {
sBuffer.append(byteToArrayString(bByte[i]));
}
return sBuffer.toString();
}
//MD5加密
public static String get(String strObj) {
String resultString = null;
try {
resultString = strObj;
MessageDigest md = MessageDigest.getInstance("MD5");
resultString = byteToString(md.digest(strObj.getBytes()));
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
return resultString;
}
public static String getFileMD5(File file) {
if (!file.isFile()) {
return null;
}
MessageDigest digest = null;
FileInputStream in = null;
byte[] buffer = new byte[1024];
int len;
try {
digest = MessageDigest.getInstance("MD5");
in = new FileInputStream(file);
while ((len = in.read(buffer, 0, 1024)) != -1) {
digest.update(buffer, 0, len);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return byteToString(digest.digest());
}
public static String getStringMD5(String input) {
try {
// 拿到一个MD5转换器如果想要SHA1参数换成”SHA1”
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
// 输入的字符串转换成字节数组
byte[] inputByteArray = input.getBytes();
// inputByteArray是输入字符串转换得到的字节数组
messageDigest.update(inputByteArray);
// 转换并返回结果也是字节数组包含16个元素
byte[] resultByteArray = messageDigest.digest();
// 字符数组转换成字符串返回
return byteArrayToHex(resultByteArray);
} catch (NoSuchAlgorithmException e) {
return "";
}
}
public static String byteArrayToHex(byte[] byteArray) {
// 首先初始化一个字符数组用来存放每个16进制字符
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] resultCharArray = new char[byteArray.length * 2];
// 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
int index = 0;
for (byte b : byteArray) {
resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
resultCharArray[index++] = hexDigits[b & 0xf];
}
// 字符数组组合成字符串返回
return new String(resultCharArray);
}
/**
* 对文件进行MD5加密
*
* @author 高焕杰
*/
public static String getFileMD5String(File file) throws IOException {
FileInputStream in = new FileInputStream(file);
FileChannel ch = in.getChannel();
MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
messagedigest.update(byteBuffer);
return bufferToHex(messagedigest.digest());
}
/**
* 对字符串进行MD5加密
*
* @author 高焕杰
*/
public static String getMD5String(String s) {
return getMD5String(s.getBytes());
}
/**
* 对byte类型的数组进行MD5加密
*
* @author 高焕杰
*/
public static String getMD5String(byte[] bytes) {
messagedigest.update(bytes);
return bufferToHex(messagedigest.digest());
}
private static String bufferToHex(byte[] bytes) {
return bufferToHex(bytes, 0, bytes.length);
}
private static String bufferToHex(byte[] bytes, int m, int n) {
StringBuffer stringbuffer = new StringBuffer(2 * n);
int k = m + n;
for (int l = m; l < k; l++) {
char c0 = hexDigits[(bytes[l] & 0xf0) >> 4];
char c1 = hexDigits[bytes[l] & 0xf];
stringbuffer.append(c0);
stringbuffer.append(c1);
}
return stringbuffer.toString();
}
private static char sHexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
public static String getMD5(String source) {
try {
byte[] bytes = source.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest md = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
md.update(bytes);
// 获得密文
byte[] mdBytes = md.digest();
// 把密文转换成十六进制的字符串形式
int length = mdBytes.length;
char[] chars = new char[length * 2];
int k = 0;
for (int i = 0; i < length; i++) {
byte byte0 = mdBytes[i];
chars[k++] = sHexDigits[byte0 >>> 4 & 0xf];
chars[k++] = sHexDigits[byte0 & 0xf];
}
return new String(chars);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View File

@@ -0,0 +1,77 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.ImageView;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.xscm.moduleutil.R;
import com.xscm.moduleutil.utils.logger.Logger;
import com.xscm.moduleutil.widget.AvatarFrameView;
/**
* 描述 设置中的用户头像
*/
public class MeHeadView extends ConstraintLayout {
private ImageView mRiv;
private AvatarFrameView mIvFrame;
private ImageView mIvSex;
private ImageView mIvOnline;
public MeHeadView(Context context) {
this(context, null, 0);
}
public MeHeadView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MeHeadView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs, defStyleAttr);
}
private void initView(Context context, AttributeSet attrs, int defStyleAttr) {
LayoutInflater.from(context).inflate(R.layout.me_view_decoration_head, this, true);
mRiv = findViewById(R.id.riv);
mIvFrame = findViewById(R.id.iv_frame);
mIvSex = findViewById(R.id.iv_sex);
mIvOnline = findViewById(R.id.iv_online);
}
public void setData(String headPicture, String framePicture, String sex) {
Logger.e(headPicture, framePicture, sex);
if (!TextUtils.isEmpty(headPicture)) {
ImageUtils.loadHeadCC(headPicture, mRiv);
}
if (TextUtils.isEmpty(framePicture)) {
mIvFrame.setVisibility(GONE);
} else {
mIvFrame.setVisibility(VISIBLE);
mIvFrame.setSource(framePicture, 1);
}
if (!TextUtils.isEmpty(sex)) {
mIvSex.setVisibility(VISIBLE);
if (sex.equals("1")){
mIvSex.setBackgroundResource(R.mipmap.nan);
}else {
mIvSex.setBackgroundResource(R.mipmap.nv);
}
} else {
mIvSex.setVisibility(GONE);
}
// ImageUtils.loadImageView(framePicture, mIvFrame);
}
public void setOnline(boolean isOnline) {
mIvOnline.setVisibility(VISIBLE);
mIvOnline.setImageResource(isOnline ? R.mipmap.me_online_icon : R.mipmap.me_icon_unchecked);
}
}

View File

@@ -0,0 +1,113 @@
package com.xscm.moduleutil.utils;
import android.media.MediaPlayer;
import android.util.Log;
public class MediaPlayerUtiles {
private MediaPlayer mediaPlayer;
private static MediaPlayerUtiles instance = new MediaPlayerUtiles();
public static MediaPlayerUtiles getInstance() {
return instance;
}
private MediaPlayerUtiles() {
if (null == mediaPlayer) {
mediaPlayer = new MediaPlayer();
}
}
private OnMediaPlayerListener mOnMediaPlayerListener;
/**
* 播放音频
*/
public void playAudio(String url, OnMediaPlayerListener onMediaPlayerListener) {
playAudio(url, -1, onMediaPlayerListener);
}
public boolean isPlaying() {
return mediaPlayer != null && mediaPlayer.isPlaying();
}
/**
* 停止播放音频
*/
public void stopAudio() {
try {
if (null != mediaPlayer) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
mediaPlayer.reset();
mediaPlayer.stop();
}
}
if (mOnMediaPlayerListener != null) {
mOnMediaPlayerListener.onCompletion(position);
}
this.mOnMediaPlayerListener = null;
} catch (Exception e) {
Log.e("stopAudio", e.getMessage());
}
}
public long getCurrentPosition() {
if (mediaPlayer != null) {
return mediaPlayer.getCurrentPosition();
}
return 0;
}
public void playAudio(String url, int position, OnMediaPlayerListener onMediaPlayerListener) {
this.position = position;
try {
stopAudio();//如果正在播放就停止
if (this.mOnMediaPlayerListener != null) {
this.mOnMediaPlayerListener.onCompletion(position);
}
this.mOnMediaPlayerListener = onMediaPlayerListener;
mediaPlayer.reset();
mediaPlayer.setDataSource(url);
mediaPlayer.setLooping(false);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
if (mOnMediaPlayerListener != null) {
mOnMediaPlayerListener.onStartPlay(position);
}
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (mOnMediaPlayerListener != null) {
mOnMediaPlayerListener.onCompletion(position);
}
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
});
} catch (Exception e) {
e.printStackTrace();
Log.e("播放音频失败", "");
}
}
public interface OnMediaPlayerListener {
void onStartPlay(int position);
void onCompletion(int position);
}
private int position = -1;
}

View File

@@ -0,0 +1,87 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import com.blankj.utilcode.util.LogUtils;
import com.bumptech.glide.Glide;
public class MemoryOptimizationUtils {
private static final String TAG = "MemoryOptimization";
/**
* 检查内存状态
*/
public static boolean isMemoryLow() {
Runtime runtime = Runtime.getRuntime();
long usedMemory = runtime.totalMemory() - runtime.freeMemory();
long maxMemory = runtime.maxMemory();
double memoryUsage = (double) usedMemory / maxMemory;
LogUtils.d(TAG, "Memory usage: " + (memoryUsage * 100) + "%");
// 内存使用超过85%认为是低内存
return memoryUsage > 0.85;
}
/**
* 强制进行垃圾回收
*/
public static void forceGC() {
try {
LogUtils.d(TAG, "Forcing garbage collection");
Runtime.getRuntime().gc();
Thread.sleep(100); // 给GC一些时间
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* 清理图片缓存
*/
public static void clearImageCache(Context context) {
try {
// 清理Glide缓存
Glide.get(context).clearMemory();
// 在后台线程清理磁盘缓存
new Thread(() -> {
try {
Glide.get(context).clearDiskCache();
} catch (Exception e) {
LogUtils.e(TAG, "Error clearing Glide disk cache: " + e.getMessage());
}
}).start();
} catch (Exception e) {
LogUtils.e(TAG, "Error clearing image cache: " + e.getMessage());
}
}
/**
* 获取当前内存使用情况
*/
public static String getMemoryInfo() {
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
long usedMemory = totalMemory - freeMemory;
return String.format("Max: %d MB, Total: %d MB, Used: %d MB, Free: %d MB",
maxMemory / (1024 * 1024),
totalMemory / (1024 * 1024),
usedMemory / (1024 * 1024),
freeMemory / (1024 * 1024));
}
/**
* 清理SVGA缓存
*/
public static void clearSVGACache() {
try {
// 如果SVGA库提供了清理缓存的方法调用它
// SVGAParser.clearCache(); // 假设有这样的方法
} catch (Exception e) {
LogUtils.e(TAG, "Error clearing SVGA cache: " + e.getMessage());
}
}
}

View File

@@ -0,0 +1,91 @@
package com.xscm.moduleutil.utils
/**
*项目名称 isolated-island
*包名com.qpyy.libcommon.widget
*创建人 黄强
*创建时间 2021/4/1 14:36
*描述 describe
*/
public class MyPictureParameterStyle {
companion object {
// fun selectPicture(): PictureSelectorStyle {
// val uiStyle = PictureSelectorStyle()
// // 开启新选择风格
// uiStyle.isNewSelectStyle = true
// // 是否改变状态栏字体颜色(黑白切换)
// uiStyle.isChangeStatusBarFontColor = true
// // 是否开启右下角已完成(0/9)风格
// uiStyle.isOpenCompletedNumStyle = false
// // 是否开启类似QQ相册带数字选择风格
// uiStyle.isOpenCheckNumStyle = true
// // 状态栏背景色
// uiStyle.pictureStatusBarColor = Color.parseColor("#FFFFFF")
// // 相册列表标题栏背景色
// uiStyle.pictureTitleBarBackgroundColor = Color.parseColor("#FFFFFF")
// // 相册父容器背景色
// uiStyle.pictureContainerBackgroundColor = Color.parseColor("#FFFFFF")
// // 相册列表标题栏右侧上拉箭头
// uiStyle.pictureTitleUpResId = R.mipmap.common_picture_icon_wechat_up
// // 相册列表标题栏右侧下拉箭头
// uiStyle.pictureTitleDownResId = R.mipmap.common_picture_icon_wechat_down
// // 相册文件夹列表选中圆点
// uiStyle.pictureFolderCheckedDotStyle = R.drawable.common_picture_wechat_num_oval_select
// // 相册返回箭头
// uiStyle.pictureLeftBackIcon = R.drawable.picture_icon_back_arrow
// // 标题栏字体颜色
// uiStyle.pictureTitleTextColor = Color.parseColor("#FF000000")
// // 相册右侧按钮字体默认颜色
// uiStyle.pictureRightDefaultTextColor = Color.parseColor("#FFFFFF")
// // 相册右侧按可点击字体颜色,只针对isWeChatStyle 为true时有效果
// uiStyle.pictureRightSelectedTextColor = Color.parseColor("#FFFFFF")
// //相册标题字体大小
// uiStyle.pictureTitleTextSize = 18
// // 相册右侧按钮背景样式,只针对isWeChatStyle 为true时有效果
// uiStyle.pictureUnCompleteBackgroundStyle = R.drawable.common_picture_send_button_default_bg
// // 相册右侧按钮可点击背景样式,只针对isWeChatStyle 为true时有效果
// uiStyle.pictureCompleteBackgroundStyle = R.drawable.common_picture_send_button_bg
// // 选择相册目录背景样式
// uiStyle.pictureAlbumStyle = com.luck.picture.lib.R.drawable.picture_item_select_bg
// // 相册列表勾选图片样式
// uiStyle.pictureCheckedStyle = R.drawable.common_picture_wechat_num_selector
// // 相册标题背景样式 ,只针对isWeChatStyle 为true时有效果
// uiStyle.pictureWeChatTitleBackgroundStyle = R.drawable.common_picture_album_bg
// // 微信样式 预览右下角样式 ,只针对isWeChatStyle 为true时有效果
// uiStyle.pictureWeChatChooseStyle = com.luck.picture.lib.R.drawable.picture_wechat_select_cb
// // 相册返回箭头 ,只针对isWeChatStyle 为true时有效果
// uiStyle.pictureWeChatLeftBackStyle = com.luck.picture.lib.R.drawable.picture_icon_back_arrow
// // 相册列表底部背景色
// uiStyle.pictureBottomBgColor = Color.parseColor("#FFFFFF")
// // 已选数量圆点背景样式
// uiStyle.pictureCheckNumBgStyle = R.drawable.common_picture_wechat_num_oval_select
// // 相册列表底下预览文字色值(预览按钮可点击时的色值)
// uiStyle.picturePreviewTextColor = Color.parseColor("#9b9b9b")
// // 相册列表底下不可预览文字色值(预览按钮不可点击时的色值)
// uiStyle.pictureUnPreviewTextColor = Color.parseColor("#9b9b9b")
// // 相册列表已完成色值(已完成 可点击色值)
// uiStyle.pictureCompleteTextColor = Color.parseColor("#FFFFFF")
// // 相册列表未完成色值(请选择 不可点击色值)
// uiStyle.pictureUnCompleteTextColor = Color.parseColor("#53575e")
// //相册列表已完成按钮文本
// uiStyle.pictureCompleteText = "完成"
// //相册列表未完成按钮文本
// uiStyle.pictureUnCompleteText = "完成"
// // 预览界面底部背景色
// uiStyle.picturePreviewBottomBgColor = Color.parseColor("#FFFFFF")
// // 外部预览界面删除按钮样式
// uiStyle.pictureExternalPreviewDeleteStyle = com.luck.picture.lib.R.drawable.picture_icon_delete
// // 原图按钮勾选样式 需设置.isOriginalImageControl(true); 才有效
// uiStyle.pictureOriginalControlStyle =com.luck.picture.lib.R.drawable.picture_original_wechat_checkbox
// // 原图文字颜色 需设置.isOriginalImageControl(true); 才有效
// uiStyle.pictureOriginalFontColor = Color.parseColor("#FF000000")
// // 外部预览界面是否显示删除按钮
// // 外部预览界面是否显示删除按钮
// uiStyle.pictureExternalPreviewGonePreviewDelete = true
// // 设置NavBar Color SDK Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP有效
// uiStyle.pictureNavBarColor = Color.parseColor("#FFFFFF")
// return uiStyle
// }
}
}

View File

@@ -0,0 +1,17 @@
package com.xscm.moduleutil.utils;
public class NumberFormatUtils {
/**
* 格式化奖励数字,如果超过一万则显示为 W 形式,并去除小数点后两位
*
* @param number 输入的原始数字
* @return 格式化后的字符串
*/
public static String formatRewardNumber(double number) {
if (number >= 10000) {
return (int) (number / 10000) + "W";
} else {
return String.valueOf((int) number);
}
}
}

View File

@@ -0,0 +1,59 @@
package com.xscm.moduleutil.utils;
/**
* 项目名称 qipao-android
* 包名com.qpyy.room.fragment
* 创建人 黄强
* 创建时间 2020/8/12 16:24
* 描述 describe
*/
import android.util.Log;
/**
* 防止按钮多次重复点击
*/
public class OnClickUtils {
private static long lastClickTime = 0;
private static long DIFF = 1000;//间隔1秒
private static int lastButtonId = -1;
/**
* 判断两次点击的间隔如果小于1000则认为是多次无效点击
*
* @return
*/
public static boolean isFastDoubleClick() {
return isFastDoubleClick(-1, DIFF);
}
/**
* 判断两次点击的间隔如果小于1000则认为是多次无效点击
*
* @return
*/
public static boolean isFastDoubleClick(int buttonId) {
return isFastDoubleClick(buttonId, DIFF);
}
/**
* 判断两次点击的间隔如果小于diff则认为是多次无效点击
*
* @param diff
* @return
*/
public static boolean isFastDoubleClick(int buttonId, long diff) {
long time = System.currentTimeMillis();
long timeD = time - lastClickTime;
if (lastButtonId == buttonId && lastClickTime > 0 && timeD < diff) {
Log.d("isFastDoubleClick", "短时间内按钮多次触发: ");
return true;
}
lastClickTime = time;
lastButtonId = buttonId;
return false;
}
}

View File

@@ -0,0 +1,12 @@
package com.xscm.moduleutil.utils;
import java.util.HashMap;
public abstract class PermissionCallback {
public abstract void onAllGranted();
public void onResult(HashMap<String, Boolean> resultMap) {
}
}

View File

@@ -0,0 +1,36 @@
package com.xscm.moduleutil.utils;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import java.util.List;
/**
* 申请权限
*/
public class PermissionUtil {
public static void request(FragmentActivity activity, PermissionCallback callback, String... permission) {
ProcessFragment processFragment = null;
FragmentManager fragmentManager = activity.getSupportFragmentManager();
List<Fragment> list = fragmentManager.getFragments();
if (list != null && list.size() > 0) {
for (Fragment fragment : list) {
if (fragment != null && fragment instanceof ProcessFragment) {
processFragment = (ProcessFragment) fragment;
break;
}
}
}
if (processFragment == null) {
processFragment = new ProcessFragment();
FragmentTransaction tx = fragmentManager.beginTransaction();
tx.add(processFragment, "ProcessFragment").commitNow();
}
processFragment.requestPermissions(callback, permission);
}
}

View File

@@ -0,0 +1,237 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.content.SharedPreferences;
import com.blankj.utilcode.util.SPUtils;
/**
* sp工具类
*
* @author
*/
public class PreferencesUtils {
public static String PREFERENCE_NAME = "YuTang";
private PreferencesUtils() {
throw new AssertionError();
}
/**
* put string preferences
*
* @param context context
* @param key The name of the preference to modify
* @param value The new values for the preference
* @return True if the new values were successfully written to persistent storage.
*/
public static boolean putString(Context context, String key, String value) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(key, value);
return editor.commit();
}
/**
* get string preferences
*
* @param context context
* @param key The name of the preference to retrieve
* @return The preference values if it exists, or null. Throws ClassCastException if there is a preference with this
* name that is not a string
* @see #getString(Context, String, String)
*/
public static String getString(Context context, String key) {
return getString(context, key, null);
}
/**
* get string preferences
*
* @param context context
* @param key The name of the preference to retrieve
* @param defaultValue Value to return if this preference does not exist
* @return The preference values if it exists, or defValue. Throws ClassCastException if there is a preference with
* this name that is not a string
*/
public static String getString(Context context, String key, String defaultValue) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
return settings.getString(key, defaultValue);
}
/**
* put int preferences
*
* @param context context
* @param key The name of the preference to modify
* @param value The new values for the preference
* @return True if the new values were successfully written to persistent storage.
*/
public static boolean putInt(Context context, String key, int value) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putInt(key, value);
return editor.commit();
}
/**
* get int preferences
*
* @param context context
* @param key The name of the preference to retrieve
* @return The preference values if it exists, or -1. Throws ClassCastException if there is a preference with this
* name that is not a int
* @see #getInt(Context, String, int)
*/
public static int getInt(Context context, String key) {
return getInt(context, key, -1);
}
/**
* get int preferences
*
* @param context context
* @param key The name of the preference to retrieve
* @param defaultValue Value to return if this preference does not exist
* @return The preference values if it exists, or defValue. Throws ClassCastException if there is a preference with
* this name that is not a int
*/
public static int getInt(Context context, String key, int defaultValue) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
return settings.getInt(key, defaultValue);
}
/**
* put long preferences
*
* @param context context
* @param key The name of the preference to modify
* @param value The new values for the preference
* @return True if the new values were successfully written to persistent storage.
*/
public static boolean putLong(Context context, String key, long value) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putLong(key, value);
return editor.commit();
}
/**
* get long preferences
*
* @param context context
* @param key The name of the preference to retrieve
* @return The preference values if it exists, or -1. Throws ClassCastException if there is a preference with this
* name that is not a long
* @see #getLong(Context, String, long)
*/
public static long getLong(Context context, String key) {
return getLong(context, key, -1);
}
/**
* get long preferences
*
* @param context context
* @param key The name of the preference to retrieve
* @param defaultValue Value to return if this preference does not exist
* @return The preference values if it exists, or defValue. Throws ClassCastException if there is a preference with
* this name that is not a long
*/
public static long getLong(Context context, String key, long defaultValue) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
return settings.getLong(key, defaultValue);
}
/**
* put float preferences
*
* @param context context
* @param key The name of the preference to modify
* @param value The new values for the preference
* @return True if the new values were successfully written to persistent storage.
*/
public static boolean putFloat(Context context, String key, float value) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putFloat(key, value);
return editor.commit();
}
/**
* get float preferences
*
* @param context context
* @param key The name of the preference to retrieve
* @return The preference values if it exists, or -1. Throws ClassCastException if there is a preference with this
* name that is not a float
* @see #getFloat(Context, String, float)
*/
public static float getFloat(Context context, String key) {
return getFloat(context, key, -1);
}
/**
* get float preferences
*
* @param context context
* @param key The name of the preference to retrieve
* @param defaultValue Value to return if this preference does not exist
* @return The preference values if it exists, or defValue. Throws ClassCastException if there is a preference with
* this name that is not a float
*/
public static float getFloat(Context context, String key, float defaultValue) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
return settings.getFloat(key, defaultValue);
}
/**
* put boolean preferences
*
* @param context context
* @param key The name of the preference to modify
* @param value The new values for the preference
* @return True if the new values were successfully written to persistent storage.
*/
public static boolean putBoolean(Context context, String key, boolean value) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(key, value);
return editor.commit();
}
/**
* get boolean preferences, default is false
*
* @param context context
* @param key The name of the preference to retrieve
* @return The preference values if it exists, or false. Throws ClassCastException if there is a preference with this
* name that is not a boolean
* @see #getBoolean(Context, String, boolean)
*/
public static boolean getBoolean(Context context, String key) {
return getBoolean(context, key, false);
}
/**
* get boolean preferences
*
* @param context context
* @param key The name of the preference to retrieve
* @param defaultValue Value to return if this preference does not exist
* @return The preference values if it exists, or defValue. Throws ClassCastException if there is a preference with
* this name that is not a boolean
*/
public static boolean getBoolean(Context context, String key, boolean defaultValue) {
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
return settings.getBoolean(key, defaultValue);
}
public static boolean clear(Context context) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).clear(true);
SharedPreferences settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.clear();
return editor.commit();
}
}

View File

@@ -0,0 +1,175 @@
package com.xscm.moduleutil.utils;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import com.blankj.utilcode.util.ToastUtils;
import com.xscm.moduleutil.R;
import com.xscm.moduleutil.base.CommonAppContext;
import com.xscm.moduleutil.widget.CommonAppConfig;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created by cxf on 2018/9/29.
* 处理 检查权限和 startActivityForResult 的回调的Fragment
*/
public class ProcessFragment extends Fragment {
private Context mContext;
private PermissionCallback mPermissionCallback;
private ActivityResultCallback mActivityResultCallback;
private LinkedHashMap<String, Boolean> mMap;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getActivity();
}
/**
* 申请权限
*/
public void requestPermissions(PermissionCallback callback, String... permissions) {
if (callback == null || permissions == null || permissions.length == 0) {
return;
}
boolean isAllGranted = true;
if (mMap == null) {
mMap = new LinkedHashMap<>();
} else {
mMap.clear();
}
for (String permission : permissions) {
boolean isGranted = ContextCompat.checkSelfPermission(mContext, permission) == PackageManager.PERMISSION_GRANTED;
mMap.put(permission, isGranted);
if (!isGranted) {
isAllGranted = false;
}
}
if (isAllGranted) {
callback.onAllGranted();
callback.onResult(mMap);
mPermissionCallback = null;
} else {
mPermissionCallback = callback;
requestPermissions(permissions, 0);
}
}
/**
* 申请权限结果
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
boolean isAllGranted = true;
if (mMap == null) {
mMap = new LinkedHashMap<>();
} else {
mMap.clear();
}
for (int i = 0, len = grantResults.length; i < len; i++) {
boolean isGranted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
mMap.put(permissions[i], isGranted);
if (!isGranted) {
isAllGranted = false;
}
}
if (isAllGranted) {
if (mPermissionCallback != null) {
mPermissionCallback.onAllGranted();
}
} else {
showTip();
}
if (mPermissionCallback != null) {
mPermissionCallback.onResult(mMap);
}
mPermissionCallback = null;
}
/**
* 拒绝某项权限时候的提示
*/
private void showTip() {
if (mMap == null && mMap.size() == 0) {
return;
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, Boolean> entry : mMap.entrySet()) {
if (!entry.getValue()) {
switch (entry.getKey()) {
case Manifest.permission.READ_EXTERNAL_STORAGE:
case Manifest.permission.WRITE_EXTERNAL_STORAGE:
String permissionStorage = WordUtil.getString(R.string.permission_storage);
if (sb.indexOf(permissionStorage) < 0) {
sb.append(permissionStorage);
sb.append("");
}
break;
case Manifest.permission.CAMERA:
sb.append(WordUtil.getString(R.string.permission_camera));
sb.append("");
break;
case Manifest.permission.RECORD_AUDIO:
sb.append(WordUtil.getString(R.string.permission_record_audio));
sb.append("");
break;
case Manifest.permission.ACCESS_COARSE_LOCATION:
sb.append(WordUtil.getString(R.string.permission_location));
sb.append("");
CommonAppConfig.getInstance().clearLocationInfo();
break;
case Manifest.permission.READ_PHONE_STATE:
sb.append(WordUtil.getString(R.string.permission_read_phone_state));
sb.append("");
break;
}
}
}
String s = sb.toString();
if (!TextUtils.isEmpty(s) && s.length() > 1) {
s = s.substring(0, s.length() - 1);
}
final String tip = String.format(WordUtil.getString(R.string.permission_refused), s);
CommonAppContext.postDelayed(new Runnable() {
@Override
public void run() {
ToastUtils.showShort(tip);
}
}, 300);
}
public void startActivityForResult(Intent intent, ActivityResultCallback callback) {
mActivityResultCallback = callback;
super.startActivityForResult(intent, 0);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mActivityResultCallback != null) {
mActivityResultCallback.onResult(resultCode, data);
if (resultCode == -1) {//RESULT_OK
mActivityResultCallback.onSuccess(data);
} else {
mActivityResultCallback.onFailure();
}
}
}
}

View File

@@ -0,0 +1,33 @@
package com.xscm.moduleutil.utils;
/**
* 描述 describe
*/
public class SPConstants {
public final static String IntentKey_ImageList = "IntentKey_ImageList";
public final static String IntentKey_CurrentPosition = "IntentKey_CurrentPosition";
public static final String PREFERENCE_NAME = "Vespa";
public static final String PREFERENCE_SEARCH_HISTORY = "searchHistory";
public static final String TOKEN = "token";
public static final String SEARCH_HISTORY = "SearchHistory";
public static final String USER_ID = "UserId";
public static final String USER_BEAN = "userBean";
public static final String EMQTT_CLIENT_ID = "emqttClientId";
public static final String FIRST_ENTER_ROOM = "firstEnterRoom";
public static final String PLAY_MODE = "PLAY_MODE"; //播放模式 0 顺序循序播放 1随机播放 2单曲循环
public static final String VOLUME = "VOLUME"; //音量
public static final String CURRENT_MUSIC = "CURRENT_MUSIC"; //当前播放音乐
public static final String OPEN_EFFECT = "OPEN_EFFECT"; //开启特效
public static final String OPEN_AU_BACK = "OPEN_AU_BACK"; //开启耳返
public static final String ORDER_NEWS_COUNT = "orderNewsCount";
public static final String ORDER_LAST_MSG = "lastOrderMsg";
public static final String GIFT_LIST = "giftList";//礼物列表
public static final String COMMON_EMOJI_LIST = "commonEmojiList";//普通房间表情列表
public static final String SPECIAL_EMOJI_LIST = "specialEmojiList";//房间专属表情列表
public static final String CABIN="cabin";//小黑屋
public static final String REAL_NAME = "realName";//是否实名认证
public static final String USER_INFO = "userInfo";
}

View File

@@ -0,0 +1,40 @@
package com.xscm.moduleutil.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Sha1Util {
public static String shaEncode(long timestamp) {
String val = "token" + SpUtil.getToken() + "timestamp" + timestamp ;
// String val = "token" + SpUtil.getToken() + "timestamp" + timestamp + BuildConfig.SALT;
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("SHA-1");
md5.update(val.getBytes());
byte[] m = md5.digest();//加密
return byteArrayToHex(m).toLowerCase();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
public static String byteArrayToHex(byte[] byteArray) {
// 首先初始化一个字符数组用来存放每个16进制字符
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] resultCharArray = new char[byteArray.length * 2];
// 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
int index = 0;
for (byte b : byteArray) {
resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
resultCharArray[index++] = hexDigits[b & 0xf];
}
// 字符数组组合成字符串返回
return new String(resultCharArray);
}
}

View File

@@ -0,0 +1,544 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import com.alibaba.fastjson.JSON;
import com.blankj.utilcode.util.SPUtils;
import com.xscm.moduleutil.base.CommonAppContext;
import com.xscm.moduleutil.bean.UserBean;
import com.xscm.moduleutil.bean.UserInfo;
import java.util.Map;
/**
* Created by cxf on 2018/9/17.
* SharedPreferences 封装
*/
public class SpUtil {
private static SpUtil sInstance;
private static SharedPreferences mSharedPreferences;
public static final String UID = "uid";
public static final String TOKEN = "token";
public static final String USER_INFO = "userInfo";
public static final String CONFIG = "config";
public static final String SYSTEM_MSG_COUNT = "systemMsgCount";
public static final String LOCATION_LNG = "locationLng";
public static final String LOCATION_LAT = "locationLat";
public static final String LOCATION_PROVINCE = "locationProvince";
public static final String LOCATION_CITY = "locationCity";
public static final String LOCATION_DISTRICT = "locationDistrict";
public static final String MH_BEAUTY_ENABLE = "mhBeautyEnable";
public static final String BRIGHTNESS = "brightness";//亮度
public static final String IM_MSG_RING = "imMsgRing";//私信音效
public static final String DEVICE_ID = "deviceId";
public static final String TEENAGER = "teenager";
public static final String TEENAGER_SHOW = "teenagerShow";
public static final String TX_IM_USER_SIGN = "txImUserSign";//腾讯IM用户签名登录腾讯IM用
public static final String TPNS_NOTIFY_EXT = "tpnsNotifyExt";//tpns通知携带参数
public static final String BASE_FUNCTION_MODE = "baseFunctionMode";//基本功能模式
public static final String LANGUAGE = "language";
private SpUtil() {
mSharedPreferences = CommonAppContext.getInstance().getSharedPreferences("SharedPreferences", Context.MODE_PRIVATE);
}
public static SpUtil getInstance() {
if (sInstance == null) {
synchronized (SpUtil.class) {
if (sInstance == null) {
sInstance = new SpUtil();
}
}
}
return sInstance;
}
public int getIntValue(String key, int defaultValue) {
return mSharedPreferences.getInt(key, defaultValue);
}
public void setIntValue(String key, int value) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putInt(key, value);
editor.apply();
}
/**
* 保存一个字符串
*/
public void setStringValue(String key, String value) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(key, value);
editor.apply();
}
/**
* 获取一个字符串
*/
public String getStringValue(String key) {
return mSharedPreferences.getString(key, "");
}
/**
* 保存多个字符串
*/
public void setMultiStringValue(Map<String, String> pairs) {
if (pairs == null || pairs.size() == 0) {
return;
}
SharedPreferences.Editor editor = mSharedPreferences.edit();
for (Map.Entry<String, String> entry : pairs.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
editor.putString(key, value);
}
}
editor.apply();
}
/**
* 获取多个字符串
*/
public String[] getMultiStringValue(String... keys) {
if (keys == null || keys.length == 0) {
return null;
}
int length = keys.length;
String[] result = new String[length];
for (int i = 0; i < length; i++) {
String temp = "";
if (!TextUtils.isEmpty(keys[i])) {
temp = mSharedPreferences.getString(keys[i], "");
}
result[i] = temp;
}
return result;
}
/**
* 保存一个布尔值
*/
public static void setBooleanValue(String key, boolean value) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(key, value);
editor.apply();
}
/**
* 获取一个布尔值
*/
public boolean getBooleanValue(String key) {
return mSharedPreferences.getBoolean(key, false);
}
/**
* 获取一个布尔值
*/
public static boolean getBooleanValue(String key, boolean defaultValue) {
return mSharedPreferences.getBoolean(key, defaultValue);
}
/**
* 保存多个布尔值
*/
public void setMultiBooleanValue(Map<String, Boolean> pairs) {
if (pairs == null || pairs.size() == 0) {
return;
}
SharedPreferences.Editor editor = mSharedPreferences.edit();
for (Map.Entry<String, Boolean> entry : pairs.entrySet()) {
String key = entry.getKey();
Boolean value = entry.getValue();
if (!TextUtils.isEmpty(key)) {
editor.putBoolean(key, value);
}
}
editor.apply();
}
/**
* 获取多个布尔值
*/
public boolean[] getMultiBooleanValue(String[] keys) {
if (keys == null || keys.length == 0) {
return null;
}
int length = keys.length;
boolean[] result = new boolean[length];
for (int i = 0; i < length; i++) {
boolean temp = false;
if (!TextUtils.isEmpty(keys[i])) {
temp = mSharedPreferences.getBoolean(keys[i], false);
}
result[i] = temp;
}
return result;
}
public void removeValue(String... keys) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
for (String key : keys) {
editor.remove(key);
}
editor.apply();
}
/**
* 亮度
*/
public void setBrightness(float brightness) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putFloat(BRIGHTNESS, brightness);
editor.apply();
}
/**
* 亮度
*/
public float getBrightness() {
return mSharedPreferences.getFloat(BRIGHTNESS, -1.0f);
}
/**
* 私信音效
*/
public void setImMsgRingOpen(boolean imMsgRingOpen) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(IM_MSG_RING, imMsgRingOpen);
editor.apply();
}
/**
* 私信音效
*/
public boolean isImMsgRingOpen() {
return mSharedPreferences.getBoolean(IM_MSG_RING, true);
}
public static String getToken() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString(SPConstants.TOKEN);
}
public static void setBoolean(String key, boolean value) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(key, value, true);
}
public static boolean getBoolean(String key, boolean defaultValue) {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getBoolean(key, defaultValue);
}
public static int getUserId() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getInt(SPConstants.USER_ID);
}
public static void saveUserId(int userId) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.USER_ID, userId, true);
}
public static void setMusicVolume(int musicVolume) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("musicVolume", musicVolume, true);
}
public static Integer getMusicVolume() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getInt("musicVolume", 50);
}
public static void settPlayoutVolume(int tPlayoutVolume){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("tPlayoutVolume", tPlayoutVolume, true);
}
public static Integer gettPlayoutVolume(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getInt("tPlayoutVolume", 50);
}
public static String getMyRoomId() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("MyRoomId");
}
public static void saveUserInfo(UserInfo userInfo) {
String s = JSON.toJSONString(userInfo);
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.USER_INFO, s, true);
}
public static void saveUserBean(UserBean userBean) {
String s = JSON.toJSONString(userBean);
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.USER_BEAN, s, true);
}
public static void saveMyRoomId(String roomId) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("MyRoomId", roomId, true);
}
public static void saveSearchHistory(String searchHistory) {
SPUtils.getInstance(SPConstants.PREFERENCE_SEARCH_HISTORY).put(SPConstants.SEARCH_HISTORY, searchHistory);
}
public static String getSearchHistory() {
return SPUtils.getInstance(SPConstants.PREFERENCE_SEARCH_HISTORY).getString(SPConstants.SEARCH_HISTORY);
}
public static void putToken(String token) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.TOKEN, token, true);
}
public static void saveTzbl(String roomId, float bl) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(getUserId() + "-" + roomId + "_Tzbl", bl, true);
}
public static float getTzbl(String roomId) {
float bl = SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getFloat(getUserId() + "-" + roomId + "_Tzbl");
if (bl < 0.0f) {
if (roomId.equals(getMyRoomId())) {
return 0.8f;
} else {
return 0.0f;
}
} else {
return bl;
}
}
public static void saveEmqttId(String clientId) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.EMQTT_CLIENT_ID, clientId);
}
public static String getEmqttId() {
String s = SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString(SPConstants.EMQTT_CLIENT_ID);
return s;
}
//获取SharedPreferences音乐轮播方式
public static int getPlayPattern() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getInt(SPConstants.PLAY_MODE, 1);
}
//通过SharedPreferences设置音乐轮播方式
public static void setPlayPattern(int i) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.PLAY_MODE, i);
}
//获取SharedPreferences音乐播放音量
public static int getChannelVolume() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getInt(SPConstants.VOLUME, 20);
}
//设置SharedPreferences音乐播放音量
public static void setChannelVolume(int i) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.VOLUME, i);
}
//获取播放的音乐
public static int getPlayCurrentMusic() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getInt(SPConstants.CURRENT_MUSIC, 0);
}
//设置播放的音乐
public static void setPlayCurrentMusic(int i) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.CURRENT_MUSIC, i);
}
//设置开启特效
public static void setOpenEffect(int i) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.OPEN_EFFECT, i);
}
//获取开启特效
public static int getOpenEffect() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getInt(SPConstants.OPEN_EFFECT, 1);
}
//设置耳返
public static void setAuricularBack(int i) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.OPEN_AU_BACK, i);
}
//获取耳返
public static int getAuricularBack() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getInt(SPConstants.OPEN_AU_BACK, 0);
}
//获取新的消息数量
public static int getOrderNewCounts() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getInt(SPConstants.ORDER_NEWS_COUNT, 0);
}
//设置新的消息数量
public static void setOrderNewCounts(int i) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.ORDER_NEWS_COUNT, i);
}
//获取装载的消息
public static String getLastOrderMsg() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString(SPConstants.ORDER_LAST_MSG, " ");
}
//设置装载的消息
public static void setLastOrderMsg(String s) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put(SPConstants.ORDER_LAST_MSG, s);
}
//新的token
public static void putNewToken(String token) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("newToken", token, true);
}
//新的token
public static String getNewToken() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("newToken", "");
}
public static void setAgreeSkillProtocol() {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("agreeSkillProtocol", true, true);
}
public static boolean getAgreeSkillProtocol() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getBoolean("agreeSkillProtocol", false);
}
public static void setInReview(boolean inReview) {
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("inReview", inReview, true);
}
public static boolean inReview() {
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getBoolean("inReview", false);
}
public static void setHomeBanner(String banner){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("homeBanner", banner, true);
}
public static String getHomeBanner(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("homeBanner", "");
}
public static void setMusicName(String name){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("musicName", name, true);
}
public static String getMusicName(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("musicName", "");
}
public static void setTopRoom(String topRoom){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("topRoom", topRoom, true);
}
public static void setUserOnline(String online){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("userOnline", online, true);
}
public static String getUserOnline(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("userOnline", "");
}
public static void setTopRoomTop(String topRoom){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("topRoomTop", topRoom, true);
}
public static String getTopRoom(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("topRoom", "");
}
public static String getTopRoomTop(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("topRoomTop", "");
}
public static void setRoomTypeModel(String roomTypeModel){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("roomTypeModel", roomTypeModel, true);
}
public static String getRoomTypeModel(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("roomTypeModel", "");
}
public static void setRoomInfoResp(String roomInfoResp){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("RoomInfoResp", roomInfoResp, true);
}
public static String getRoomInfoResp(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("RoomInfoResp", "");
}
public static void setHomeBean(String homeBean){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("homeBean", homeBean, true);
}
public static String getHomeBean(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("homeBean", "");
}
public static void setRoomModel(String roomModel){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("roomModel", roomModel, true);
}
public static String getRoomModel(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("roomModel", "");
}
public static void setRtmToken(String rtm_token){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("rtm_token", rtm_token, true);
}
public static String getRtmToken(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("rtm_token", "");
}
public static void setAuctionId(String auctionId){
SPUtils.getInstance(SPConstants.PREFERENCE_NAME).put("auctionId", auctionId, true);
}
public static String getauctionId(){
return SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString("auctionId", "");
}
// TODO: 2025/5/16 设置实名认证
public static void setRealName(boolean realName){
SPUtils.getInstance(SPConstants.REAL_NAME).put("realName", realName, true);
}
// TODO: 2025/5/16 是否实名认证
public static boolean getRealName(){
return SPUtils.getInstance(SPConstants.REAL_NAME).getBoolean("realName", false);
}
public static UserBean getUserBean() {
String s = SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString(SPConstants.USER_BEAN);
if (TextUtils.isEmpty(s)) {
return new UserBean();
}
UserBean userBean = JSON.parseObject(s, UserBean.class);
if (userBean == null) {
return new UserBean();
}
return userBean;
}
public static UserInfo getUserInfo() {
String s = SPUtils.getInstance(SPConstants.PREFERENCE_NAME).getString(SPConstants.USER_INFO);
if (TextUtils.isEmpty(s)) {
return new UserInfo();
}
UserInfo userInfo = JSON.parseObject(s, UserInfo.class);
if (userInfo == null) {
return new UserInfo();
}
return userInfo;
}
/**
* 是否同意协议
*
* @return
*/
public static boolean isAgreePolicy() {
return !SPUtils.getInstance("Constant").getBoolean("launchRequestPermission", true);
}
/**
* 同意协议
*/
public static void completeAgreePolicy() {
SPUtils.getInstance("Constant").put("launchRequestPermission",
false, true);
}
}

View File

@@ -0,0 +1,240 @@
package com.xscm.moduleutil.utils;
import com.xscm.moduleutil.widget.CommonAppConfig;
import java.io.File;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Random;
import java.util.regex.Pattern;
/**
* Created by cxf on 2018/9/28.
*/
public class StringUtil {
private static final DecimalFormat sDecimalFormat;
private static final DecimalFormat sDecimalFormat2;
// private static Pattern sPattern;
private static final Pattern sIntPattern;
private static final Random sRandom;
private static final StringBuilder sStringBuilder;
static {
sDecimalFormat = new DecimalFormat("#.#");
sDecimalFormat.setRoundingMode(RoundingMode.HALF_UP);
sDecimalFormat2 = new DecimalFormat("#.##");
sDecimalFormat2.setRoundingMode(RoundingMode.DOWN);
//sPattern = Pattern.compile("[\u4e00-\u9fa5]");
sIntPattern = Pattern.compile("^[-\\+]?[\\d]*$");
sRandom = new Random();
sStringBuilder = new StringBuilder();
}
public static String format(double value) {
return sDecimalFormat.format(value);
}
/**
* 把数字转化成多少万
*/
public static String toWan(long num) {
if (num < 10000) {
return String.valueOf(num);
}
return sDecimalFormat.format(num / 10000d) + "W";
}
/**
* 把数字转化成多少万
*/
public static String toWan2(String num,int decimalPlaces) {
if (num == null ){
return "0";
}else {
try {
// 尝试解析为 double 类型
double numDouble = Double.parseDouble(num);
if (numDouble < 10000) {
return String.valueOf((long) numDouble);
}
if (decimalPlaces == 1) {
return sDecimalFormat2.format(numDouble / 10000d)+"w";
} else if (decimalPlaces == 2) {
return sDecimalFormat2.format(numDouble / 10000d)+"w";
} else {
return String.valueOf((long) (numDouble / 10000)) + "w";
}
} catch (NumberFormatException e) {
// 如果解析失败,返回 "Invalid input"
return "0";
}
}
}
/**
* 把数字转化成多少万
*/
public static String toWan3(long num) {
if (num < 10000) {
return String.valueOf(num);
}
return sDecimalFormat2.format(num / 10000d) + "w";
}
// /**
// * 判断字符串中是否包含中文
// */
// public static boolean isContainChinese(String str) {
// Matcher m = sPattern.matcher(str);
// if (m.find()) {
// return true;
// }
// return false;
// }
/**
* 判断一个字符串是否是数字
*/
public static boolean isInt(String str) {
return sIntPattern.matcher(str).matches();
}
/**
* 把一个long类型的总毫秒数转成时长
*/
public static String getDurationText(long mms) {
int hours = (int) (mms / (1000 * 60 * 60));
int minutes = (int) ((mms % (1000 * 60 * 60)) / (1000 * 60));
int seconds = (int) ((mms % (1000 * 60)) / 1000);
sStringBuilder.delete(0, sStringBuilder.length());
if (hours > 0) {
if (hours < 10) {
sStringBuilder.append("0");
}
sStringBuilder.append(String.valueOf(hours));
sStringBuilder.append(":");
}
if (minutes > 0) {
if (minutes < 10) {
sStringBuilder.append("0");
}
sStringBuilder.append(String.valueOf(minutes));
sStringBuilder.append(":");
} else {
sStringBuilder.append("00:");
}
if (seconds > 0) {
if (seconds < 10) {
sStringBuilder.append("0");
}
sStringBuilder.append(String.valueOf(seconds));
} else {
sStringBuilder.append("00");
}
return sStringBuilder.toString();
}
/**
* 把秒数转成时长
*/
public static String getDurationText2(int secondCount,StringBuilder sb) {
int hours = secondCount / 3600;
int minutes = 0;
int last = secondCount % 3600;
if (last > 0) {
minutes = last / 60;
}
int seconds = secondCount % 60;
sb.delete(0, sb.length());
if (hours > 0) {
if (hours < 10) {
sb.append("0");
}
sb.append(String.valueOf(hours));
sb.append(":");
}
if (minutes > 0) {
if (minutes < 10) {
sb.append("0");
}
sb.append(String.valueOf(minutes));
sb.append(":");
} else {
sb.append("00:");
}
if (seconds > 0) {
if (seconds < 10) {
sb.append("0");
}
sb.append(String.valueOf(seconds));
} else {
sb.append("00");
}
// String s = sb.toString();
// L.e("getDurationText---hours---->" + hours + "---minutes-->" + minutes + "---seconds-->" + seconds + "--s-->" + s);
return sb.toString();
}
/**
* 设置视频输出路径
*/
public static String generateVideoOutputPath() {
String outputDir = CommonAppConfig.VIDEO_PATH;
File outputFolder = new File(outputDir);
if (!outputFolder.exists()) {
outputFolder.mkdirs();
}
String videoName = DateFormatUtil.getVideoCurTimeString() + sRandom.nextInt(9999);
return contact(outputDir, "/android_", CommonAppConfig.getInstance().getUid(), "_", videoName, ".mp4");
}
/**
* 获取随机文件名
*/
public static String generateFileName() {
return contact("android_",
CommonAppConfig.getInstance().getUid(),
"_",
DateFormatUtil.getVideoCurTimeString(),
String.valueOf(sRandom.nextInt(9999)));
}
/**
* 多个字符串拼接
*/
public static String contact(String... args) {
sStringBuilder.delete(0, sStringBuilder.length());
for (String s : args) {
sStringBuilder.append(s);
}
return sStringBuilder.toString();
}
/*比较字符串*/
public static boolean compareString(String var1, String var2) {
if (var1 == null && var2 == null) {
return true;
} else if (var1 != null && var2 != null) {
return var1.equals(var2);
} else {
return false;
}
}
public static int getRandomInt(int bound){
return sRandom.nextInt(bound);
}
}

View File

@@ -0,0 +1,137 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import android.os.Build;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.MetaDataUtils;
import com.chad.library.BuildConfig;
import com.xscm.moduleutil.base.CommonAppContext;
import com.xscm.moduleutil.utils.config.ConfigUtils;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
public class SystemUtils {
/**
* 获取当前手机系统语言。
*
* @return 返回当前系统语言。例如:当前设置的是“中文-中国”则返回“zh-CN”
*/
public static String getSystemLanguage() {
return Locale.getDefault().getLanguage();
}
/**
* 获取当前手机系统版本号
*
* @return 系统版本号
*/
public static String getSystemVersion() {
return Build.VERSION.RELEASE;
}
/**
* 获取手机型号
*
* @return 手机型号
*/
public static String getSystemModel() {
return Build.MODEL;
}
/**
* 获取手机厂商
*
* @return 手机厂商
*/
public static String getDeviceBrand() {
return Build.BRAND;
}
public static String getClientID(String channel) {
StringBuffer sb = new StringBuffer();
sb.append(channel);
sb.append(Build.SERIAL);
sb.append(Build.BOARD.length() % 10);
sb.append(Build.BRAND.length() % 10);
sb.append(Build.CPU_ABI.length() % 10);
sb.append(Build.DEVICE.length() % 10);
sb.append(Build.DISPLAY.length() % 10);
sb.append(Build.HOST.length() % 10);
sb.append(Build.ID.length() % 10);
sb.append(Build.MANUFACTURER.length() % 10);
sb.append(Build.MODEL.length() % 10);
sb.append(Build.PRODUCT.length() % 10);
sb.append(Build.TAGS.length() % 10);
sb.append(Build.TYPE.length() % 10);
sb.append(Build.USER.length() % 10);
return Md5Utils.get(sb.toString());
}
public static String getShortClientID(Context context, String channel) {
String cid = getClientID(channel);
return Md5Utils.get(cid + getUUID(context));
}
public static String getShortClientID(Context context) {
String cid = getClientID("xqipaoandroid");
return Md5Utils.get(cid + getUUID(context));
}
/**
* 得到全局唯一UUID
*/
public static String getUUID(Context context) {
String system_uuid_key = "system_uuid";
ConfigUtils configUtils = ConfigUtils.getInstance(context);
configUtils.setConfigName(system_uuid_key);
String system_config_uuid = configUtils.findStringByKey(system_uuid_key);
if (system_config_uuid == null) {
// system_config_uuid = DeviceUtils.getUniqueDeviceId();
configUtils.addOrUpdateText(system_uuid_key, system_config_uuid);
}
return system_config_uuid;
}
/**
* 系统参数
*
* @return
*/
public static Map<String, String> getSystemParams() {
Map<String, String> headers = new HashMap<>();
headers.put("deviceId", SystemUtils.getShortClientID(CommonAppContext.getInstance()));
headers.put("appVersion", BuildConfig.VERSION_NAME + "." + BuildConfig.VERSION_CODE);
headers.put("versionName", BuildConfig.VERSION_NAME);
headers.put("versionCode", String.valueOf(BuildConfig.VERSION_CODE));
headers.put("system", "android");
headers.put("emulator", CommonAppContext.getInstance().emulator);
headers.put("deviceName", SystemUtils.getDeviceBrand() + SystemUtils.getSystemModel() + SystemUtils.getSystemVersion());
try {
String channelId = MetaDataUtils.getMetaDataInApp("TD_CHANNEL_ID");
headers.put("CHANNELID", channelId);
headers.put("appName", encodeHeadInfo(AppUtils.getAppName()));
} catch (Exception e) {
e.printStackTrace();
}
return headers;
}
private static String encodeHeadInfo( String headInfo ) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0, length = headInfo.length(); i < length; i++) {
char c = headInfo.charAt(i);
if (c <= '\u001f' || c >= '\u007f') {
stringBuffer.append( String.format ("\\u%04x", (int)c) );
} else {
stringBuffer.append(c);
}
}
return stringBuffer.toString();
}
}

View File

@@ -0,0 +1,240 @@
package com.xscm.moduleutil.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class TimeUtils {
/**
* 获取年
*
* @return
*/
public static int getYear() {
Calendar cd = Calendar.getInstance();
return cd.get(Calendar.YEAR);
}
/**
* 获取月
*
* @return
*/
public static int getMonth() {
Calendar cd = Calendar.getInstance();
return cd.get(Calendar.MONTH) + 1;
}
public static String getMonths() {
Calendar cd = Calendar.getInstance();
int month = cd.get(Calendar.MONTH) + 1;
if (month <= 9) {
return "0" + month;
} else {
return String.valueOf(month);
}
}
/**
* 获取日
*
* @return
*/
public static int getDay() {
Calendar cd = Calendar.getInstance();
return cd.get(Calendar.DATE);
}
public static String getDays() {
Calendar cd = Calendar.getInstance();
int day = cd.get(Calendar.DATE);
if (day <= 9) {
return "0" + day;
} else {
return String.valueOf(day);
}
}
/**
* 获取时
*
* @return
*/
public static int getHour() {
Calendar cd = Calendar.getInstance();
return cd.get(Calendar.HOUR);
}
public static String getFormatterHour() {
Calendar cd = Calendar.getInstance();
int hour = cd.get(Calendar.HOUR_OF_DAY);
if (hour < 10) {
return "0" + hour;
}
return String.valueOf(hour);
}
/**
* 获取时
*
* @return
*/
public static int getNewHour() {
Calendar cd = Calendar.getInstance();
return cd.get(Calendar.HOUR_OF_DAY);
}
/**
* 获取分
*
* @return
*/
public static int getMinute() {
Calendar cd = Calendar.getInstance();
return cd.get(Calendar.MINUTE);
}
/**
* 获取分
*
* @return
*/
public static String getFormatterMinute() {
Calendar cd = Calendar.getInstance();
int minute = cd.get(Calendar.MINUTE);
if (minute < 10) {
return "0" + minute;
}
return String.valueOf(minute);
}
/**
* 获取秒
*
* @return
*/
public static int getSeconds() {
Calendar cd = Calendar.getInstance();
return cd.get(Calendar.SECOND);
}
/**
* 获取秒
*
* @return
*/
public static String getFormatterSeconds() {
Calendar cd = Calendar.getInstance();
int seconds = cd.get(Calendar.SECOND);
if (seconds < 10) {
return "0" + seconds;
}
return String.valueOf(seconds);
}
/**
* 根据某年份、某月份获取对应的月份天数
*
* @param year 年份
* @param month 月份
* @return 月份的天数
*/
public static int getDaysByYearMonth(int year, int month) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
calendar.set(Calendar.DATE, 1);
calendar.roll(Calendar.DATE, -1);
int days = calendar.get(Calendar.DATE);
return days;
}
/**
* 日期字符串例如 2015-3-10 Num:需要减少的天数例如 7
*
* @param day 日期字符串例如 2015-3-10
* @param Num 需要减少的天数例如 7
* @return
*/
public static String getDateStr(String day, int Num) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date nowDate = null;
try {
nowDate = df.parse(day);
} catch (ParseException e) {
e.printStackTrace();
}
//如果需要向后计算日期 -改为+
Date newDate2 = new Date(nowDate.getTime() - (long) Num * 24 * 60 * 60 * 1000);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String dateOk = simpleDateFormat.format(newDate2);
return dateOk;
}
/*获取系统时间 格式为:"yyyy/MM/dd "*/
public static String getCurrentDate() {
Date d = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日");
return sf.format(d);
}
/*时间戳转换成字符窜*/
public static String getDateToString(long time) {
Date d = new Date(time);
SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日");
return sf.format(d);
}
public static String getDateToStringNoZ(long time) {
Date d = new Date(time);
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
return sf.format(d);
}
/*将字符串转为时间戳*/
public static long getStringToDate(String time) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
Date date = new Date();
try {
date = sdf.parse(time);
} catch (ParseException e) {
e.printStackTrace();
}
return date.getTime();
}
//获取当前日期
public static String getCurrentDate2() {
Date d = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
return sf.format(d);
}
/**
* 将毫秒数转换为 MM:ss 格式03:45
*/
public static String formatDuration(long durationMs) {
long seconds = (durationMs / 1000) % 60;
long minutes = (durationMs / 1000 / 60) % 60;
return String.format("%02d:%02d", minutes, seconds);
}
public static String formatDuration2(long durationMs) {
long totalSeconds = durationMs / 1000;
long days = totalSeconds / 86400;
long hours = (totalSeconds % 86400) / 3600;
StringBuilder sb = new StringBuilder();
if (days > 0) {
sb.append(days).append("");
}
if (hours > 0 || days > 0) {
sb.append(hours).append("小时 ");
}
// sb.append(String.format("%02d:%02d"));
return sb.toString().trim();
}
}

View File

@@ -0,0 +1,56 @@
package com.xscm.moduleutil.utils;
import android.os.CountDownTimer;
public class TimerManager {
private static TimerManager instance;
private CountDownTimer countDownTimer;
private boolean isRunning = false;
private TimerManager() {}
public static synchronized TimerManager getInstance() {
if (instance == null) {
instance = new TimerManager();
}
return instance;
}
public void startTimer() {
if (countDownTimer == null && !isRunning) {
countDownTimer = new CountDownTimer(60000, 1000) { // 1分钟倒计时
@Override
public void onTick(long millisUntilFinished) {
// 每秒执行一次
}
@Override
public void onFinish() {
// 倒计时完成,请求接口
requestApi();
startTimer(); // 继续下一轮倒计时
}
};
countDownTimer.start();
isRunning = true;
}
}
public void stopTimer() {
if (countDownTimer != null) {
countDownTimer.cancel();
countDownTimer = null;
isRunning = false;
}
}
private void requestApi() {
// 请求接口逻辑
}
public boolean isRunning() {
return isRunning;
}
}

View File

@@ -0,0 +1,53 @@
package com.xscm.moduleutil.utils;
import android.content.Context;
import com.lahm.library.EasyProtectorLib;
import com.lahm.library.EmulatorCheckCallback;
/**
* ProjectName: BubbleVoice
* Package: com.lnkj.lib_utils
* Description: java类作用描述
* Author: 姚闻达
* CreateDate: 2020/12/15 17:27
* UpdateUser: 更新者
* UpdateDate: 2020/12/15 17:27
* UpdateRemark: 更新说明
* Version: 1.0
*/
public class UtilConfig {
private static Context context;
public static String emulator = "0";
public static String salt = "";
public static void init(Context context) {
setContext(context);
}
public static Context getContext() {
return context;
}
public static void setContext(Context context) {
UtilConfig.context = context;
// checkInEmulator();
}
public static void checkInEmulator() {
emulator = EasyProtectorLib.checkIsRunningInEmulator(getContext(), new EmulatorCheckCallback() {
@Override
public void findEmulator(String emulatorInfo) {
// Logger.e(emulatorInfo);
}
}) ? "1" : "0";
}
public static String getSalt() {
return salt;
}
public static void setSalt(String salt) {
UtilConfig.salt = salt;
}
}

View File

@@ -0,0 +1,50 @@
package com.xscm.moduleutil.utils;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.LocaleList;
import android.util.DisplayMetrics;
import com.xscm.moduleutil.base.CommonAppContext;
import java.util.Locale;
/**
* Created by cxf on 2017/10/10.
* 获取string.xml中的字
*/
public class WordUtil {
private static Resources sResources;
static {
sResources = CommonAppContext.getInstance().getResources();
}
public static String getString(int res) {
if (res == 0) {
return "";
}
Locale appLocale = LanguageUtil.getLanguageLocale();
Configuration configuration = sResources.getConfiguration();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
LocaleList localeList = configuration.getLocales();
if (localeList.isEmpty() || !localeList.get(0).equals(appLocale)) {
configuration.setLocale(appLocale);
DisplayMetrics dm = sResources.getDisplayMetrics();
sResources.updateConfiguration(configuration, dm);
}
} else {
Locale locale = configuration.locale;
if (locale == null || !locale.equals(appLocale)) {
configuration.setLocale(appLocale);
DisplayMetrics dm = sResources.getDisplayMetrics();
sResources.updateConfiguration(configuration, dm);
}
}
return sResources.getString(res);
}
}

View File

@@ -0,0 +1,40 @@
package com.xscm.moduleutil.utils.config;
import java.util.HashMap;
import java.util.Map;
/**
*@author
*@data
*@description: 模拟获取网络配置信息
*/
public class ConfigLoader {
public interface LoadCallback {
void onFailure(Exception e);
void onSuccess(Object config);
}
public static void loadRemoteConfig(EnvironmentEnum env, LoadCallback callback) {
// 模拟异步加载远程配置
new Thread(() -> {
try {
Thread.sleep(500); // 模拟网络延迟
// 模拟不同环境返回不同的配置
Map<String, String> remoteData = new HashMap<>();
if (env == EnvironmentEnum.PRODUCTION) {
remoteData.put("feature_new_ui", "true");
remoteData.put("app_version", "3.0.0");
} else {
remoteData.put("feature_new_ui", "false");
remoteData.put("app_version", "2.1.0");
}
callback.onSuccess(new RemoteConfig(remoteData));
} catch (Exception e) {
callback.onFailure(e);
}
}).start();
}
}

View File

@@ -0,0 +1,52 @@
package com.xscm.moduleutil.utils.config;
import java.util.HashMap;
import java.util.Map;
public class ConfigManager {
// 当前环境配置
private EnvironmentEnum currentEnvironment = EnvironmentEnum.TEST;
// 远程配置缓存
private Map<String, String> remoteConfigs = new HashMap<>();
// 单例模式
private static final ConfigManager instance = new ConfigManager();
private ConfigManager() {}
public static ConfigManager getInstance() {
return instance;
}
// 切换环境
public void switchEnvironment(EnvironmentEnum environment) {
this.currentEnvironment = environment;
}
// 获取当前环境
public EnvironmentEnum getCurrentEnvironment() {
return currentEnvironment;
}
// 获取当前服务器地址
public String getCurrentServerUrl() {
return currentEnvironment.getServerUrl();
}
// 获取当前第三方 Key
public String getCurrentThirdPartyKey() {
return currentEnvironment.getALI_AUTH_KEY();
}
// 模拟获取远程配置(可替换为网络请求)
public void fetchRemoteConfigsFromApi() {
remoteConfigs.put("feature_flag", "enabled");
remoteConfigs.put("app_version", "2.0.0");
}
// 获取远程配置值
public String getRemoteConfigValue(String key) {
return remoteConfigs.get(key);
}
}

View File

@@ -0,0 +1,39 @@
package com.xscm.moduleutil.utils.config;
/**
*@author
*@data
*@description: 统一配置提供者
*/
public class ConfigProvider {
private static final RemoteConfigManager configManager = new RemoteConfigManager();
public static void loadConfigForEnvironment(EnvironmentEnum env, ConfigLoader.LoadCallback callback) {
// ConfigLoader.loadRemoteConfig(env, config -> {
//// configManager.saveConfig(env, config);
// callback.onSuccess(null);
// });
}
public static String getConfigValue(EnvironmentEnum env, String key) {
RemoteConfig config = configManager.getConfig(env);
if (config != null && config.containsKey(key)) {
return config.get(key);
}
return null;
}
public static RemoteConfig getAllConfigs(EnvironmentEnum env) {
return configManager.getConfig(env);
}
private static EnvironmentEnum currentEnv = EnvironmentEnum.TEST;
public static void setCurrentEnvironment(EnvironmentEnum env) {
currentEnv = env;
}
public static String getAliAuthKey() {
return currentEnv.getALI_AUTH_KEY();
}
}

View File

@@ -0,0 +1,163 @@
package com.xscm.moduleutil.utils.config;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.HashMap;
import java.util.Map;
public class ConfigUtils {
private static SharedPreferences sp = null;
private static SharedPreferences.Editor edit = null;
private static ConfigUtils instance = null;
private static Map<String, Object> data_list = null;
private static String data_list_name = "config";
public static ConfigUtils getInstance(Context context) {
if (instance == null) {
sp = context.getSharedPreferences(data_list_name, Context.MODE_PRIVATE);
instance = new ConfigUtils();
if (data_list == null)
data_list = new HashMap<String, Object>();
}
return instance;
}
//设置配置文件的名称
public void setConfigName(String configName) {
this.data_list_name = configName;
}
/*
* 添加或者更新一个方法
*/
public boolean addOrUpdateText(String key, String content) {
if (edit == null) {
edit = sp.edit();
}
data_list.put(key, content);
edit.putString(key, content);
return edit.commit();
}
public boolean addOrUpdateIntNumber(String key, int content) {
if (edit == null) {
edit = sp.edit();
}
data_list.put(key, content);
edit.putInt(key, content);
return edit.commit();
}
public boolean addOrUpdateFloatNumber(String key, float content) {
if (edit == null) {
edit = sp.edit();
}
data_list.put(key, content);
edit.putFloat(key, content);
return edit.commit();
}
public boolean addOrUpdateBoolean(String key, boolean content) {
if (edit == null) {
edit = sp.edit();
}
data_list.put(key, content);
edit.putBoolean(key, content);
return edit.commit();
}
/*
* 查询
*/
public String findStringByKey(String key) {
if (data_list.containsKey(key))
return data_list.get(key).toString();
else
return sp.getString(key, null);
}
public String findStringByKey(String key, String default_value) {
if (data_list.containsKey(key)) {
return data_list.get(key).toString();
} else {
return sp.getString(key, default_value);
}
}
public boolean findBoolByKey(String key) {
if (data_list.containsKey(key)) {
return (Boolean) data_list.get(key);
} else {
return sp.getBoolean(key, false);
}
}
public boolean findBoolByKey(String key, boolean default_value) {
if (data_list.containsKey(key)) {
return (Boolean) data_list.get(key);
} else {
return sp.getBoolean(key, default_value);
}
}
public int findIntByKey(String key) {
if (data_list.containsKey(key)) {
return (Integer) data_list.get(key);
} else {
return sp.getInt(key, -1);
}
}
public int findIntByKey(String key, int default_value) {
if (data_list.containsKey(key)) {
return (Integer) data_list.get(key);
} else {
return sp.getInt(key, default_value);
}
}
public float findFloatByKey(String key) {
if (data_list.containsKey(key)) {
return (Float) data_list.get(key);
} else {
return sp.getFloat(key, -1);
}
}
public float findFloatByKey(String key, float default_value) {
if (data_list.containsKey(key)) {
return (Float) data_list.get(key);
} else {
return sp.getFloat(key, default_value);
}
}
/*
* 删除
*/
public void deleteByKey(String key) {
if (edit == null) {
edit = sp.edit();
}
data_list.remove(key);
edit.remove(key);
edit.commit();
}
/*
* 清空
*/
public void clearConfig() {
if (edit == null) {
edit = sp.edit();
}
data_list.clear();
edit.clear();
edit.commit();
}
}

View File

@@ -0,0 +1,114 @@
package com.xscm.moduleutil.utils.config;
public enum EnvironmentEnum {
PRODUCTION(//生产环境
"http://chat.qxmier.com/",
"6rdWuz058oq5OahdbFiGEybUcdahd12J83L34Uc7MrPIrxtFG+rXiwDvRcqNvjwbClbbmvMrmxKVkIysFByBsl0Qe9kqd2w8T/nhK5G6eXXlk2V9AjYCieIU+jRnjZBB+Cfechr6rCGJ2aeBARIsXcRPW7wm9WFK9euh5T+v6Pyte68yNaNdcYCll3+U4/uCEog7HygCnMIbAU+kqoPdmn2H+51YOHW+VsnsHd4w1+I3f8Tt0xLIXGM4GWnQueZ5GR46GTWiSYMy8dCIh9SPIMRyC91GosVcfGPMJSdcXqc=",
"https://oss-cn-hangzhou.aliyuncs.com/",
"LTAI5tJ2UYfFNF7K3F4e1siv",
"DhpCS82gaigZljYqsWsUWUAZ20dREz",
"qx-yusheng",
"https://qx-yusheng.oss-cn-hangzhou.aliyuncs.com/",
"wxc7681513be9f926b",
1600101474,
"4a521d6f1c6343998b1c8fd425dea02a",
"tcp://81.70.45.221",
"https://vespa.qxmier.com"),
TEST(//测试环境
"http://tmd.qixing2.top/",
"6rdWuz058oq5OahdbFiGEybUcdahd12J83L34Uc7MrPIrxtFG+rXiwDvRcqNvjwbClbbmvMrmxKVkIysFByBsl0Qe9kqd2w8T/nhK5G6eXXlk2V9AjYCieIU+jRnjZBB+Cfechr6rCGJ2aeBARIsXcRPW7wm9WFK9euh5T+v6Pyte68yNaNdcYCll3+U4/uCEog7HygCnMIbAU+kqoPdmn2H+51YOHW+VsnsHd4w1+I3f8Tt0xLIXGM4GWnQueZ5GR46GTWiSYMy8dCIh9SPIMRyC91GosVcfGPMJSdcXqc=",
"https://oss-cn-hangzhou.aliyuncs.com/",
"LTAI5tJ2UYfFNF7K3F4e1siv",
"DhpCS82gaigZljYqsWsUWUAZ20dREz",
"qx-yusheng",
"https://qx-yusheng.oss-cn-hangzhou.aliyuncs.com/",
"wxc7681513be9f926b",
1600101474,
"05b406b4541e413887d8d2bf9be8642c",
"tcp://47.120.21.132",
"https://chatvespa.qxmier.com");
private final String serverUrl;
private final String ALI_AUTH_KEY;//阿里云授权key
private final String ossEndPoint;
private final String ossaAcessKeyId;
private final String ossAccessKeySecret;
private final String ossBucketName;
private final String ossBaseUrl;
private final String wxAppId;
private final int sdkAppId;//腾讯云sdkAppId im
private final String swSdkAppId;
private final String mqttUrl;
private final String H5Url;
EnvironmentEnum(String serverUrl, String ALI_AUTH_KEY, String ossEndPoint, String ossaAcessKeyId,
String ossAccessKeySecret, String ossBucketName, String ossBaseUrl, String wxAppId,
int sdkAppId, String swSdkAppId,String mqttUrl,String H5Url) {
this.serverUrl = serverUrl;
this.ALI_AUTH_KEY = ALI_AUTH_KEY;
this.ossEndPoint = ossEndPoint;
this.ossaAcessKeyId = ossaAcessKeyId;
this.ossAccessKeySecret = ossAccessKeySecret;
this.ossBucketName = ossBucketName;
this.ossBaseUrl = ossBaseUrl;
this.wxAppId=wxAppId;
this.sdkAppId=sdkAppId;
this.swSdkAppId = swSdkAppId;
this.mqttUrl = mqttUrl;
this.H5Url = H5Url;
}
public String getH5Url() {
return H5Url;
}
public String getMqttUrl() {
return mqttUrl;
}
public String getSwSdkAppId() {
return swSdkAppId;
}
public int getSdkAppId() {
return sdkAppId;
}
public String getWxAppId() {
return wxAppId;
}
public String getServerUrl() {
return serverUrl;
}
public String getALI_AUTH_KEY() {
return ALI_AUTH_KEY;
}
public String getOssEndPoint() {
return ossEndPoint;
}
public String getOssaAcessKeyId() {
return ossaAcessKeyId;
}
public String getOssAccessKeySecret() {
return ossAccessKeySecret;
}
public String getOssBucketName() {
return ossBucketName;
}
public String getOssBaseUrl() {
return ossBaseUrl;
}
}

View File

@@ -0,0 +1,37 @@
package com.xscm.moduleutil.utils.config;
import android.content.Context;
import android.content.SharedPreferences;
/**
*@author
*@data
*@description: 将配置信息保存在本地
*/
public class EnvironmentPrefs {
private static final String PREFS_NAME = "EnvironmentPrefs";
private static final String KEY_ENV = "selected_environment";
private final SharedPreferences sharedPreferences;
public EnvironmentPrefs(Context context) {
sharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
}
// 保存当前选择的环境
public void setSelectedEnvironment(EnvironmentEnum environment) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(KEY_ENV, environment.name());
editor.apply();
}
// 获取当前选择的环境,默认为 PRODUCTION
public EnvironmentEnum getSelectedEnvironment() {
String envName = sharedPreferences.getString(KEY_ENV, EnvironmentEnum.TEST.name());
try {
return EnvironmentEnum.valueOf(envName);
} catch (IllegalArgumentException e) {
return EnvironmentEnum.TEST; // 出错时默认返回生产环境
}
}
}

View File

@@ -0,0 +1,23 @@
package com.xscm.moduleutil.utils.config;
import java.util.Map;
public class RemoteConfig {
private Map<String, String> configs;
public RemoteConfig(Map<String, String> configs) {
this.configs = configs;
}
public String get(String key) {
return configs.get(key);
}
public boolean containsKey(String key) {
return configs.containsKey(key);
}
public Map<String, String> getAll() {
return configs;
}
}

View File

@@ -0,0 +1,21 @@
package com.xscm.moduleutil.utils.config;
import java.util.HashMap;
import java.util.Map;
public class RemoteConfigManager {
private Map<EnvironmentEnum, RemoteConfig> configCache = new HashMap<>();
public RemoteConfig getConfig(EnvironmentEnum env) {
return configCache.get(env);
}
public boolean hasConfig(EnvironmentEnum env) {
return configCache.containsKey(env);
}
public void saveConfig(EnvironmentEnum env, Object config) {
configCache.put(env, (RemoteConfig) config);
}
}

View File

@@ -0,0 +1,94 @@
package com.xscm.moduleutil.utils.location;
import android.annotation.SuppressLint;
import android.content.Context;
import android.location.Address;
import android.util.Log;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class GmsLocationProvider implements LocationProvider {
private static final String TAG = "GmsLocationProvider";
private FusedLocationProviderClient fusedLocationClient;
private LocationCallback locationCallback;
public GmsLocationProvider(Context context) {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
}
@SuppressLint("MissingPermission")
@Override
public void getLastKnownLocation(Context context, LocationCallback callback) {
fusedLocationClient.getLastLocation()
.addOnSuccessListener(location -> {
if (location != null) {
String city = getCityName(context, location.getLatitude(), location.getLongitude());
callback.onLocationReceived(location.getLatitude(), location.getLongitude(), city);
} else {
callback.onFailed("无法获取位置");
}
})
.addOnFailureListener(e -> callback.onFailed("Google Play 定位失败:" + e.getMessage()));
}
@SuppressLint("MissingPermission")
@Override
public void requestLocationUpdates(Context context, LocationCallback callback) {
this.locationCallback = new LocationCallback() {
@Override
public void onLocationReceived(double latitude, double longitude, String city) {
// for (android.location.Location location : locationResult.getLocations()) {
String city1 = getCityName(context, latitude, longitude);
callback.onLocationReceived(latitude, longitude, city1);
// }
}
@Override
public void onFailed(String errorMessage) {
}
// @Override
// public void onLocationResult(@NonNull LocationResult locationResult) {
// for (android.location.Location location : locationResult.getLocations()) {
// String city = getCityName(context, location.getLatitude(), location.getLongitude());
// callback.onLocationReceived(location.getLatitude(), location.getLongitude(), city);
// }
// }
};
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(10000)
.setFastestInterval(5000)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
fusedLocationClient.requestLocationUpdates(locationRequest, (com.google.android.gms.location.LocationCallback) locationCallback, null);
}
@Override
public void stopLocationUpdates() {
if (locationCallback != null) {
fusedLocationClient.removeLocationUpdates((com.google.android.gms.location.LocationCallback) locationCallback);
}
}
private String getCityName(Context context, double latitude, double longitude) {
android.location.Geocoder geocoder = new android.location.Geocoder(context, Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
if (addresses != null && !addresses.isEmpty()) {
return addresses.get(0).getLocality();
}
} catch (IOException e) {
Log.e(TAG, "地理编码失败", e);
}
return "未知城市";
}
}

View File

@@ -0,0 +1,65 @@
package com.xscm.moduleutil.utils.location;
import android.content.Context;
import android.os.AsyncTask;
import com.alibaba.fastjson.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class IpLocationProvider implements LocationProvider {
@Override
public void getLastKnownLocation(Context context, LocationCallback callback) {
new FetchIpLocationTask(callback).execute();
}
@Override
public void requestLocationUpdates(Context context, LocationCallback callback) {
getLastKnownLocation(context, callback); // 单次定位即可
}
@Override
public void stopLocationUpdates() {}
private static class FetchIpLocationTask extends AsyncTask<Void, Void, String> {
private final LocationCallback callback;
FetchIpLocationTask(LocationCallback callback) {
this.callback = callback;
}
@Override
protected String doInBackground(Void... voids) {
try {
URL url = new URL("https://ip-api.com/json/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder json = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
json.append(line);
}
JSONObject obj = new JSONObject(Boolean.parseBoolean(json.toString()));
return obj.getString("city");
} catch (Exception e) {
return null;
}
}
@Override
protected void onPostExecute(String city) {
if (city != null && !city.isEmpty()) {
callback.onLocationReceived(0, 0, city);
} else {
callback.onFailed("IP 定位失败");
}
}
}
}

View File

@@ -0,0 +1,21 @@
package com.xscm.moduleutil.utils.location;
import android.content.Context;
public interface LocationProvider {
void getLastKnownLocation(Context context, LocationCallback callback);
void requestLocationUpdates(Context context, LocationCallback callback);
void stopLocationUpdates();
interface LocationCallback {
void onLocationReceived(double latitude, double longitude, String city);
void onFailed(String errorMessage);
}
// interface LocationCallback {
// void onLocationReceived(double latitude, double longitude, String city);
// void onFailed(String errorMessage);
// }
}

View File

@@ -0,0 +1,24 @@
package com.xscm.moduleutil.utils.location;
import android.content.Context;
public class LocationServiceFactory {
public static LocationProvider createBestProvider(Context context) {
if (false) {
return new GmsLocationProvider(context);
} else {
return new SystemLocationProvider();
}
}
private static boolean isGooglePlayServicesAvailable(Context context) {
// 实现判断逻辑,例如使用 GoogleApiAvailability
// 或者简单尝试加载类是否存在
try {
Class.forName("com.google.android.gms.common.GoogleApiAvailability");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}

View File

@@ -0,0 +1,258 @@
package com.xscm.moduleutil.utils.location;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import com.blankj.utilcode.util.ToastUtils;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class SystemLocationProvider implements LocationProvider {
private LocationManager locationManager;
public void getLastKnownLocation(@NonNull Context context, @NonNull LocationCallback callback) {
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (locationManager == null) {
callback.onFailed("无法获取定位服务");
return;
}
Log.d("LocationDebug", "LocationManager 初始化成功");
try {
boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
Log.d("LocationDebug", "GPS Enabled: " + isGpsEnabled);
Log.d("LocationDebug", "Network Enabled: " + isNetworkEnabled);
if (!isGpsEnabled && !isNetworkEnabled) {
callback.onFailed("GPS 和 网络定位均未启用");
return;
}
final Handler handler = new Handler(Looper.getMainLooper());
Runnable timeout = () -> callback.onFailed("定位请求超时");
handler.postDelayed(timeout, 15000); // 15秒超时
LocationListener listener = new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
handler.removeCallbacks(timeout);
String city = getCityName(context, location.getLatitude(), location.getLongitude());
callback.onLocationReceived(location.getLatitude(), location.getLongitude(), city);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d("LocationDebug", "onStatusChanged: " + provider + ", status: " + status);
}
@Override
public void onProviderEnabled(@NonNull String provider) {
Log.d("LocationDebug", "onProviderEnabled: " + provider);
}
@Override
public void onProviderDisabled(@NonNull String provider) {
Log.d("LocationDebug", "onProviderDisabled: " + provider);
fallbackToNetwork(callback, context);
}
};
if (isNetworkEnabled) {
Log.d("LocationDebug", "尝试使用 NETWORK 定位");
locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, listener, Looper.getMainLooper());
}
else if (isGpsEnabled) {
Log.d("LocationDebug", "尝试使用 GPS 定位");
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, listener, Looper.getMainLooper());
}
} catch (SecurityException e) {
Log.e("LocationDebug", "缺少定位权限", e);
callback.onFailed("缺少定位权限:" + e.getMessage());
}
}
// @Override
// public void getLastKnownLocation(@NonNull Context context, @NonNull LocationCallback callback) {
// locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
// if (locationManager == null) {
// callback.onFailed("无法获取定位服务");
// return;
// }
//
// try {
// if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
// locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, new LocationListener() {
// @Override
// public void onLocationChanged(@NonNull Location location) {
// String city = getCityName(context, location.getLatitude(), location.getLongitude());
// callback.onLocationReceived(location.getLatitude(), location.getLongitude(), city);
// }
//
// @Override
// public void onStatusChanged(String provider, int status, Bundle extras) {
// ToastUtils.showShort(provider);
// }
//
// @Override
// public void onProviderEnabled(@NonNull String provider) {
// ToastUtils.showShort(provider);
// }
//
// @Override
// public void onProviderDisabled(@NonNull String provider) {
// fallbackToNetwork(callback, context);
// }
// }, Looper.getMainLooper());
// } else if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
// locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, new LocationListener() {
// @Override
// public void onLocationChanged(@NonNull Location location) {
// String city = getCityName(context, location.getLatitude(), location.getLongitude());
// callback.onLocationReceived(location.getLatitude(), location.getLongitude(), city);
// }
//
// @Override
// public void onStatusChanged(String provider, int status, Bundle extras) {
// ToastUtils.showShort(provider);
// }
//
// @Override
// public void onProviderEnabled(@NonNull String provider) {
// ToastUtils.showShort(provider);
// }
//
// @Override
// public void onProviderDisabled(@NonNull String provider) {
// callback.onFailed("网络定位不可用");
// }
// }, Looper.getMainLooper());
// } else {
// callback.onFailed("GPS 和 网络定位均未启用");
// }
// } catch (SecurityException e) {
// callback.onFailed("缺少定位权限:" + e.getMessage());
// }
// }
private void fallbackToNetwork(LocationCallback callback, Context context) {
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
String city = getCityName(context, location.getLatitude(), location.getLongitude());
callback.onLocationReceived(location.getLatitude(), location.getLongitude(), city);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
ToastUtils.showShort(provider);
}
@Override
public void onProviderEnabled(@NonNull String provider) {
ToastUtils.showShort(provider);
}
@Override
public void onProviderDisabled(@NonNull String provider) {
callback.onFailed("网络定位不可用");
}
}, Looper.getMainLooper());
} else {
callback.onFailed("GPS 不可用且网络定位也未启用");
}
}
@Override
public void requestLocationUpdates(Context context, LocationCallback callback) {
// 可扩展为持续监听
}
@Override
public void stopLocationUpdates() {
// 可扩展为停止监听
}
private String getCityName(Context context, double latitude, double longitude) {
android.location.Geocoder geocoder = new android.location.Geocoder(context, Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
if (addresses != null && !addresses.isEmpty()) {
return addresses.get(0).getAdminArea() + "," + addresses.get(0).getLocality()+ "," + addresses.get(0).getSubLocality();
}
} catch (IOException e) {
e.printStackTrace();
}
return "未知城市";
}
public void useNetworkLocation(Context context, LocationCallback callback) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (locationManager == null) {
callback.onFailed("无法获取定位服务");
return;
}
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
callback.onFailed("缺少定位权限");
return;
}
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
String city = getCityName(context, location.getLatitude(), location.getLongitude());
callback.onLocationReceived(location.getLatitude(), location.getLongitude(), city);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
ToastUtils.showShort(provider);
}
@Override
public void onProviderEnabled(@NonNull String provider) {
ToastUtils.showShort(provider);
}
@Override
public void onProviderDisabled(@NonNull String provider) {
callback.onFailed("网络定位不可用");
}
}, Looper.getMainLooper());
} else {
callback.onFailed("网络定位未启用");
}
}
}

View File

@@ -0,0 +1,206 @@
package com.xscm.moduleutil.utils.logger;
import androidx.annotation.Nullable;
/**
* SCore
* Created by ShangChuanliang
* on 2017/10/12.
*/
public final class DataLogger implements DataLoggingInterceptor.Logger {
private final StringBuilder mMessage = new StringBuilder();
public static class LogAdapter extends com.orhanobut.logger.AndroidLogAdapter {
private final boolean mDebuggable;
public LogAdapter(boolean debuggable) {
super();
mDebuggable = debuggable;
}
@Override
public boolean isLoggable(int priority, @Nullable String tag) {
// return super.isLoggable(priority, tag);
return mDebuggable;
}
}
public static class LogUtil {
public static void init(boolean debuggable) {
com.orhanobut.logger.Logger.addLogAdapter(new LogAdapter(debuggable));
}
public static void d(String message) {
com.orhanobut.logger.Logger.d(message);
}
public static void i(String message) {
com.orhanobut.logger.Logger.i(message);
}
public static void w(String message, Throwable e) {
String info = e != null ? e.toString() : "null";
com.orhanobut.logger.Logger.w(message + "" + info);
}
public static void e(String message, Throwable e) {
com.orhanobut.logger.Logger.e(e, message);
}
public static void json(String json) {
com.orhanobut.logger.Logger.json(json);
}
}
@Override
public void log(String message) {
// 请求或者响应开始
if (message.startsWith(DataLoggingInterceptor.sLogStartFlag)) {
mMessage.setLength(0);
return;
}
// 响应结束,打印整条日志
if (message.startsWith(DataLoggingInterceptor.sLogEndFlag)) {
LogUtil.d(mMessage.toString());
return;
}
// 以{}或者[]形式的说明是响应结果的json数据需要进行格式化
if ((message.startsWith("{") && message.endsWith("}"))
|| (message.startsWith("[") && message.endsWith("]"))) {
message = formatJson(decodeUnicode(message));
}
// 追加消息
try { mMessage.append(message.concat("\n"));
} catch (Exception ignored) {}
}
@Override
public void reset() {
mMessage.setLength(0);
}
private static String formatJson(String jsonStr) {
if (null == jsonStr || "".equals(jsonStr)) return "";
StringBuilder sb = new StringBuilder();
char last = '\0';
char current = '\0';
int indent = 0;
for (int i = 0; i < jsonStr.length(); i++) {
last = current;
current = jsonStr.charAt(i);
//遇到{ [换行,且下一行缩进
switch (current) {
case '{':
case '[':
sb.append(current);
sb.append('\n');
indent++;
addIndentBlank(sb, indent);
break;
//遇到} ]换行,当前行缩进
case '}':
case ']':
sb.append('\n');
indent--;
addIndentBlank(sb, indent);
sb.append(current);
break;
//遇到,换行
case ',':
sb.append(current);
if (last != '\\') {
sb.append('\n');
addIndentBlank(sb, indent);
}
break;
default:
sb.append(current);
}
}
return sb.toString();
}
/**
* 添加space
*
* @param sb
* @param indent
*/
private static void addIndentBlank(StringBuilder sb, int indent) {
for (int i = 0; i < indent; i++) {
sb.append('\t');
}
}
/**
* http 请求数据返回 json 中中文字符为 unicode 编码转汉字转码
*
* @param theString
* @return 转化后的结果.
*/
private static String decodeUnicode(String theString) {
char aChar;
int len = theString.length();
StringBuilder outBuffer = new StringBuilder(len);
for (int x = 0; x < len; ) {
aChar = theString.charAt(x++);
if (aChar == '\\') {
aChar = theString.charAt(x++);
if (aChar == 'u') {
int value = 0;
for (int i = 0; i < 4; i++) {
aChar = theString.charAt(x++);
switch (aChar) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
value = (value << 4) + aChar - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
value = (value << 4) + 10 + aChar - 'a';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
value = (value << 4) + 10 + aChar - 'A';
break;
default:
throw new IllegalArgumentException(
"Malformed \\uxxxx encoding.");
}
}
outBuffer.append((char) value);
} else {
if (aChar == 't')
aChar = '\t';
else if (aChar == 'r')
aChar = '\r';
else if (aChar == 'n')
aChar = '\n';
else if (aChar == 'f')
aChar = '\f';
outBuffer.append(aChar);
}
} else
outBuffer.append(aChar);
}
return outBuffer.toString();
}
}

View File

@@ -0,0 +1,215 @@
package com.xscm.moduleutil.utils.logger;
import androidx.annotation.NonNull;
import org.jetbrains.annotations.NotNull;
import java.io.EOFException;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import okhttp3.Connection;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.http.HttpHeaders;
import okio.Buffer;
import okio.BufferedSource;
/**
* SCore
* Created by ShangChuanliang
* on 2017/12/21.
*/
public class DataLoggingInterceptor implements Interceptor {
private static final String sFormatLine =
"===========================================================================================";
public static final String sLogStartFlag = "==scliang==log==start==";
public static final String sLogEndFlag = "==scliang==log==end==";
private static final Charset UTF8 = StandardCharsets.UTF_8;
public interface Logger {
void reset();
void log(String message);
}
public DataLoggingInterceptor(Logger logger) {
this.logger = logger;
}
private final Logger logger;
@NotNull
@Override public Response intercept(@NonNull Chain chain) throws IOException {
Request request = chain.request();
logger.reset();
logger.log(sLogStartFlag);
logger.log(sFormatLine);
RequestBody requestBody = request.body();
boolean hasRequestBody = requestBody != null;
Connection connection = chain.connection();
Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
String requestStartMessage = request.method() + " " + request.url() + " " + protocol;
logger.log(requestStartMessage);
if (hasRequestBody) {
// Request body headers are only present when installed as a network interceptor. Force
// them to be included (when available) so there values are known.
if (requestBody.contentType() != null) {
logger.log("Content-Type: " + requestBody.contentType());
}
if (requestBody.contentLength() != -1) {
logger.log("Content-Length: " + requestBody.contentLength());
}
}
Headers rHeaders = request.headers();
for (int i = 0, count = rHeaders.size(); i < count; i++) {
String name = rHeaders.name(i);
// Skip headers from the request body as they are explicitly logged above.
if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
logger.log(name + ": " + rHeaders.value(i));
}
}
if (!hasRequestBody) {
logger.log("END " + request.method());
} else if (bodyEncoded(request.headers())) {
logger.log("END " + request.method() + " (encoded body omitted)");
} else {
Buffer buffer = new Buffer();
requestBody.writeTo(buffer);
Charset charset = UTF8;
MediaType contentType = requestBody.contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
if (charset != null) {
logger.log(sFormatLine);
if (isPlaintext(buffer)) {
try {
String requestStr = URLDecoder.decode(buffer.readString(charset), "UTF-8");
String[] strs = requestStr.split("&");
for (String str : strs) {
logger.log(str);
}
} catch (Exception e) {
logger.log(buffer.readString(charset));
}
logger.log("END " + request.method()
+ " (" + requestBody.contentLength() + "-byte body)");
} else {
logger.log("END " + request.method() + " (binary "
+ requestBody.contentLength() + "-byte body omitted)");
}
}
}
logger.log(sFormatLine);
long startNs = System.nanoTime();
Response response;
try {
response = chain.proceed(request);
} catch (Exception e) {
logger.log("HTTP FAILED: " + e);
logger.log(sLogEndFlag);
throw e;
}
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
ResponseBody responseBody = response.body();
if (responseBody != null) {
long contentLength = responseBody.contentLength();
String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length";
logger.log(response.code() + " " + response.message() + " "
+ response.request().url() + " (" + tookMs + "ms)");
Headers headers = response.headers();
for (int i = 0, count = headers.size(); i < count; i++) {
logger.log(headers.name(i) + ": " + headers.value(i));
}
if (!HttpHeaders.hasBody(response)) {
logger.log("END HTTP");
} else if (bodyEncoded(response.headers())) {
logger.log("END HTTP (encoded body omitted)");
} else {
BufferedSource source = responseBody.source();
if (source.isOpen()) {
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
Charset charset = UTF8;
MediaType contentType = responseBody.contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
if (!isPlaintext(buffer)) {
logger.log("END HTTP (binary " + buffer.size() + "-byte body omitted)");
logger.log(sFormatLine);
logger.log(sLogEndFlag);
return response;
}
if (contentLength != 0 && charset != null) {
logger.log(sFormatLine);
logger.log(buffer.clone().readString(charset));
}
logger.log("END HTTP (" + buffer.size() + "-byte body)");
} else {
logger.log("END HTTP");
}
}
}
logger.log(sFormatLine);
logger.log(sLogEndFlag);
return response;
}
/**
* Returns true if the body in question probably contains human readable text. Uses a small sample
* of code points to detect unicode control characters commonly used in binary file signatures.
*/
private static boolean isPlaintext(Buffer buffer) {
try {
Buffer prefix = new Buffer();
long byteCount = buffer.size() < 64 ? buffer.size() : 64;
buffer.copyTo(prefix, 0, byteCount);
for (int i = 0; i < 16; i++) {
if (prefix.exhausted()) {
break;
}
int codePoint = prefix.readUtf8CodePoint();
if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
return false;
}
}
return true;
} catch (EOFException e) {
return false; // Truncated UTF-8 sequence.
}
}
private boolean bodyEncoded(Headers headers) {
String contentEncoding = headers.get("Content-Encoding");
return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");
}
}

View File

@@ -0,0 +1,112 @@
package com.xscm.moduleutil.utils.logger;
import android.util.Log;
import java.lang.ref.SoftReference;
/**
* SCore
* Created by ShangChuanliang
* on 2017/9/29.
*/
public class Logger {
public interface OnLoggerListener {
void onLogI(String buildType, String tag, String msg);
void onLogD(String buildType, String tag, String msg);
void onLogE(String buildType, String tag, String msg);
void onLogV(String buildType, String tag, String msg);
void onLogW(String buildType, String tag, String msg);
}
private Logger() {}
private static SoftReference<OnLoggerListener> sOnLoggerListener;
private static final String Tag = "SLog";
private static String BuildType;
private static boolean IsRelease;
private static boolean IsBeta;
private static boolean Loggable;
public static void init(String buildType) {
BuildType = buildType;
IsRelease = "release".equalsIgnoreCase(BuildType);
IsBeta = "beta".equalsIgnoreCase(BuildType);
Loggable = !IsRelease;
}
public static void setOnLoggerListener(OnLoggerListener listener) {
sOnLoggerListener = new SoftReference<>(listener);
}
public static String getBuildType() {
return BuildType;
}
public static boolean isRelease() {
return IsRelease;
}
public static boolean isBeta() {
return IsBeta;
}
public static boolean isLoggable() {
return Loggable;
}
public static void i(String msg, Object... args) {
StringBuilder sb = new StringBuilder();
for (Object arg : args) if (arg != null) sb.append(";").append(arg);
callOnLoggerListener(1, BuildType, Tag, msg + sb.toString());
if (isLoggable()) Log.i(Tag, msg + sb.toString());
}
public static void d(String msg, Object... args) {
StringBuilder sb = new StringBuilder();
for (Object arg : args) if (arg != null) sb.append(";").append(arg);
callOnLoggerListener(2, BuildType, Tag, msg + sb.toString());
if (isLoggable()) Log.d(Tag, msg + sb.toString());
}
public static void e(String msg, Object... args) {
StringBuilder sb = new StringBuilder();
for (Object arg : args) if (arg != null) sb.append(";").append(arg);
callOnLoggerListener(3, BuildType, Tag, msg + sb.toString());
if (isLoggable()) Log.e(Tag, msg + sb.toString());
}
public static void v(String msg, Object... args) {
StringBuilder sb = new StringBuilder();
for (Object arg : args) if (arg != null) sb.append(";").append(arg);
callOnLoggerListener(4, BuildType, Tag, msg + sb.toString());
if (isLoggable()) Log.v(Tag, msg + sb.toString());
}
public static void w(String msg, Object... args) {
StringBuilder sb = new StringBuilder();
for (Object arg : args) if (arg != null) sb.append(";").append(arg);
callOnLoggerListener(5, BuildType, Tag, msg + sb.toString());
if (isLoggable()) Log.w(Tag, msg + sb.toString());
}
private static void callOnLoggerListener(int type, String buildType, String tag, String msg) {
if (sOnLoggerListener == null) {
return;
}
OnLoggerListener listener = sOnLoggerListener.get();
if (listener == null) {
return;
}
switch (type) {
case 1: listener.onLogI(buildType, tag, msg); break;
case 2: listener.onLogD(buildType, tag, msg); break;
case 3: listener.onLogE(buildType, tag, msg); break;
case 4: listener.onLogV(buildType, tag, msg); break;
case 5: listener.onLogW(buildType, tag, msg); break;
}
}
}

View File

@@ -0,0 +1,312 @@
package com.xscm.moduleutil.utils.oss;
import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.callback.OSSProgressCallback;
import com.alibaba.sdk.android.oss.common.OSSLog;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSPlainTextAKSKCredentialProvider;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.xscm.moduleutil.base.CommonAppContext;
import com.xscm.moduleutil.utils.Md5Utils;
import com.xscm.moduleutil.utils.logger.Logger;
import java.io.File;
/**
* Created by zjh on 2016/2/22.
*/
public class OSSOperUtils {
private static OSS oss;
private static OSSOperUtils utils;
/**
* GetObjectRequest get = new GetObjectRequest("duia-log", name);
* <p>
* String endpoint = "https://oss-cn-beijing.aliyuncs.com";
* <p>
* // 明文设置secret的方式建议只在测试时使用更多鉴权模式请参考后面的`访问控制`章节
* OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider("qgR150FXSbdnCi5e", "wi4jUJvFgKZXkPp63vCY8nA849GpLT");
* <p>
* OSS
* Access Key ID: LTAIdLLZpWaeXb6j
* Access Key Secret: rBUwiyKNk8ddRaJMDYBucrTrxIidgr
* AliYunOSSURLFile: zholiao.oss-cn-shenzhen.aliyuncs.com
*/
// 运行sample前需要配置以下字段为有效的值
private static final String endpoint = CommonAppContext.getInstance().getCurrentEnvironment().getOssEndPoint();
private static final String accessKeyId = CommonAppContext.getInstance().getCurrentEnvironment().getOssaAcessKeyId();
private static final String accessKeySecret = CommonAppContext.getInstance().getCurrentEnvironment().getOssAccessKeySecret();
private static final String bucketName = CommonAppContext.getInstance().getCurrentEnvironment().getOssBucketName();
public static final String AliYunOSSURLFile = CommonAppContext.getInstance().getCurrentEnvironment().getOssBaseUrl();
public static final String img = "img/";
public static final String video = "video/";
public static final String audio = "audio/";
/**
* 文件
*
* @param file
* @param type 0 图片 1音频 2视频
* @return
*/
public static String getPath(File file, int type) {
String fileMD5 = Md5Utils.getFileMD5(file);
String suffix = "";
if (file.getName().contains(".")) {
suffix = file.getName().substring(file.getName().lastIndexOf("."));
}
if (type == 0) {
return img + fileMD5 + suffix;
} else if (type == 1) {
return audio + fileMD5 + suffix;
} else {
return video + fileMD5 + suffix;
}
}
public static OSSOperUtils newInstance() {
if (null == utils) {
utils = new OSSOperUtils();
}
if (null == oss) {
OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider(accessKeyId, accessKeySecret);
ClientConfiguration conf = new ClientConfiguration();
conf.setConnectionTimeout(150 * 1000); // 连接超时默认15秒
conf.setSocketTimeout(150 * 1000); // socket超时默认15秒
conf.setMaxConcurrentRequest(5); // 最大并发请求书默认5个
conf.setMaxErrorRetry(2); // 失败后最大重试次数默认2次
OSSLog.enableLog();
oss = new OSSClient(CommonAppContext.getInstance(), endpoint, credentialProvider, conf);
}
return utils;
}
//上传
public OSSAsyncTask putObjectMethod(String uploadObject, String uploadFilePath, OssCallback ossCallback) {
PutObjectSamples put = new PutObjectSamples(oss, bucketName, uploadObject, uploadFilePath);
return put.asyncPutObjectFromLocalFile(new OSSProgressCallback<PutObjectRequest>() {
@Override
public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
}
}, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
if (ossCallback != null) {
ossCallback.onSuccess();
}
}
});
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
if (ossCallback != null) {
ossCallback.onFail();
}
}
});
}
});
}
//上传
public OSSAsyncTask putObjectMethod(String uploadObject, String uploadFilePath, OSSProgressCallback mossProgressCallback, OSSCompletedCallback mcompletedCallback) {
PutObjectSamples put = new PutObjectSamples(oss, bucketName, uploadObject, uploadFilePath);
return put.asyncPutObjectFromLocalFile(mossProgressCallback, mcompletedCallback);
}
//判断文件是否存在
public String fileExist(String fileName) {
try {
boolean exist = oss.doesObjectExist(bucketName, fileName);
Logger.e(bucketName, fileName, exist);
if (exist) {
//加个参数去缓存
return String.format("%s/%s?v=1", AliYunOSSURLFile, fileName);
}
} catch (ClientException e) {
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
}
return null;
}
public interface OssCallback {
void onSuccess();
void onFail();
}
/**
* 发布动态上传图片或者视频
*
* @param file
* @param type 0 img 1 audio 2 video
*/
public void uploadImageOrVideo(File file, int type, UploadCallback uploadCallback) {
uploadCallback.startUpload();
String objectKey = getPath(file, type);
long size;
size = FileUtils.getFileLength(file.getPath());
if (-1 == size) { //文件不存在
uploadCallback.uploadFailed();
return;
}
boolean exist;
try {
exist = oss.doesObjectExist(bucketName, objectKey);
String format = String.format("%s%s", AliYunOSSURLFile, objectKey);
if (false) { //Oss服务器文件存在
uploadCallback.onProgress(size, size);
uploadCallback.uploadEnd(format);
} else { //文件不存在
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectKey, file.getAbsolutePath());
putObjectRequest.setProgressCallback((request, currentSize, totalSize) -> {
ThreadUtils.runOnUiThread(() -> uploadCallback.onProgress(currentSize, totalSize));
});
oss.asyncPutObject(putObjectRequest, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
ThreadUtils.runOnUiThread(() -> uploadCallback.uploadEnd(format));
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
ThreadUtils.runOnUiThread(uploadCallback::uploadFailed);
clientException.printStackTrace();
serviceException.printStackTrace();
}
});
}
} catch (ClientException | ServiceException e) {
e.printStackTrace();
uploadCallback.uploadFailed();
}
}
/**
* 发布动态上传图片或者视频
*
* @param file
* @param type 0 img 1 audio 2 video
*/
public String uploadImageOrVideo(File file, int type) {
String objectKey = getPath(file, type);
long size;
size = FileUtils.getFileLength(file.getPath());
if (-1 == size) {
return null;
}
try {
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectKey, file.getAbsolutePath());
putObjectRequest.setProgressCallback((request, currentSize, totalSize) -> {});
oss.putObject(putObjectRequest);
return String.format("%s%s", AliYunOSSURLFile, objectKey);
} catch (ClientException | ServiceException e) {
e.printStackTrace();
return null;
}
}
/**
* 发布动态上传封面用
*
* @param bytes
* @param uploadCallback
*/
public void uploadBitmap(byte[] bytes, UploadCallback uploadCallback) {
uploadCallback.startUpload();
int size = bytes.length;
String md5 = Md5Utils.getMD5String(bytes);
String objectKey = img + md5 + ".jpg";
boolean exist;
try {
exist = oss.doesObjectExist(bucketName, objectKey);
String format = String.format("%s%s", AliYunOSSURLFile, objectKey);
if (false) { //Oss服务器文件存在
uploadCallback.onProgress(size, size);
uploadCallback.uploadEnd(format);
} else { //文件不存在
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectKey, bytes);
putObjectRequest.setProgressCallback((request, currentSize, totalSize) -> {
ThreadUtils.runOnUiThread(() -> uploadCallback.onProgress(currentSize, totalSize));
});
oss.asyncPutObject(putObjectRequest, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
ThreadUtils.runOnUiThread(() -> uploadCallback.uploadEnd(format));
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
ThreadUtils.runOnUiThread(uploadCallback::uploadFailed);
clientException.printStackTrace();
serviceException.printStackTrace();
}
});
}
} catch (ClientException | ServiceException e) {
e.printStackTrace();
}
}
/**
* 发布动态上传封面用
*
* @param bytes
*/
public String uploadBitmap(byte[] bytes) {
String md5 = Md5Utils.getMD5String(bytes);
String objectKey = img + md5 + ".jpg";
try {
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectKey, bytes);
putObjectRequest.setProgressCallback((request, currentSize, totalSize) -> {
});
oss.putObject(putObjectRequest);
return String.format("%s%s", AliYunOSSURLFile, objectKey);
} catch (ClientException | ServiceException e) {
e.printStackTrace();
return null;
}
}
/**
* 上传进度条回调
*/
public interface UploadCallback {
void startUpload();
void onProgress(long currentSize, long totalSize);
void uploadEnd(String url);
void uploadFailed();
}
}

View File

@@ -0,0 +1,67 @@
package com.xscm.moduleutil.utils.oss;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.callback.OSSProgressCallback;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
/**
* Created by zhouzhuo on 12/3/15.
*/
public class PutObjectSamples {
private OSS oss;
private String testBucket;
private String testObject;
private String uploadFilePath;
public PutObjectSamples(OSS client, String testBucket, String testObject, String uploadFilePath) {
this.oss = client;
this.testBucket = testBucket;
this.testObject = testObject;
this.uploadFilePath = uploadFilePath;
}
// 从本地文件上传,使用非阻塞的异步接口
public OSSAsyncTask asyncPutObjectFromLocalFile(final OSSProgressCallback<PutObjectRequest> mossProgressCallback, final OSSCompletedCallback<PutObjectRequest, PutObjectResult> mcompletedCallback) {
// 构造上传请求
PutObjectRequest put = new PutObjectRequest(testBucket, testObject, uploadFilePath);
// 异步上传时可以设置进度回调
put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
@Override
public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
if (mossProgressCallback != null) {
mossProgressCallback.onProgress(request, currentSize, totalSize);
}
}
});
OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
@Override
public void onSuccess(PutObjectRequest request, PutObjectResult result) {
if (mcompletedCallback != null) {
mcompletedCallback.onSuccess(request, result);
}
}
@Override
public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
// 请求异常
if (clientExcepion != null) {
// 本地异常如网络异常等
clientExcepion.printStackTrace();
}
if (mcompletedCallback != null) {
mcompletedCallback.onFailure(request, clientExcepion, serviceException);
}
}
});
return task;
}
}

View File

@@ -0,0 +1,172 @@
package com.xscm.moduleutil.utils.permission;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.core.app.AppOpsManagerCompat;
import androidx.core.content.ContextCompat;
import com.blankj.utilcode.util.AppUtils;
import com.xscm.moduleutil.utils.permission.rom.HuaweiUtils;
import com.xscm.moduleutil.utils.permission.rom.MeizuUtils;
import com.xscm.moduleutil.utils.permission.rom.MiuiUtils;
import com.xscm.moduleutil.utils.permission.rom.OppoUtils;
import com.xscm.moduleutil.utils.permission.rom.QikuUtils;
import com.xscm.moduleutil.utils.permission.rom.RomUtils;
import com.xscm.moduleutil.widget.dialog.CommonDialog;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* Created by liyong on 2018/9/21.
*/
public class PermissionUtils {
public static final String TAG = "PermissionUtils";
public static void showDenied(Context context, String msg, CommonDialog.OnClickListener listener) {
CommonDialog commonDialog = new CommonDialog(context);
commonDialog.setContent(msg);
commonDialog.setmOnClickListener(listener);
commonDialog.show();
}
public static void showDenied(Context context, String msg) {
CommonDialog commonDialog = new CommonDialog(context);
commonDialog.setContent(msg);
commonDialog.setmOnClickListener(new CommonDialog.OnClickListener() {
@Override
public void onLeftClick() {
}
@Override
public void onRightClick() {
AppUtils.launchAppDetailsSettings();
}
});
commonDialog.show();
}
/**
* 检查悬浮窗权限
*
* @param context
* @return
*/
public boolean checkFloatWindowPermission(Context context) {
//6.0 版本之后由于 google 增加了对悬浮窗权限的管理,所以方式就统一了
if (Build.VERSION.SDK_INT < 23) {
if (RomUtils.checkIsMiuiRom()) {
return MiuiUtils.checkFloatWindowPermission(context);
} else if (RomUtils.checkIsMeizuRom()) {
return MeizuUtils.checkFloatWindowPermission(context);
} else if (RomUtils.checkIsHuaweiRom()) {
return HuaweiUtils.checkFloatWindowPermission(context);
} else if (RomUtils.checkIs360Rom()) {
return QikuUtils.checkFloatWindowPermission(context);
} else if (RomUtils.checkIsOppoRom()) {
return OppoUtils.checkFloatWindowPermission(context);
}
}
return commonROMPermissionCheck(context);
}
public static boolean hasPermission(@NonNull Context context, @NonNull String permission) {
List<String> permisstions = new ArrayList<>();
permisstions.add(permission);
return hasPermission(context, permisstions);
}
/**
* 系统层的权限判断
*
* @param context 上下文
* @param permissions 申请的权限 Manifest.permission.READ_CONTACTS
* @return 是否有权限 :其中有一个获取不了就是失败了
*/
public static boolean hasPermission(@NonNull Context context, @NonNull List<String> permissions) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
for (String permission : permissions) {
try {
String op = AppOpsManagerCompat.permissionToOp(permission);
if (TextUtils.isEmpty(op)) continue;
int result = AppOpsManagerCompat.noteOp(context, op, android.os.Process.myUid(), context.getPackageName());
if (result == AppOpsManagerCompat.MODE_IGNORED) return false;
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
String ops = AppOpsManager.permissionToOp(permission);
int locationOp = appOpsManager.checkOp(ops, Binder.getCallingUid(), context.getPackageName());
if (locationOp == AppOpsManager.MODE_IGNORED) return false;
result = ContextCompat.checkSelfPermission(context, permission);
if (result != PackageManager.PERMISSION_GRANTED) return false;
} catch (Exception ex) {
Log.e(TAG, "[hasPermission] error ", ex);
}
}
return true;
}
/**
* 跳转到权限设置界面
*
* @param context
*/
public static void toPermissionSetting(Context context) throws NoSuchFieldException, IllegalAccessException {
if (Build.VERSION.SDK_INT < 23) {
if (RomUtils.checkIsMiuiRom()) {
MiuiUtils.applyMiuiPermission(context);
} else if (RomUtils.checkIsMeizuRom()) {
MeizuUtils.applyPermission(context);
} else if (RomUtils.checkIsHuaweiRom()) {
HuaweiUtils.applyPermission(context);
} else if (RomUtils.checkIs360Rom()) {
QikuUtils.applyPermission(context);
} else if (RomUtils.checkIsOppoRom()) {
OppoUtils.applyOppoPermission(context);
} else {
RomUtils.getAppDetailSettingIntent(context);
}
} else {
if (RomUtils.checkIsMeizuRom()) {
MeizuUtils.applyPermission(context);
} else {
if (RomUtils.checkIsOppoRom() || RomUtils.checkIsVivoRom()
|| RomUtils.checkIsHuaweiRom() || RomUtils.checkIsSamsunRom()) {
RomUtils.getAppDetailSettingIntent(context);
} else if (RomUtils.checkIsMiuiRom()) {
MiuiUtils.toPermisstionSetting(context);
} else {
RomUtils.commonROMPermissionApplyInternal(context);
}
}
}
}
private static boolean commonROMPermissionCheck(Context context) {
//最新发现魅族6.0的系统这种方式不好用,天杀的,只有你是奇葩,没办法,单独适配一下
if (RomUtils.checkIsMeizuRom()) {
return MeizuUtils.checkFloatWindowPermission(context);
} else {
Boolean result = true;
if (Build.VERSION.SDK_INT >= 23) {
try {
Class clazz = Settings.class;
Method canDrawOverlays = clazz.getDeclaredMethod("canDrawOverlays", Context.class);
result = (Boolean) canDrawOverlays.invoke(null, context);
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
return result;
}
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.xscm.moduleutil.utils.permission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
import java.lang.reflect.Method;
public class HuaweiUtils {
private static final String TAG = "HuaweiUtils";
/**
* 检测 Huawei 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
}
return true;
}
/**
* 去华为权限申请页面
*/
public static void applyPermission(Context context) {
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// ComponentName comp = new ComponentName("com.huawei.systemmanager","com.huawei.permissionmanager.ui.MainActivity");//华为权限管理
// ComponentName comp = new ComponentName("com.huawei.systemmanager",
// "com.huawei.permissionmanager.ui.SingleAppActivity");//华为权限管理跳转到指定app的权限管理位置需要华为接口权限未解决
ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity");//悬浮窗管理页面
intent.setComponent(comp);
if (RomUtils.getEmuiVersion() == 3.1) {
//emui 3.1 的适配
context.startActivity(intent);
} else {
//emui 3.0 的适配
comp = new ComponentName("com.huawei.systemmanager", "com.huawei.notificationmanager.ui.NotificationManagmentActivity");//悬浮窗管理页面
intent.setComponent(comp);
context.startActivity(intent);
}
} catch (SecurityException e) {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// ComponentName comp = new ComponentName("com.huawei.systemmanager","com.huawei.permissionmanager.ui.MainActivity");//华为权限管理
ComponentName comp = new ComponentName("com.huawei.systemmanager",
"com.huawei.permissionmanager.ui.MainActivity");//华为权限管理跳转到本app的权限管理页面,这个需要华为接口权限,未解决
// ComponentName comp = new ComponentName("com.huawei.systemmanager","com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity");//悬浮窗管理页面
intent.setComponent(comp);
context.startActivity(intent);
Log.e(TAG, Log.getStackTraceString(e));
} catch (ActivityNotFoundException e) {
/**
* 手机管家版本较低 HUAWEI SC-UL10
*/
// Toast.makeText(MainActivity.this, "act找不到", Toast.LENGTH_LONG).show();
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName comp = new ComponentName("com.Android.settings", "com.android.settings.permission.TabItem");//权限管理页面 android4.4
// ComponentName comp = new ComponentName("com.android.settings","com.android.settings.permission.single_app_activity");//此处可跳转到指定app对应的权限管理页面但是需要相关权限未解决
intent.setComponent(comp);
context.startActivity(intent);
Log.e(TAG, Log.getStackTraceString(e));
} catch (Exception e) {
//抛出异常时提示信息
Toast.makeText(context, "进入设置页面失败,请手动设置", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
//com.android.packageinstaller/.permission.ui.ManagePermissionsActivity
public static void toPermisstionSetting(Context context) {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("android.intent.action.MANAGE_APP_PERMISSIONS");
ComponentName comp = new ComponentName("com.android.packageinstaller", "com.android.packageinstaller.permission.ui.ManagePermissionsActivity");
intent.setComponent(comp);
context.startActivity(intent);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e(TAG, "Below API 19 cannot invoke!");
}
return false;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.xscm.moduleutil.utils.permission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Method;
public class MeizuUtils {
private static final String TAG = "MeizuUtils";
/**
* 检测 meizu 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
}
return true;
}
/**
* 去魅族权限申请页面
*/
public static void applyPermission(Context context) {
try {
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
// intent.setClassName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity");//remove this line code for fix flyme6.3
intent.putExtra("packageName", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} catch (Exception e) {
try {
Log.e(TAG, "获取悬浮窗权限, 打开AppSecActivity失败, " + Log.getStackTraceString(e));
// 最新的魅族flyme 6.2.5 用上述方法获取权限失败, 不过又可以用下述方法获取权限了
RomUtils.commonROMPermissionApplyInternal(context);
} catch (Exception eFinal) {
Log.e(TAG, "获取悬浮窗权限失败, 通用获取方法失败, " + Log.getStackTraceString(eFinal));
}
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e(TAG, "Below API 19 cannot invoke!");
}
return false;
}
}

View File

@@ -0,0 +1,214 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.xscm.moduleutil.utils.permission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import java.lang.reflect.Method;
public class MiuiUtils {
private static final String TAG = "MiuiUtils";
/**
* 获取小米 rom 版本号,获取失败返回 -1
*
* @return miui rom version code, if fail , return -1
*/
public static int getMiuiVersion() {
String version = RomUtils.getSystemProperty("ro.miui.ui.version.name");
if (version != null) {
try {
return Integer.parseInt(version.substring(1));
} catch (Exception e) {
Log.e(TAG, "get miui version code error, version : " + version);
Log.e(TAG, Log.getStackTraceString(e));
}
}
return -1;
}
/**
* 检测 miui 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
} else {
// if ((context.getApplicationInfo().flags & 1 << 27) == 1) {
// return true;
// } else {
// return false;
// }
return true;
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e(TAG, "Below API 19 cannot invoke!");
}
return false;
}
/**
* 小米 ROM 权限申请
*/
public static void applyMiuiPermission(Context context) {
int versionCode = getMiuiVersion();
if (versionCode == 5) {
goToMiuiPermissionActivity_V5(context);
} else if (versionCode == 6) {
goToMiuiPermissionActivity_V6(context);
} else if (versionCode == 7) {
goToMiuiPermissionActivity_V7(context);
} else if (versionCode == 8) {
goToMiuiPermissionActivity_V8(context);
} else {
Log.e(TAG, "this is a special MIUI rom version, its version code " + versionCode);
}
}
private static boolean isIntentAvailable(Intent intent, Context context) {
if (intent == null) {
return false;
}
return context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
/**
* 小米 V5 版本 ROM权限申请
*/
public static void goToMiuiPermissionActivity_V5(Context context) {
Intent intent = null;
String packageName = context.getPackageName();
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", packageName, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "intent is not available!");
}
//设置页面在应用详情页面
// Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
// PackageInfo pInfo = null;
// try {
// pInfo = context.getPackageManager().getPackageInfo
// (HostInterfaceManager.getHostInterface().getApp().getPackageName(), 0);
// } catch (PackageManager.NameNotFoundException e) {
// AVLogger.e(TAG, e.getMessage());
// }
// intent.setClassName("com.android.settings", "com.miui.securitycenter.permission.AppPermissionsEditor");
// intent.putExtra("extra_package_uid", pInfo.applicationInfo.uid);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// if (isIntentAvailable(intent, context)) {
// context.startActivity(intent);
// } else {
// AVLogger.e(TAG, "Intent is not available!");
// }
}
/**
* 小米 V6 版本 ROM权限申请
*/
public static void goToMiuiPermissionActivity_V6(Context context) {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "Intent is not available!");
}
}
/**
* 小米 V7 版本 ROM权限申请
*/
public static void goToMiuiPermissionActivity_V7(Context context) {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "Intent is not available!");
}
}
/**
* 小米 V8 版本 ROM权限申请
*/
public static void goToMiuiPermissionActivity_V8(Context context) {
Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
// intent.setPackage("com.miui.securitycenter");
intent.putExtra("extra_pkgname", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setPackage("com.miui.securitycenter");
intent.putExtra("extra_pkgname", context.getPackageName());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "Intent is not available!");
}
}
}
public static void toPermisstionSetting(Context context) throws NoSuchFieldException, IllegalAccessException {
int rom = getMiuiVersion();
Intent intent = null;
if (5 == rom) {
Uri packageURI = Uri.parse("package:" + context.getApplicationInfo().packageName);
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
} else if (rom == 6 || rom == 7) {
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", context.getPackageName());
} else if (rom == 8 || rom == 9) {
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
intent.putExtra("extra_pkgname", context.getPackageName());
} else {
RomUtils.commonROMPermissionApplyInternal(context);
return;
}
context.startActivity(intent);
}
}

View File

@@ -0,0 +1,70 @@
package com.xscm.moduleutil.utils.permission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Method;
/**
* Description:
*
* @author Shawn_Dut
* @since 2018-02-01
*/
public class OppoUtils {
private static final String TAG = "OppoUtils";
/**
* 检测 360 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
}
return true;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int) method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e(TAG, "Below API 19 cannot invoke!");
}
return false;
}
/**
* oppo ROM 权限申请
*/
public static void applyOppoPermission(Context context) {
//merge request from https://github.com/zhaozepeng/FloatWindowPermission/pull/26
try {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//com.coloros.safecenter/.sysfloatwindow.FloatWindowListActivity
ComponentName comp = new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.sysfloatwindow.FloatWindowListActivity");//悬浮窗管理页面
intent.setComponent(comp);
context.startActivity(intent);
}
catch(Exception e){
Log.e(TAG, "",e);
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.xscm.moduleutil.utils.permission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Method;
public class QikuUtils {
private static final String TAG = "QikuUtils";
/**
* 检测 360 悬浮窗权限
*/
public static boolean checkFloatWindowPermission(Context context) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
return checkOp(context, 24); //OP_SYSTEM_ALERT_WINDOW = 24;
}
return true;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static boolean checkOp(Context context, int op) {
final int version = Build.VERSION.SDK_INT;
if (version >= 19) {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
Class clazz = AppOpsManager.class;
Method method = clazz.getDeclaredMethod("checkOp", int.class, int.class, String.class);
return AppOpsManager.MODE_ALLOWED == (int)method.invoke(manager, op, Binder.getCallingUid(), context.getPackageName());
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} else {
Log.e("", "Below API 19 cannot invoke!");
}
return false;
}
/**
* 去360权限申请页面
*/
public static void applyPermission(Context context) {
Intent intent = new Intent();
intent.setClassName("com.android.settings", "com.android.settings.Settings$OverlaySettingsActivity");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
intent.setClassName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.AppEnterActivity");
if (isIntentAvailable(intent, context)) {
context.startActivity(intent);
} else {
Log.e(TAG, "can't open permission page with particular name, please use " +
"\"adb shell dumpsys activity\" command and tell me the name of the float window permission page");
}
}
}
private static boolean isIntentAvailable(Intent intent, Context context) {
if (intent == null) {
return false;
}
return context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
}

View File

@@ -0,0 +1,187 @@
/*
* Copyright (C) 2016 Facishare Technology Co., Ltd. All Rights Reserved.
*/
package com.xscm.moduleutil.utils.permission.rom;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
/**
* Description:
*
* @author zhaozp
* @since 2016-05-23
*/
public class RomUtils {
private static final String TAG = "RomUtils";
/**
* 获取 emui 版本号
*
* @return
*/
public static double getEmuiVersion() {
try {
String emuiVersion = getSystemProperty("ro.build.version.emui");
String version = emuiVersion.substring(emuiVersion.indexOf("_") + 1);
return Double.parseDouble(version);
} catch (Exception e) {
Log.e(TAG, "", e);
}
return 4.0;
}
/**
* 获取小米 rom 版本号,获取失败返回 -1
*
* @return miui rom version code, if fail , return -1
*/
public static int getMiuiVersion() {
String version = getSystemProperty("ro.miui.ui.version.name");
if (version != null) {
try {
return Integer.parseInt(version.substring(1));
} catch (Exception e) {
Log.e(TAG, "get miui version code error, version : " + version);
}
}
return -1;
}
public static String getSystemProperty(String propName) {
String line;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop " + propName);
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (IOException ex) {
Log.e(TAG, "Unable to read sysprop " + propName, ex);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
Log.e(TAG, "Exception while closing InputStream", e);
}
}
}
return line;
}
public static boolean checkIsHuaweiRom() {
return Build.MANUFACTURER.contains("HUAWEI");
}
/**
* check if is miui ROM
*/
public static boolean checkIsMiuiRom() {
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.name"));
}
public static boolean checkIsMeizuRom() {
//return Build.MANUFACTURER.contains("Meizu");
String meizuFlymeOSFlag = getSystemProperty("ro.build.display.id");
if (TextUtils.isEmpty(meizuFlymeOSFlag)) {
return false;
} else if (meizuFlymeOSFlag.contains("flyme") || meizuFlymeOSFlag.toLowerCase().contains("flyme")) {
return true;
} else {
return false;
}
}
public static boolean checkIs360Rom() {
//fix issue https://github.com/zhaozepeng/FloatWindowPermission/issues/9
return Build.MANUFACTURER.contains("QiKU")
|| Build.MANUFACTURER.contains("360");
}
public static boolean checkIsOppoRom() {
//https://github.com/zhaozepeng/FloatWindowPermission/pull/26
return Build.MANUFACTURER.contains("OPPO") || Build.MANUFACTURER.contains("oppo");
}
public static boolean checkIsVivoRom() {
return Build.MANUFACTURER.contains("vivo") || Build.MANUFACTURER.contains("VIVO");
}
public static boolean checkIsSamsunRom() {
return Build.MANUFACTURER.contains("samsung");
}
/**
* 判断小米MIUI系统中授权管理中对应的权限授取
*
* @return false 存在核心的未收取的权限 true 核心权限已经全部授权
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public static boolean hasMiuiPermission(Context context) {
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int locationOp = appOpsManager.checkOp(AppOpsManager.OPSTR_FINE_LOCATION, Binder.getCallingUid(), context.getPackageName());
if (locationOp == AppOpsManager.MODE_IGNORED) {
return false;
}
return true;
}
public static void commonROMPermissionApplyInternal(Context context) throws NoSuchFieldException, IllegalAccessException {
Class clazz = Settings.class;
Field field = clazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION");
Intent intent = new Intent(field.get(null).toString());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);
}
/**
* 跳转到权限设置界面
*/
public static void getAppDetailSettingIntent(Context context) {
// vivo 点击设置图标>加速白名单>我的app
// 点击软件管理>软件管理权限>软件>我的app>信任该软件
Intent appIntent = context.getPackageManager().getLaunchIntentForPackage("com.iqoo.secure");
if (appIntent != null) {
context.startActivity(appIntent);
return;
}
// oppo 点击设置图标>应用权限管理>按应用程序管理>我的app>我信任该应用
// 点击权限隐私>自启动管理>我的app
appIntent = context.getPackageManager().getLaunchIntentForPackage("com.oppo.safe");
if (appIntent != null) {
context.startActivity(appIntent);
return;
}
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
intent.setAction(Intent.ACTION_VIEW);
intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
intent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName());
}
context.startActivity(intent);
}
}

View File

@@ -0,0 +1,195 @@
package com.xscm.moduleutil.utils.wx;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import com.xscm.moduleutil.base.CommonAppContext;
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX;
import com.tencent.mm.opensdk.modelmsg.WXImageObject;
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage;
import com.tencent.mm.opensdk.modelmsg.WXMiniProgramObject;
import com.tencent.mm.opensdk.modelmsg.WXTextObject;
import com.tencent.mm.opensdk.modelmsg.WXWebpageObject;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import java.io.ByteArrayOutputStream;
// todo 微信分享工具类
public class WeChatShareUtils {
// private static final int TIMELINE_SUPPORTED_VERSION = 0x21020001; // 微信4.2以上支持
private static final int TIMELINE_SUPPORTED_VERSION = 0x27000D00; // 判断微信版本是否为7.0.13及以上
private static final String id = "xxxxxx"; //小程序原始id
private static final String pageUrl = "xxxxxx"; //兼容低版本的网页链接
//IWXAPI是第三方app和微信通信的openapi接口
private IWXAPI api;
private Context context;
public static WeChatShareUtils weChatShareUtils;
public static WeChatShareUtils getInstance(Context context){
if(weChatShareUtils ==null){
weChatShareUtils = new WeChatShareUtils();
}
if(weChatShareUtils.api !=null){
weChatShareUtils.api.unregisterApp();;
}
weChatShareUtils.context = context;
weChatShareUtils.regToWx();
return weChatShareUtils;
}
// todo 注册应用id到微信
private void regToWx(){
//通过WXAPIFactory工厂获取IWXAPI的实例
api = WXAPIFactory.createWXAPI(context, CommonAppContext.getInstance().getCurrentEnvironment().getWxAppId(),true);
//将应用的appId注册到微信
api.registerApp(CommonAppContext.getInstance().getCurrentEnvironment().getWxAppId());
}
/**
*todo 分享文字到朋友圈或者好友
* @param text 文本内容
* @param scene 分享方式:好友还是朋友圈
* @return
*/
public boolean shareText(String text,int scene){
//初始化一个WXTextObject对象填写分享的文本对象
WXTextObject textObject = new WXTextObject();
textObject.text = text;
return share(textObject,text,scene);
}
/**
* todo 分享图片到朋友圈或者好友
* @param bmp 图片的Bitmap对象
* @param scene 分享方式:好友 WXSceneSession 还是朋友圈 WXSceneTimeline,收藏 WXSceneFavorite
* @return
*/
public boolean sharePic(Bitmap bmp, int scene){
//初始化一个WXImageObject对象
WXImageObject imageObject = new WXImageObject();
//设置缩略图
Bitmap thump = Bitmap.createScaledBitmap(bmp,300,300,true);
bmp.recycle();
return share(imageObject,thump,scene);
}
/**
* todo 分享网页到朋友圈或者好友,视频和音乐的分享和网页大同小异,只是创建的对象不同。
* @param url 网页的url
* @param title 显示分享网页的标题
* @param thumb 图片的缩略图
* @param description 对网页的描述
* @param scene 分享方式:好友还是朋友圈
* @return
*/
public boolean shareUrl(String url, String title, Bitmap thumb, String description, int scene) {
//初试话一个WXWebpageObject对象填写url
WXWebpageObject webPage = new WXWebpageObject();
webPage.webpageUrl = url;
//设置缩略图
Bitmap tmb = Bitmap.createScaledBitmap(thumb,150,150,true);
thumb.recycle();
return share(webPage, title, tmb, description, scene);
}
/**
* todo 分享小程序类型
* @param url
* @param title
* @param thumb
* @param description
* @param scene 只支持分享给微信好友
* @return
*/
public boolean shareMiniProgram(String url, String title, Bitmap thumb, String description, int scene) {
//初试话一个WXMiniProgramObject对象填写url
WXMiniProgramObject wxMiniProgramObject = new WXMiniProgramObject();
wxMiniProgramObject.webpageUrl = pageUrl; //兼容低版本的网页链接
wxMiniProgramObject.miniprogramType = WXMiniProgramObject.MINIPROGRAM_TYPE_TEST; //小程序类型,测试版
wxMiniProgramObject.userName = id; //小程序原始id
wxMiniProgramObject.path = url; //小程序的path
//设置缩略图
Bitmap tmb = Bitmap.createScaledBitmap(thumb,300,300,true);
thumb.recycle();
return share(wxMiniProgramObject, title, tmb, description, scene);
}
private boolean share(WXMediaMessage.IMediaObject mediaObject, Bitmap thumb, int scene) {
return share(mediaObject, null, thumb, null, scene);
}
private boolean share(WXMediaMessage.IMediaObject mediaObject, String description, int scene) {
return share(mediaObject, null, null, description, scene);
}
private boolean share(WXMediaMessage.IMediaObject mediaObject,String title,Bitmap thumb,String description, int scene){
WXMediaMessage msg = new WXMediaMessage(mediaObject);
if(title !=null){
msg.title = title;
}
if(description !=null){
msg.description = description;
}
if(thumb !=null){
msg.thumbData = bmpToByteArray(thumb, true);
}
//构造一个Req
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = String.valueOf(System.currentTimeMillis());
req.message = msg;
req.scene = scene;
return api.sendReq(req);
}
//判断是否支持转发到朋友圈
//微信4.2以上支持如果需要检查微信版本支持API的情况 可调用IWXAPI的getWXAppSupportAPI方法,0x21020001及以上支持发送朋友圈
//微信版本:当且仅当通过 IWXAPI.getWXAppSupportAPI() 接口获取到的值 >= 0x27000D00(7.0.13以上才能支持FileProvider的方式进行分享。
public boolean isSupportWX(){
int wxSdkVersion = api.getWXAppSupportAPI();
return wxSdkVersion >= TIMELINE_SUPPORTED_VERSION;
}
// todo Bitmap转换为 byte数组
private byte[] bmpToByteArray(final Bitmap bmp,final boolean needRecycle){
int i;
int j;
if (bmp.getHeight() > bmp.getWidth()) {
i = bmp.getWidth();
j = bmp.getWidth();
} else {
i = bmp.getHeight();
j = bmp.getHeight();
}
Bitmap localBitmap = Bitmap.createBitmap(i, j, Bitmap.Config.RGB_565);
Canvas localCanvas = new Canvas(localBitmap);
while ( true) {
localCanvas.drawBitmap(bmp, new Rect(0, 0, i, j), new Rect(0, 0,i, j), null);
if (needRecycle)
bmp.recycle();
ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();
localBitmap.compress(Bitmap.CompressFormat.JPEG, 100,
localByteArrayOutputStream);
localBitmap.recycle();
byte[] arrayOfByte = localByteArrayOutputStream.toByteArray();
try {
localByteArrayOutputStream.close();
return arrayOfByte;
} catch (Exception e) {
// F.out(e);
}
i = bmp.getHeight();
j = bmp.getHeight();
}
}
}