diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..e4801e66 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.sh text eol=lf +*.command text eol=lf +*.bat text eol=crlf \ No newline at end of file diff --git a/README.md b/README.md index 9d48ea6e..5da3fd1c 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,8 @@ * 嵌套滚动布局框架:[NestedScrollLayout](https://github.com/getActivity/NestedScrollLayout) ![](https://img.shields.io/github/stars/getActivity/NestedScrollLayout.svg) ![](https://img.shields.io/github/forks/getActivity/NestedScrollLayout.svg) +* Android 命令行工具集:[AndroidCmdTools](https://github.com/getActivity/AndroidCmdTools) ![](https://img.shields.io/github/stars/getActivity/AndroidCmdTools.svg) ![](https://img.shields.io/github/forks/getActivity/AndroidCmdTools.svg) + * Android 版本适配:[AndroidVersionAdapter](https://github.com/getActivity/AndroidVersionAdapter) ![](https://img.shields.io/github/stars/getActivity/AndroidVersionAdapter.svg) ![](https://img.shields.io/github/forks/getActivity/AndroidVersionAdapter.svg) * Android 代码规范:[AndroidCodeStandard](https://github.com/getActivity/AndroidCodeStandard) ![](https://img.shields.io/github/stars/getActivity/AndroidCodeStandard.svg) ![](https://img.shields.io/github/forks/getActivity/AndroidCodeStandard.svg) diff --git a/app/src/main/java/com/hjq/demo/app/AppActivity.java b/app/src/main/java/com/hjq/demo/app/AppActivity.java index 53b7db67..a18e74b1 100644 --- a/app/src/main/java/com/hjq/demo/app/AppActivity.java +++ b/app/src/main/java/com/hjq/demo/app/AppActivity.java @@ -174,13 +174,20 @@ public ImmersionBar getStatusBarConfig() { */ @NonNull protected ImmersionBar createStatusBarConfig() { - return ImmersionBar.with(this) - // 默认状态栏字体颜色为黑色 - .statusBarDarkFont(isStatusBarDarkFont()) - // 指定导航栏背景颜色 - .navigationBarColor(R.color.white) - // 状态栏字体和导航栏内容自动变色,必须指定状态栏颜色和导航栏颜色才可以自动变色 - .autoDarkModeEnable(true, 0.2f); + ImmersionBar immersionBar = ImmersionBar.with(this) + // 默认状态栏字体颜色为黑色 + .statusBarDarkFont(isStatusBarDarkFont()) + // 状态栏字体和导航栏内容自动变色,必须指定状态栏颜色和导航栏颜色才可以自动变色 + .autoDarkModeEnable(true, 0.2f); + // 适配 Android 15 EdgeToEdge 特性 + if (AndroidVersion.isAndroid15()) { + // 设置透明的导航栏 + immersionBar.transparentNavigationBar(); + } else { + // 指定导航栏背景颜色 + immersionBar.navigationBarColor(R.color.white); + } + return immersionBar; } /** diff --git a/app/src/main/java/com/hjq/demo/app/TitleBarFragment.java b/app/src/main/java/com/hjq/demo/app/TitleBarFragment.java index 7f6212ff..c9750146 100644 --- a/app/src/main/java/com/hjq/demo/app/TitleBarFragment.java +++ b/app/src/main/java/com/hjq/demo/app/TitleBarFragment.java @@ -109,13 +109,20 @@ protected ImmersionBar getStatusBarConfig() { */ @NonNull protected ImmersionBar createStatusBarConfig() { - return ImmersionBar.with(this) - // 默认状态栏字体颜色为黑色 - .statusBarDarkFont(isStatusBarDarkFont()) - // 指定导航栏背景颜色 - .navigationBarColor(R.color.white) - // 状态栏字体和导航栏内容自动变色,必须指定状态栏颜色和导航栏颜色才可以自动变色 - .autoDarkModeEnable(true, 0.2f); + ImmersionBar immersionBar = ImmersionBar.with(this) + // 默认状态栏字体颜色为黑色 + .statusBarDarkFont(isStatusBarDarkFont()) + // 状态栏字体和导航栏内容自动变色,必须指定状态栏颜色和导航栏颜色才可以自动变色 + .autoDarkModeEnable(true, 0.2f); + // 适配 Android 15 EdgeToEdge 特性 + if (AndroidVersion.isAndroid15()) { + // 设置透明的导航栏 + immersionBar.transparentNavigationBar(); + } else { + // 指定导航栏背景颜色 + immersionBar.navigationBarColor(R.color.white); + } + return immersionBar; } /** diff --git a/app/src/main/java/com/hjq/demo/http/model/RequestHandler.java b/app/src/main/java/com/hjq/demo/http/model/RequestHandler.java index 9ee53b00..4dfb9c91 100644 --- a/app/src/main/java/com/hjq/demo/http/model/RequestHandler.java +++ b/app/src/main/java/com/hjq/demo/http/model/RequestHandler.java @@ -174,7 +174,8 @@ public Throwable requestFail(@NonNull HttpRequest httpRequest, @NonNull Throw return new CancelException(mApplication.getString(R.string.http_request_cancel), throwable); } - return new HttpException(throwable.getMessage(), throwable); + String message = throwable.getMessage(); + return new HttpException(message != null ? message : "", throwable); } @NonNull diff --git a/app/src/main/java/com/hjq/demo/http/model/RequestServer.java b/app/src/main/java/com/hjq/demo/http/model/RequestServer.java index 9195ab8b..34811a8f 100644 --- a/app/src/main/java/com/hjq/demo/http/model/RequestServer.java +++ b/app/src/main/java/com/hjq/demo/http/model/RequestServer.java @@ -2,7 +2,7 @@ import androidx.annotation.NonNull; import com.hjq.demo.other.AppConfig; -import com.hjq.http.config.IHttpPostBodyStrategy; +import com.hjq.http.config.IHttpBodyStrategy; import com.hjq.http.config.IRequestServer; import com.hjq.http.model.RequestBodyType; @@ -22,7 +22,7 @@ public String getHost() { @NonNull @Override - public IHttpPostBodyStrategy getBodyType() { + public IHttpBodyStrategy getBodyType() { // 以表单的形式提交参数 return RequestBodyType.FORM; } diff --git a/app/src/main/java/com/hjq/demo/manager/InitManager.java b/app/src/main/java/com/hjq/demo/manager/InitManager.java index f77e1951..afc49584 100644 --- a/app/src/main/java/com/hjq/demo/manager/InitManager.java +++ b/app/src/main/java/com/hjq/demo/manager/InitManager.java @@ -7,6 +7,7 @@ import android.net.ConnectivityManager; import android.net.Network; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; @@ -29,7 +30,7 @@ import com.hjq.demo.other.ToastInterceptor; import com.hjq.demo.other.ToastStyle; import com.hjq.gson.factory.GsonFactory; -import com.hjq.gson.factory.ParseExceptionCallback; +import com.hjq.gson.factory.OnParseExceptionCallback; import com.hjq.http.EasyConfig; import com.hjq.http.config.IRequestInterceptor; import com.hjq.http.model.HttpHeaders; @@ -162,20 +163,20 @@ public void interceptArguments(@NonNull HttpRequest httpRequest, .into(); // 设置 Json 解析容错监听 - GsonFactory.setParseExceptionCallback(new ParseExceptionCallback() { + GsonFactory.setOnParseExceptionCallback(new OnParseExceptionCallback() { @Override - public void onParseObjectException(TypeToken typeToken, String fieldName, JsonToken jsonToken) { + public void onParseObjectException(@NonNull TypeToken typeToken, @Nullable String fieldName, @Nullable JsonToken jsonToken) { handlerGsonParseException("解析对象析异常:" + typeToken + "#" + fieldName + ",后台返回的类型为:" + jsonToken); } @Override - public void onParseListItemException(TypeToken typeToken, String fieldName, JsonToken listItemJsonToken) { + public void onParseListItemException(@NonNull TypeToken typeToken, @Nullable String fieldName, @Nullable JsonToken listItemJsonToken) { handlerGsonParseException("解析 List 异常:" + typeToken + "#" + fieldName + ",后台返回的条目类型为:" + listItemJsonToken); } @Override - public void onParseMapItemException(TypeToken typeToken, String fieldName, String mapItemKey, JsonToken mapItemJsonToken) { + public void onParseMapItemException(@NonNull TypeToken typeToken, @Nullable String fieldName, @Nullable String mapItemKey, @Nullable JsonToken mapItemJsonToken) { handlerGsonParseException("解析 Map 异常:" + typeToken + "#" + fieldName + ",mapItemKey = " + mapItemKey + ",后台返回的条目类型为:" + mapItemJsonToken); } diff --git a/app/src/main/java/com/hjq/demo/permission/PermissionDescription.java b/app/src/main/java/com/hjq/demo/permission/PermissionDescription.java index abaf5681..8f2a40a8 100644 --- a/app/src/main/java/com/hjq/demo/permission/PermissionDescription.java +++ b/app/src/main/java/com/hjq/demo/permission/PermissionDescription.java @@ -5,9 +5,6 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.Point; -import android.os.Handler; -import android.os.Looper; -import android.os.SystemClock; import android.util.DisplayMetrics; import android.view.Display; import android.view.Gravity; @@ -22,6 +19,7 @@ import com.hjq.permissions.OnPermissionDescription; import com.hjq.permissions.permission.PermissionPageType; import com.hjq.permissions.permission.base.IPermission; +import com.hjq.permissions.tools.PermissionTaskHandler; import java.util.List; /** @@ -32,9 +30,6 @@ */ public final class PermissionDescription implements OnPermissionDescription { - /** 消息处理 Handler 对象 */ - public static final Handler HANDLER = new Handler(Looper.getMainLooper()); - /** 权限请求描述弹窗显示类型:Dialog */ private static final int DESCRIPTION_WINDOW_TYPE_DIALOG = 0; /** 权限请求描述弹窗显示类型:PopupWindow */ @@ -103,13 +98,13 @@ public void onRequestPermissionStart(@NonNull Activity activity, @NonNull List requestList) { // 移除跟这个 Token 有关但是没有还没有执行的消息 - HANDLER.removeCallbacksAndMessages(mHandlerToken); + PermissionTaskHandler.cancelTask(mHandlerToken); // 销毁当前正在显示的弹窗 dismissPopupWindow(); dismissDialog(); diff --git a/app/src/main/java/com/hjq/demo/permission/PermissionInterceptor.java b/app/src/main/java/com/hjq/demo/permission/PermissionInterceptor.java index 00c97f21..00a59889 100644 --- a/app/src/main/java/com/hjq/demo/permission/PermissionInterceptor.java +++ b/app/src/main/java/com/hjq/demo/permission/PermissionInterceptor.java @@ -33,7 +33,7 @@ public void onRequestPermissionEnd(@NonNull Activity activity, boolean skipReque @NonNull List deniedList, @Nullable OnPermissionCallback callback) { if (callback != null) { - callback.onResult(grantedList, deniedList); + callback.onPermissionResult(grantedList, deniedList); } if (deniedList.isEmpty()) { @@ -80,7 +80,7 @@ private void showPermissionSettingDialog(@NonNull Activity activity, return; } // 用户全部授权了,回调成功给外层监听器,免得用户还要再发起权限申请 - callback.onResult(requestList, latestDeniedList); + callback.onPermissionResult(requestList, latestDeniedList); }); }) .show(); diff --git a/app/src/main/java/com/hjq/demo/ui/activity/SplashActivity.java b/app/src/main/java/com/hjq/demo/ui/activity/SplashActivity.java index 2e1078e6..8e6f3fd1 100644 --- a/app/src/main/java/com/hjq/demo/ui/activity/SplashActivity.java +++ b/app/src/main/java/com/hjq/demo/ui/activity/SplashActivity.java @@ -33,7 +33,7 @@ public final class SplashActivity extends AppActivity { private LottieAnimationView mLottieView; - private SlantedTextView mDebugView; + private SlantedTextView mBuildTypeView; @Override protected int getLayoutId() { @@ -43,7 +43,7 @@ protected int getLayoutId() { @Override protected void initView() { mLottieView = findViewById(R.id.lav_splash_lottie); - mDebugView = findViewById(R.id.iv_splash_debug); + mBuildTypeView = findViewById(R.id.iv_splash_build_type); // 设置动画监听 mLottieView.addAnimatorListener(new AnimatorListenerAdapter() { @@ -78,11 +78,11 @@ public void onCancel(@NonNull BaseDialog dialog) { @Override protected void initData() { - mDebugView.setText(AppConfig.getBuildType().toUpperCase()); if (AppConfig.isDebug()) { - mDebugView.setVisibility(View.VISIBLE); + mBuildTypeView.setVisibility(View.VISIBLE); + mBuildTypeView.setText(AppConfig.getBuildType().toUpperCase()); } else { - mDebugView.setVisibility(View.INVISIBLE); + mBuildTypeView.setVisibility(View.INVISIBLE); } if (true) { diff --git a/app/src/main/java/com/hjq/demo/ui/adapter/StatusAdapter.java b/app/src/main/java/com/hjq/demo/ui/adapter/StatusAdapter.java index 624a9312..1b78005b 100644 --- a/app/src/main/java/com/hjq/demo/ui/adapter/StatusAdapter.java +++ b/app/src/main/java/com/hjq/demo/ui/adapter/StatusAdapter.java @@ -1,7 +1,6 @@ package com.hjq.demo.ui.adapter; import android.content.Context; -import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; @@ -38,13 +37,6 @@ private ViewHolder() { @Override public void onBindView(int position) { mTextView.setText(getItem(position)); - getItemView().setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - removeItem(position); - return false; - } - }); } } } \ No newline at end of file diff --git a/app/src/main/java/com/hjq/demo/ui/fragment/home/HomeMineFragment.java b/app/src/main/java/com/hjq/demo/ui/fragment/home/HomeMineFragment.java index 604c35b7..887d2638 100644 --- a/app/src/main/java/com/hjq/demo/ui/fragment/home/HomeMineFragment.java +++ b/app/src/main/java/com/hjq/demo/ui/fragment/home/HomeMineFragment.java @@ -189,8 +189,8 @@ public void onCancel() { } new VideoPlayActivity.Builder() - .setVideoTitle("速度与激情特别行动") - .setVideoSource("http://vfx.mtime.cn/Video/2019/06/29/mp4/190629004821240734.mp4") + .setVideoTitle("动物世界") + .setVideoSource("http://vjs.zencdn.net/v/oceans.mp4") .setActivityOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) .start(activity); diff --git a/app/src/main/res-common/layout/widget_player_view.xml b/app/src/main/res-common/layout/widget_player_view.xml index b3b1dc35..54d454ab 100644 --- a/app/src/main/res-common/layout/widget_player_view.xml +++ b/app/src/main/res-common/layout/widget_player_view.xml @@ -16,7 +16,6 @@ - + android:fitsSystemWindows="true"> + + + @@ -125,7 +131,7 @@ android:id="@+id/tv_player_view_total_time" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingHorizontal="@dimen/dp_5" + android:layout_marginEnd="@dimen/dp_15" android:textColor="@color/white" android:textSize="@dimen/sp_14" tools:text="10:00" /> diff --git a/app/src/main/res-common/raw/province.json b/app/src/main/res-common/raw/province.json index 96bba259..d7be929f 100644 --- a/app/src/main/res-common/raw/province.json +++ b/app/src/main/res-common/raw/province.json @@ -5092,6 +5092,7 @@ "岳普湖县", "伽师县", "巴楚县", + "岑岭县", "塔什库尔干塔吉克自治县" ] }, @@ -5105,7 +5106,9 @@ "洛浦县", "策勒县", "于田县", - "民丰县" + "民丰县", + "和康县", + "和安县" ] }, { @@ -5288,6 +5291,30 @@ "一三一团", "一三七团" ] + }, + { + "name": "新星市", + "area": [ + "新星市核心区", + "二道湖镇", + "骆驿镇", + "黄田镇" + ] + }, + { + "name": "白杨市", + "area": [ + "一六一团小白杨镇", + "一六三团富兴镇镇", + "一六四团金玉", + "一六五团锦绣镇" + ] + }, + { + "name": "草湖市", + "area": [ + "草湖镇" + ] } ] }, diff --git a/app/src/main/res/layout/splash_activity.xml b/app/src/main/res/layout/splash_activity.xml index 9fb07ea9..64e2fd7b 100644 --- a/app/src/main/res/layout/splash_activity.xml +++ b/app/src/main/res/layout/splash_activity.xml @@ -19,7 +19,7 @@ app:lottie_rawRes="@raw/welcome" />