Commit 522dad58 authored by fengruiyu's avatar fengruiyu

修改项目

parent dc4c934e
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
......@@ -14,15 +18,22 @@ android {
//flavorDimensions "default"
buildConfigField ("boolean","IS_DEV","false")
//多个dex
multiDexEnabled true
}
dataBinding {
enabled true
buildFeatures{
dataBinding = true
// for view binding :
viewBinding = true
}
compileOptions {
sourceCompatibility rootProject.ext.java_version["compileJavaVersion"]
targetCompatibility rootProject.ext.java_version["targetJavaVersion"]
}
// buildTypes {
// debug {
// minifyEnabled false
......@@ -71,4 +82,5 @@ dependencies {
api project(':library_base')
}
\ No newline at end of file
......@@ -3,13 +3,14 @@
package="com.mints.goodnews">
<application
android:name=".AppApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<activity android:name=".main.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
......
package com.mints.goodnews
import android.os.StrictMode
import android.os.StrictMode.VmPolicy
import android.util.Log
import com.fry.base.base.BaseApp
import java.util.concurrent.TimeoutException
/**
* Created by 冯瑞雨 on 2021/7/1.
*/
class AppApplication :BaseApp() {
override fun onCreate() {
super.onCreate()
val builder = VmPolicy.Builder()
StrictMode.setVmPolicy(builder.build())
builder.detectFileUriExposure()
// 解决java.util.concurrent.TimeoutException https://www.jianshu.com/p/844ef9c84f15
val defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler { t, e ->
if (t.name == "FinalizerWatchdogDaemon" && e is TimeoutException) {
Log.e("ignore", "ignore")
} else {
defaultUncaughtExceptionHandler?.uncaughtException(t, e)
}
}
}
}
\ No newline at end of file
package com.mints.goodnews;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
\ No newline at end of file
package com.mints.goodnews.main
import android.os.Bundle
import com.fry.base.base.BaseActivity
import com.mints.goodnews.BR
import com.mints.goodnews.R
import com.mints.goodnews.databinding.ActivityMainBinding
class MainActivity : BaseActivity<ActivityMainBinding,MainViewModel>() {
override fun initContentView(savedInstanceState: Bundle?) = R.layout.activity_main
override fun initVariableId() = BR.viewModel
override fun initData() {
super.initData()
//初始化底部Button
}
}
\ No newline at end of file
package com.mints.goodnews.main
import android.app.Application
import me.goldze.mvvmhabit.base.BaseViewModel
/**
* Created by 冯瑞雨 on 2021/7/1.
*/
class MainViewModel(application : Application) :BaseViewModel(application) {
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<layout>
<data>
<variable
name="viewModel"
type="com.mints.goodnews.main.MainViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".main.MainActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#6200EE</color>
<color name="colorPrimaryDark">#3700B3</color>
<color name="colorAccent">#03DAC5</color>
<color name="colorPrimary">#ffffffff</color>
<color name="colorPrimaryDark">#ffffffff</color>
<color name="colorAccent">#FF4081</color>
</resources>
\ No newline at end of file
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowIsTranslucent">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@color/appBackColor</item>
<item name="android:windowAnimationStyle">@style/animFade</item>
<!--全局默认竖屏-->
<item name="android:screenOrientation">portrait</item>
<item name="android:configChanges">
screenLayout|screenSize|smallestScreenSize|orientation|keyboardHidden
</item>
</style>
<!-- 界面切换动画 -->
<style name="animFade" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/slide_in_from_right</item>
<item name="android:activityOpenExitAnimation">@anim/slide_out_to_left</item>
<item name="android:activityCloseExitAnimation">@anim/slide_out_to_right</item>
<item name="android:activityCloseEnterAnimation">@anim/slide_in_from_left</item>
<!--<item name="android:windowEnterAnimation">@anim/slide_in_from_right</item>
<item name="android:windowExitAnimation">@anim/slide_out_to_right</item>-->
</style>
</resources>
\ No newline at end of file
......@@ -14,6 +14,7 @@ android {
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
flavorDimensions '23'
multiDexEnabled true
buildConfigField ("boolean","IS_DEV","false")
//从com.android.tools.build:gradle:4.1.0开始,build.gradle文件正式移除了versionName和versionCode,参照Android开发者官网。
......@@ -48,7 +49,6 @@ android {
// 设置Kotlin编译环境,不设置默认为1.6
jvmTarget = 1.8
}
buildTypes {
release {
minifyEnabled false
......@@ -71,8 +71,11 @@ android {
sourceCompatibility rootProject.ext.java_version["compileJavaVersion"]
targetCompatibility rootProject.ext.java_version["targetJavaVersion"]
}
dataBinding {
enabled true
buildFeatures{
dataBinding = true
// for view binding :
viewBinding = true
}
}
......
......@@ -45,12 +45,11 @@ dependencies {
//阿里路由框架
api rootProject.ext.dependencies["arouter-api"]
api 'androidx.multidex:multidex:2.0.1'
api rootProject.ext.dependencies["super-textview"]
//banner
api 'com.github.xiaohaibin:XBanner:1.7.4'
api rootProject.ext.dependencies["walle"]
......@@ -60,8 +59,7 @@ dependencies {
api rootProject.ext.dependencies["viewpager2"]
//裁剪图片
api 'com.github.yalantis:ucrop:2.2.5-native'
//时间选择器
api 'com.contrarywind:Android-PickerView:4.1.9'
// 依赖协程核心库
api rootProject.ext.kotlin["coroutine"]
api rootProject.ext.kotlin["coroutine-android"]
......
......@@ -19,10 +19,6 @@
<application>
<activity
android:name="com.fry.base.ui.activity.CommonWebViewActivity"
android:configChanges="screenLayout|screenSize|smallestScreenSize|orientation|keyboardHidden"
android:screenOrientation="portrait" />
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:configChanges="screenLayout|screenSize|smallestScreenSize|orientation|keyboardHidden"
......
......@@ -20,17 +20,16 @@ import static android.text.TextUtils.isEmpty;
public class BaseApp extends BaseApplication {
@Override
public void onCreate() {
initWebView();
super.onCreate();
boolean isMainProcess = AppUtils.isMainProcess(this);
//初始化组件(靠前)
ModuleLifecycleConfig.getInstance().initModuleAhead(this,isMainProcess);
WorkTaskManager.getInstance().addWorkEventTask(() ->
ModuleLifecycleConfig.getInstance().initModuleAsWork(BaseApp.this,isMainProcess));
//....
//初始化组件(靠后)
ModuleLifecycleConfig.getInstance().initModuleLow(this,isMainProcess);
// boolean isMainProcess = AppUtils.isMainProcess(this);
// //初始化组件(靠前)
// ModuleLifecycleConfig.getInstance().initModuleAhead(this,isMainProcess);
// //线程管理类
// WorkTaskManager.getInstance().addWorkEventTask(() ->
// ModuleLifecycleConfig.getInstance().initModuleAsWork(BaseApp.this,isMainProcess));
// //....
// //初始化组件(靠后)
// ModuleLifecycleConfig.getInstance().initModuleLow(this,isMainProcess);
}
......@@ -40,15 +39,4 @@ public class BaseApp extends BaseApplication {
MultiDex.install(base);
}
private void initWebView() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
String processName = AppUtils.getProcessName(this);
if (!"com.qjzn.ddg".equals(processName)) {
WebView.setDataDirectorySuffix(getString(processName, "d"));
}
}
}
public String getString(String s, String defValue) {
return isEmpty(s) ? defValue : s;
}
}
package com.fry.base.bean
import com.google.gson.annotations.SerializedName
/**
* @author 冯瑞雨
* @date 2020/3/15 13:12
*/
class ForwardConfigurationBean {
/**
* 是否转发售罄商品is_share_sellout0:不转发,1:转发
*/
@SerializedName("is_share_sellout")
var isShareSellout:Int? = null
/**
* 商品转发样式
* goods_banner_and_desc:拼图(商品首图+商品描述)
* four_goods_pic_and_desc:拼图(4张商品图+商品描述)
* more_goods_pic_and_desc:多图(默认复制商品描述)
*/
@SerializedName("goods_share_style")
var goodsShareStyle:String?=null
/**
* 全局加价设置加价类型number:数字,percent:百分比
*/
@SerializedName("global_add_price_setting_type")
var globalAddPriceSettingType:String?=null
/**
* 全局加价设置加价金额amount
*/
@SerializedName("global_add_price_setting_amount")
var globalAddPriceSettingAmount:String?=null
override fun toString(): String {
return "ForwardConfigurationBean(isShareSellout=$isShareSellout, goodsShareStyle=$goodsShareStyle, globalAddPriceSettingType=$globalAddPriceSettingType, globalAddPriceSettingAmount=$globalAddPriceSettingAmount)"
}
}
enum class ShareType(val type:String){
/***
* 拼图(商品首图+商品描述)
*/
GOODS_BANNER_AND_DESC("goods_banner_and_desc"),
/***
* 拼图(4张商品图+商品描述)
*/
FOUR_GOODS_PIC_AND_DESC("four_goods_pic_and_desc"),
/***
* 多图(默认复制商品描述)
*/
MORE_GOODS_PIC_AND_DESC("more_goods_pic_and_desc")
}
\ No newline at end of file
package com.fry.base.bean;
import java.util.List;
/**
* @author 冯瑞雨
* @date 2019/10/7 15:39
* Udesk客服 订单 或者 商品
*/
public class GoodsUdesk {
/**
* 图片
*/
private String imgUrl;
/**
* 名字
*/
private String name;
/**
* 客服人员查看的商品或者订单的详情
*/
private String url;
private List<ParamsBean> paramsBean;
public GoodsUdesk(){
}
public static class ParamsBean {
/**
* 名称
*/
private String textName;
/**
* 名称的颜色
*/
private String nameColor;
/**
* 是否粗体
*/
private boolean fold;
/**
* 是否换行
*/
private boolean nameBreaX;
/**
* 名称字体大小
*/
private int nameSize;
public ParamsBean(){
}
public ParamsBean(String textName, String nameColor, boolean fold, boolean nameBreaX, int nameSize) {
this.textName = textName;
this.nameColor = nameColor;
this.fold = fold;
this.nameBreaX = nameBreaX;
this.nameSize = nameSize;
}
public String getTextName() {
return textName;
}
public void setTextName(String textName) {
this.textName = textName;
}
public String getNameColor() {
return nameColor;
}
public void setNameColor(String nameColor) {
this.nameColor = nameColor;
}
public boolean isFold() {
return fold;
}
public void setFold(boolean fold) {
this.fold = fold;
}
public boolean isNameBreaX() {
return nameBreaX;
}
public void setNameBreaX(boolean nameBreaX) {
this.nameBreaX = nameBreaX;
}
public int getNameSize() {
return nameSize;
}
public void setNameSize(int nameSize) {
this.nameSize = nameSize;
}
}
public String getImgUrl() {
return imgUrl;
}
public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public List<ParamsBean> getParamsBean() {
return paramsBean;
}
public void setParamsBean(List<ParamsBean> paramsBean) {
this.paramsBean = paramsBean;
}
}
package com.fry.base.bean
import com.google.gson.annotations.SerializedName
import com.fry.base.annotation.Poko
import java.io.Serializable
/**
*@author Created by xiaohui.
*@email 1794833832@qq.com
*@ClassName PersonCenterBean
*@Description 用户信息的实例
*@date 2018/12/31
*/
@Poko
data class PersonCenterBean(
var id: Int,
var gid: Int,
var openid: String,
@SerializedName("username") var userName: Any,
var token: String,
var email: Any,
@SerializedName("nickname") var nickName: String,
var thumb: Any,
@SerializedName("user_money") var userMoney: String,
var points: Int,
var sex: String?,
var birthday: String,
var phone: Any,
var address: Any,
@SerializedName("shareurl") var shareUrl: String,
@SerializedName("last_ip") var lastIp: String,
@SerializedName("last_time") var lastTime: String,
var status: Int,
@SerializedName("created_at") var createdAt: String,
@SerializedName("updated_at") var updatedAt: String,
@SerializedName("unionid") var unionid: String,
@SerializedName("ware_openid") var wareOpenid: String,
var hxUname: String,
@SerializedName("easemob_username") var easemobUsername: String,
@SerializedName("easemob_password") var easemobPassword: String,
@SerializedName("member_id") var memberId: String,
@SerializedName("ddguser") var ddgUser: PersonDdguserBean
) : Serializable
\ No newline at end of file
package com.fry.base.bean
import com.google.gson.annotations.SerializedName
import com.fry.base.annotation.Poko
import java.io.Serializable
/**
*@author Created by xiaohui.
*@email 1794833832@qq.com
*@ClassName PersonDdguserBean
*@Description __
*@date 2019/1/4
*/
@Poko
data class PersonDdguserBean(
@SerializedName("id") var id: Int,
@SerializedName("uid") var uid: Int,
@SerializedName("status") var status: String,
@SerializedName("created_at") var createdAt: String,
@SerializedName("updated_at") var updatedAt: String,
@SerializedName("code") var code: String,
@SerializedName("code_status") var codeStatus: String
) : Serializable
\ No newline at end of file
package com.fry.base.bean
/**
*
* @author jeme
* @date 2020/3/7
*/
class UpgradeInfo(var title : String?
,var name : String?
,var content : String?
, var versionName : String?
,var v_code : String?
,var downloadUrl : String
,var apkMd5 : String?
,var isForce : Boolean) {
}
\ No newline at end of file
package com.fry.base.bean;
import com.google.gson.annotations.SerializedName;
/**
* 升级信息
* @author jeme
* @date 2019/10/13
*/
public class UpgradeInfoBean {
/***
* 下载地址
*/
@SerializedName("apk_url")
private String apkUrl;
/***
* 新版app版本号
*/
@SerializedName("app_version")
private String appVersion;
/***
* 升级级别:0.不提示不升级 | 1.不提示可升级 | 2.弹窗提示去升级 | 9.弹窗提示强制升级
*/
@SerializedName("upgrad_level")
private int upgradLevel;
/***
* 升级提示
*/
private String desc;
public String getApkUrl() {
return apkUrl;
}
public void setApkUrl(String apkUrl) {
this.apkUrl = apkUrl;
}
public String getAppVersion() {
return appVersion;
}
public void setAppVersion(String appVersion) {
this.appVersion = appVersion;
}
public int getUpgradLevel() {
return upgradLevel;
}
public void setUpgradLevel(int upgradLevel) {
this.upgradLevel = upgradLevel;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
package com.fry.base.binding.banner;
import androidx.databinding.BindingAdapter;
import android.view.View;
import android.widget.ImageView;
import com.stx.xhb.xbanner.XBanner;
import com.stx.xhb.xbanner.entity.SimpleBannerInfo;
import com.fry.base.utils.ImageLoader;
import java.util.List;
/**
* @author jeme
* @date 2019/9/17
*/
public final class ViewAdapter {
@BindingAdapter(value = {"bannerImgData","bannerCorner","bannerPlaceHolder","bannerScaleType"},requireAll = false)
public static void setBannerImgData(XBanner banner, List<SimpleBannerInfo>bannerImgData, final int bannerCorner,final int bannerPlaceHolder,final ImageView.ScaleType scaleType){
banner.loadImage(new XBanner.XBannerAdapter() {
@Override
public void loadBanner(XBanner banner, Object model, View view, int position) {
new ImageLoader.ImageBuilder().setCornerDp(bannerCorner)
.setPlaceHolder(bannerPlaceHolder)
.setUrl((String)bannerImgData.get(position).getXBannerUrl())
.setScaleType(scaleType)
.setTargetView((ImageView)view).start();
}
});
banner.setBannerData(bannerImgData);
}
}
......@@ -68,7 +68,6 @@ public class InitConstants {
public static String getVersionName() {
if (VERSION_NAME == null) {
return BuildConfig.VERSION_NAME;
return "";
}
return VERSION_NAME;
}
......
package com.fry.base.ui.activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.DownloadListener;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.fry.base.BR;
import com.fry.base.R;
import com.fry.base.databinding.CommonWebviewActivityBinding;
import com.fry.base.ui.widget.CommonTitleBar;
import com.fry.base.viewmodel.BaseWebViewModel;
import me.goldze.mvvmhabit.base.HabitBaseActivity;
import me.goldze.mvvmhabit.utils.KLog;
import static android.view.KeyEvent.KEYCODE_BACK;
/**
* Created by jeme on 2019/2/19
*/
public class CommonWebViewActivity extends HabitBaseActivity<CommonWebviewActivityBinding, BaseWebViewModel> {
public final static String BASE_URL = "loadUrl";
private WebSettings mWebSettings;
private String mUrl;
@Override
public int initContentView(Bundle savedInstanceState) {
return R.layout.common_webview_activity;
}
@Override
public int initVariableId() {
return BR.viewModel;
}
@Override
public void initData() {
super.initData();
mUrl = getIntent().getStringExtra(BASE_URL);
initWebView();
if(!TextUtils.isEmpty(mUrl)){
binding.webView.loadUrl(mUrl);
}
binding.ctbTitle.setClickListener(new CommonTitleBar.SampleClickListenerImpl(){
@Override
public void onBackClick(View view) {
finish();
}
});
}
private void initWebView() {
mWebSettings = binding.webView.getSettings();
//设置自适应屏幕,两者合用
mWebSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
mWebSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
//缩放操作
mWebSettings.setSupportZoom(false); //支持缩放,默认为true。是下面那个的前提。
// mWebSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
// mWebSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
//其他细节操作
mWebSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
mWebSettings.setAllowFileAccess(true); //设置可以访问文件
mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
mWebSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
mWebSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
//5.0以后,不允许https访问http的请求
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mWebSettings
.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
//下载时跳转到外部浏览器
binding.webView.setDownloadListener(new FileDownLoadListener());
binding.webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
KLog.d("开始加载");
showDialog("正在加载");
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
KLog.d("加载结束" + view.getTitle());
binding.ctbTitle.setTitle(view.getTitle());
dismissDialog();
}
// 链接跳转都会走这个方法
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
KLog.d("Url:"+ url );
if(url.startsWith("http")) {
view.loadUrl(url);// 强制在当前 WebView 中加载 url
}
return true;
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
});
binding.webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
KLog.d("newProgress:"+ newProgress );
}
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
KLog.d("标题:"+ title);
binding.ctbTitle.setTitle(title);
}
});
}
@Override
protected void onResume() {
super.onResume();
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
// 若加载的 html 里有JS 在执行动画等操作,会造成资源浪费(CPU、电量)
// 在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可
mWebSettings.setJavaScriptEnabled(true);
mWebSettings.setDomStorageEnabled(true);
}
@Override
protected void onStop() {
super.onStop();
mWebSettings.setJavaScriptEnabled(false);
mWebSettings.setDomStorageEnabled(false);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KEYCODE_BACK) && binding.webView.canGoBack()) {
binding.webView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
private class FileDownLoadListener implements DownloadListener {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
}
}
package com.kom.basic.util
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import com.fry.base.utils.AppSys
import com.fry.base.utils.CallBack3
import com.tbruyelle.rxpermissions2.RxPermissions
import com.yalantis.ucrop.UCrop
import com.yalantis.ucrop.UCropActivity
import me.goldze.mvvmhabit.utils.KLog
/**
* 2020/6/21 created
* 图片选择
* @author KOM
*/
data class CropParam(
val ratioX: Float = 1F,
val ratioY: Float = 1F,
val uiOption: UCrop.Options?
)
/**
* 默认不裁剪
*/
class ImagePicker(
private val callBack: CallBack3<Uri, String, Type>
) {
enum class Type {
CAMERA, ALBUM, CROP
}
private var imageUri: Uri? = null
private var isCrop: Boolean? = null
private var cropParam: CropParam? = null
private var activity: FragmentActivity? = null
private val selfCallBack = object : CallBack3<Uri,String, Type> {
override fun success(msg: Uri) {
activity = null
imageUri = null
callBack.success(msg)
}
override fun failure(msg: String) {
activity = null
imageUri = null
callBack.failure(msg)
}
override fun cancel(msg: Type) {
activity = null
imageUri = null
callBack.cancel(msg)
}
}
@SuppressLint("CheckResult")
fun openCamera(
activity: FragmentActivity, isCrop: Boolean? = null, cropParam: CropParam? = null
) {
this.activity = activity
this.isCrop = isCrop
this.cropParam = cropParam
val rxPermissions = RxPermissions(activity)
rxPermissions.request(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA
).subscribe { granted ->
if (granted) {
imageUri = AppSys.openCamera(activity, CODE_CAMERA)
if (imageUri == null) {
Toast.makeText(activity, "打开相机失败", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(
activity,
"权限未同意,程序可能出现未知错误!",
Toast.LENGTH_SHORT
).show()
}
}
}
fun openAlbum(
activity: FragmentActivity, isCrop: Boolean? = null, cropParam: CropParam? = null
) {
this.activity = activity
this.isCrop = isCrop
this.cropParam = cropParam
AppSys.openAlbum(activity, CODE_ALBUM)
}
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
CODE_CAMERA -> {
if (resultCode == Activity.RESULT_OK) {
KLog.d(TAG, "CAMERA onActivityResult imageUri=$imageUri")
openCropOrReturn(imageUri!!)
} else {
selfCallBack.cancel(Type.CAMERA)
}
}
CODE_ALBUM -> {
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
imageUri = data.data
KLog.d(TAG, "ALBUM onActivityResult imageUri=$imageUri")
openCropOrReturn(imageUri!!)
}
} else {
selfCallBack.cancel(Type.ALBUM)
}
}
UCrop.REQUEST_CROP -> {
if (data != null) {
when (resultCode) {
Activity.RESULT_OK -> {
imageUri = UCrop.getOutput(data)
selfCallBack.success(imageUri!!)
KLog.d(TAG, "ALBUM onActivityResult imageUri=$imageUri")
}
UCrop.RESULT_ERROR -> {
UCrop.getError(data)?.printStackTrace()
selfCallBack.failure("裁剪出错")
}
else -> {
selfCallBack.cancel(Type.CROP)
}
}
} else {
selfCallBack.cancel(Type.CROP)
}
}
}
}
private fun openCropOrReturn(uri: Uri) {
if (isCrop == true) {
val cropParam = cropParam ?: CropParam(uiOption = createDefaultCropOption())
AppSys.openCrop(activity!!, uri, cropParam.ratioX, cropParam.ratioY, cropParam.uiOption)
} else {
selfCallBack.success(uri)
}
// 重置 是否裁剪
isCrop = null
cropParam = null
}
companion object {
private val TAG = ImagePicker::class.simpleName
private const val CODE_ALBUM = 0x101
private const val CODE_CAMERA = 0x102
fun createDefaultCropOption(): UCrop.Options {
return UCrop.Options().apply {
//下面参数分别是缩放,旋转,裁剪框的比例
setAllowedGestures(UCropActivity.ALL, UCropActivity.NONE, UCropActivity.NONE)
//设置标题栏文字
setToolbarTitle("裁剪")
//设置裁剪网格线的宽度(我这网格设置不显示,所以没效果)
setCropGridStrokeWidth(2)
//设置裁剪框的宽度
setCropFrameStrokeWidth(10)
//设置最大缩放比例
setMaxScaleMultiplier(2F)
//隐藏下边控制栏
setHideBottomControls(false)
//设置是否显示裁剪网格
setShowCropGrid(true)
//设置是否显示裁剪边框(true为方形边框)
setShowCropFrame(false)
//标题字的颜色以及按钮颜色
setToolbarWidgetColor(Color.parseColor("#ffffff"))
//设置裁剪外颜色
setDimmedLayerColor(Color.parseColor("#AA000000"))
// 设置标题栏颜色
setToolbarColor(Color.parseColor("#000000"))
//设置状态栏颜色
setStatusBarColor(Color.parseColor("#000000"))
//设置裁剪网格的颜色
setCropGridColor(Color.parseColor("#ffffff"))
//设置裁剪框的颜色
setCropFrameColor(Color.parseColor("#ffffff"))
//设置裁剪的图片质量,取值0-100
setCompressionQuality(100)
}
}
}
}
package com.fry.base.utils
import android.app.Activity
import android.content.ContentValues
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import androidx.annotation.RequiresApi
import com.yalantis.ucrop.UCrop
import java.io.File
/**
* 2020/6/22 created
* 系统应用
* @author KOM
*/
object AppSys {
/**
* 打开相册
*/
fun openAlbum(activity: Activity, requestCode: Int) {
activity.startActivityForResult(Intent(Intent.ACTION_PICK).apply {
setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*")
}, requestCode)
}
fun openCamera(activity: Activity, requestCode: Int): Uri? {
var uri: Uri? = null
//打开相机的Intent
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
//这句作用是如果没有相机则该应用不会闪退,要是不加这句则当系统没有相机应用的时候该应用会闪退
if (cameraIntent.resolveActivity(activity.packageManager) != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// 适配android 10
uri = createEmptyImageUri(activity)
} else {
val imageFile = File(activity.getExternalFilesDir(null)?.path + "/${System.currentTimeMillis()}.jpg")
if (imageFile.isFile && imageFile.exists()) {
imageFile.delete()
}
// 适配Android7,私有文件授权
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider7.getUriForFile(activity, imageFile)
cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
} else {
uri = Uri.fromFile(imageFile)
}
}
if (uri != null) {
//将用于输出的文件Uri传递给相机
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
activity.startActivityForResult(cameraIntent, requestCode)
}
}
return uri
}
/**
* 打开裁剪
*/
fun openCrop(
activity: Activity,
uri: Uri,
ratioX: Float = 1F,
ratioY: Float = 1F,
options: UCrop.Options? = null
) {
//裁剪后图片保存在文件夹中
val destinationUri =
Uri.fromFile(File(activity.cacheDir, "${System.currentTimeMillis()}uCrop.jpg"))
//第一个参数是裁剪前的uri,第二个参数是裁剪后的uri
val uCrop = UCrop.of(uri, destinationUri)
//设置裁剪框的宽高比例
uCrop.withAspectRatio(ratioX, ratioY)
if (options != null) {
uCrop.withOptions(options)
}
uCrop.start(activity)
}
/**
* 创建图片地址uri,用于保存拍照后的照片 Android 10以后使用这种方法
*/
@RequiresApi(Build.VERSION_CODES.Q)
private fun createEmptyImageUri(activity: Activity): Uri? {
val status = Environment.getExternalStorageState()
// 判断是否有SD卡,优先使用SD卡存储,当没有SD卡时使用手机存储
return if (status == Environment.MEDIA_MOUNTED) {
activity.contentResolver
.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, ContentValues())
} else {
activity.contentResolver
.insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, ContentValues())
}
}
}
\ No newline at end of file
package com.fry.base.viewmodel;
import android.app.Application;
import androidx.annotation.NonNull;
import me.goldze.mvvmhabit.base.BaseViewModel;
/**
* Created by jeme on 2019/2/19
*/
public class BaseWebViewModel extends BaseViewModel {
public BaseWebViewModel(@NonNull Application application) {
super(application);
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.fry.base.viewmodel.BaseWebViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.fry.base.ui.widget.CommonTitleBar
android:id="@+id/ctb_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:ctb_theme="dark"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ctb_title"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
#Wed Jun 30 19:52:15 CST 2021
VERSION_BUILD=2320
#Thu Jul 01 19:22:36 CST 2021
VERSION_BUILD=2459
......@@ -11,8 +11,11 @@ android {
consumerProguardFiles 'consumer-rules.pro'
}
dataBinding {
enabled true
buildFeatures{
dataBinding = true
// for view binding :
viewBinding = true
}
......@@ -21,7 +24,7 @@ android {
dependencies {
//implementation fileTree(include: ['*.jar','*.aar'], dir: 'libs')
provided files('libs\\xpopup-release.aar')
compileOnly files('libs\\xpopup-release.aar')
//support
api rootProject.ext.support["support-v4"]
api rootProject.ext.support["appcompat-v7"]
......
......@@ -20,8 +20,8 @@ public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
setApplication(this);
SPUtils2.init(this);
// setApplication(this);
// SPUtils2.init(this);
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment