From 9fbcdc146440b49ef80714c1336c226e00727da8 Mon Sep 17 00:00:00 2001 From: Administrator <123> Date: Thu, 28 Oct 2021 10:16:30 +0000 Subject: [PATCH] 其他部分框架方法及文件新增 --- app/src/main/java/com/duqing/missions/base/BaseActivity.java | 404 +++++++++++ app/src/main/java/com/duqing/missions/data/BasePageResult.java | 21 app/src/main/java/com/duqing/missions/source/HttpPageSource.java | 16 app/src/main/java/com/duqing/missions/util/SpUtils.java | 476 +++++++++++++ app/src/main/java/com/duqing/missions/data/BaseApiResult.java | 23 app/src/main/java/com/duqing/missions/ui/main/home/HomeFragment.java | 113 +++ app/src/main/java/com/duqing/missions/ui/main/home/adapter/MissiontTopAdapter.java | 18 app/src/main/res/layout/fragment_dashboard.xml | 2 app/src/main/res/layout/activity_main.xml | 31 app/src/main/java/com/duqing/missions/MainActivity.java | 2 app/src/main/java/com/duqing/missions/ui/main/notifications/NotificationsViewModel.java | 2 app/build.gradle | 10 app/src/main/java/com/duqing/missions/common/NullViewHolder.java | 18 app/src/main/res/navigation/mobile_navigation.xml | 6 app/src/main/java/com/duqing/missions/ui/main/home/model/TopItemViewModel.java | 11 app/src/main/AndroidManifest.xml | 1 app/src/main/java/com/duqing/missions/data/ApkUpGradeResult.java | 29 app/src/main/res/layout/fragment_home.xml | 17 app/src/main/java/com/duqing/missions/MyApplication.java | 136 +++ app/src/main/res/layout/fragment_notifications.xml | 2 app/src/main/java/com/duqing/missions/util/ResPonse.java | 15 app/src/main/java/com/duqing/missions/base/BaseFragment.java | 52 + /dev/null | 19 app/src/main/java/com/duqing/missions/base/BaseAdapter.java | 154 ++++ app/src/main/java/com/duqing/missions/ui/main/notifications/NotificationsFragment.java | 2 app/src/main/java/com/duqing/missions/ui/main/Text.java | 7 app/src/main/java/com/duqing/missions/util/DeviceUtil.java | 374 ++++++++++ app/src/main/java/com/duqing/missions/ui/main/dashboard/DashboardFragment.java | 4 app/src/main/java/com/duqing/missions/ui/main/home/model/MissionDesc.java | 12 app/src/main/java/com/duqing/missions/util/MyLog.java | 42 + app/src/main/java/com/duqing/missions/ui/main/home/HomeViewModel.java | 47 + 31 files changed, 2,012 insertions(+), 54 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d9ad186..79380c7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -45,4 +45,14 @@ //// 注意:分包之后不会有默认的Header和Footer需要手动添加!还是原来的三种方法! implementation 'com.scwang.smart:refresh-layout-kernel:2.0.1' //核心必须依赖 implementation 'com.scwang.smart:refresh-header-classics:2.0.1' //经典刷新头 + implementation 'com.github.d-max:spots-dialog:1.1@aar'//loading view + implementation 'com.google.code.gson:gson:2.8.6' + implementation 'com.ansen.http:okhttpencapsulation:1.0.1'//版本更新下载 + implementation 'com.squareup.okhttp3:okhttp:3.12.1' + implementation 'com.squareup.retrofit2:retrofit:2.3.0' + //RXjava和retrofit结合 + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.2.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'com.github.bumptech.glide:glide:4.12.0' + implementation 'com.permissionx.guolindev:permissionx:1.2.2' //权限依赖 } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0d606cb..468dd29 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.duqing.missions" > + <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" diff --git a/app/src/main/java/com/duqing/missions/MainActivity.java b/app/src/main/java/com/duqing/missions/MainActivity.java index 3d0f16a..6c2f39a 100644 --- a/app/src/main/java/com/duqing/missions/MainActivity.java +++ b/app/src/main/java/com/duqing/missions/MainActivity.java @@ -9,7 +9,6 @@ import com.duqing.missions.base.BaseActivity; import com.duqing.missions.databinding.ActivityMainBinding; -import com.google.android.material.bottomnavigation.BottomNavigationView; public class MainActivity extends BaseActivity<ActivityMainBinding> { @@ -18,7 +17,6 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - BottomNavigationView navView = binding.navView; // Passing each menu ID as a set of Ids because each // menu should be considered as top level destinations. AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder( diff --git a/app/src/main/java/com/duqing/missions/MyApplication.java b/app/src/main/java/com/duqing/missions/MyApplication.java new file mode 100644 index 0000000..ef0eda4 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/MyApplication.java @@ -0,0 +1,136 @@ +package com.duqing.missions; + +import android.app.Activity; +import android.app.Application; +import android.content.Context; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.duqing.missions.util.MyLog; +import com.scwang.smart.refresh.footer.ClassicsFooter; +import com.scwang.smart.refresh.header.ClassicsHeader; +import com.scwang.smart.refresh.layout.SmartRefreshLayout; +import com.scwang.smart.refresh.layout.api.RefreshFooter; +import com.scwang.smart.refresh.layout.api.RefreshHeader; +import com.scwang.smart.refresh.layout.api.RefreshLayout; +import com.scwang.smart.refresh.layout.listener.DefaultRefreshFooterCreator; +import com.scwang.smart.refresh.layout.listener.DefaultRefreshHeaderCreator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public class MyApplication extends Application { + + final String TAG = "MyApplication"; + List<Activity> activities = new ArrayList<>(); + private Activity currentActivity;//当前activity + private boolean isInfront; //是否前台运行 + private static MyApplication application; + public static MyApplication getApplication() { + return application; + } + + public Activity getCurrentActivity() { + return currentActivity; + } + + @Override + public void onCreate() { + super.onCreate(); + application = this; + //CrashReport.initCrashReport(getApplicationContext(), "8d88679ae9", false);//注册bugly + //设置全局的Header构建器 + SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() { + @Override + public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) { + //layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white);//全局设置主题颜色 + return new ClassicsHeader(context);//.setTimeFormat(new DynamicTimeFormat("更新于 %s"));//指定为经典Header,默认是 贝塞尔雷达Header + } + }); + //设置全局的Footer构建器 + SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() { + @Override + public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) { + //指定为经典Footer,默认是 BallPulseFooter + return new ClassicsFooter(context).setDrawableSize(20); + } + }); + registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { + @Override + public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { + MyLog.d(TAG,"onActivityCreated "+activity.getClass().getSimpleName()); + if(!activities.contains(activity)){ + activities.add(activity); + } + } + + @Override + public void onActivityStarted(@NonNull Activity activity) { + MyLog.d(TAG,"onActivityStarted "+activity.getClass().getSimpleName()); + currentActivity = activity; + } + + @Override + public void onActivityResumed(@NonNull Activity activity) { + MyLog.d(TAG,"onActivityResumed "+activity.getClass().getSimpleName()); + currentActivity = activity; + isInfront = true; + } + + @Override + public void onActivityPaused(@NonNull Activity activity) { + MyLog.d(TAG,"onActivityPaused "+activity.getClass().getSimpleName()); + + } + + @Override + public void onActivityStopped(@NonNull Activity activity) { + MyLog.d(TAG,"onActivityStopped "+activity.getClass().getSimpleName()); + + } + + @Override + public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle bundle) { + MyLog.d(TAG,"onActivitySaveInstanceState "+activity.getClass().getSimpleName()); + isInfront = false; + + } + + @Override + public void onActivityDestroyed(@NonNull Activity activity) { + MyLog.d(TAG,"onActivityDestroyed "+activity.getClass().getSimpleName()); + if(activities.contains(activity)){ + activities.remove(activity); + } + } + }); + } + + /** + * 退出程序 + */ + public void quitApp(){ + for(Activity activity:activities){ + activity.finish(); + } + System.exit(0); + } + + public void clearActivities(){ + for(Activity activity:activities){ + /*if(activity instanceof LoginActivity){ + continue; + }*/ + activity.finish(); + } + } + + public boolean isInfront(){ + return isInfront; + } +} diff --git a/app/src/main/java/com/duqing/missions/base/BaseActivity.java b/app/src/main/java/com/duqing/missions/base/BaseActivity.java index cd24d4d..ef14ad3 100644 --- a/app/src/main/java/com/duqing/missions/base/BaseActivity.java +++ b/app/src/main/java/com/duqing/missions/base/BaseActivity.java @@ -1,14 +1,56 @@ package com.duqing.missions.base; +import android.Manifest; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.os.Environment; +import android.provider.Settings; +import android.util.Log; import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.Toast; +import androidx.annotation.ColorRes; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.FileProvider; import androidx.viewbinding.ViewBinding; +import com.duqing.missions.MyApplication; +import com.duqing.missions.data.ApkUpGradeResult; +import com.duqing.missions.util.MyLog; +import com.duqing.missions.util.ResPonse; +import com.duqing.missions.util.SpUtils; +import com.permissionx.guolindev.PermissionX; +import com.permissionx.guolindev.callback.ExplainReasonCallbackWithBeforeParam; +import com.permissionx.guolindev.callback.ForwardToSettingsCallback; +import com.permissionx.guolindev.callback.RequestCallback; +import com.permissionx.guolindev.request.ExplainScope; +import com.permissionx.guolindev.request.ForwardScope; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; +import java.util.Date; +import java.util.List; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; /** * Created by Administrator on 2021/10/27 0027. @@ -16,6 +58,41 @@ public abstract class BaseActivity<B extends ViewBinding> extends AppCompatActivity { protected B binding; + protected String TAG ; + public final String[] FILE_PERMISSIONS = new String []{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}; + public final String[] LOCATION_PERMISSIONS = new String []{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}; + public final String[] CAMERA_PERMISSIONS = new String[]{ FILE_PERMISSIONS[0],FILE_PERMISSIONS[1], Manifest.permission.CAMERA}; + public final String[] CAMERA_RECORD_PERMISSIONS = new String[]{ FILE_PERMISSIONS[0],FILE_PERMISSIONS[1], Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO}; + + public static final int RESULT_LOGIN = 100,RESULT_LOGIN_RECREATE = 103,RESULT_BIND = 101,RESULT_SENDEDFILES = 105,RESULT_DISSCONNECT = 104, + RESULT_UPDATEUSER = 115,RESULT_LOGOUT = 113, REQUEST_CODE_ACTIVITY = 333; + public static final int REQUEST_CODE_LOGOUT = 20009,/*退出*/ + REQUEST_CODE_ORDER = 10010,/*订单详情*/ + REQUEST_CODE_LOGIN = 20010,/*登录*/ + REQUEST_CODE_SCAN = 20011/*扫描请求*/, + REQUEST_CODE_PIC = 20012,/*选择图片*/ + REQUEST_CODE_PAYPASS = 20112,/*支付验证*/ + REQUEST_CODE_PAYPASS_FOR_ALIPAY = 20110,/*支付宝修改支付验证*/ + REQUEST_CODE_PAYPASS_FOR_REALNAME = 20111,/*支付宝修改支付验证*/ + REQUEST_CODE_PERMISSION = 20013,/*请求权限*/ + REQUEST_VERSION_PERMISSION = 20013,/*检查更新*/ + REQUEST_INSTALL_PERMISSION = 20014,/*请求安装权限*/ + REQUEST_CODE_MANAGE_GROUP = 20015,/*选择分组*/ + REQUEST_CODE_MANAGE_DEL = 20016,/*选择删除*/ + REQUEST_CODE_MANAGE_EDIT = 20017,/*选择编辑*/ + REQUEST_CODE_MANAGE_ADD = 20018,/*选择添加*/ + REQUEST_CODE_MANAGE_DRAFT = 20019,/*选择草稿编辑*/ + REQUEST_CODE_WEPAY = 20020,/*微信支付*/ + REQUEST_CODE_ALIPAY = 20021,/*支付宝*/ + REQUEST_CODE_PINKAGE = 20022,/*包邮设置*/ + REQUEST_INSTALL_APK = 20200,/*请求安装权限*/ + REQUEST_CODE_COMMENT_REFRESH = 20222,/*请求安装权限*/ + RESULT_CODE_DRAFT = 4041/*草稿*/, + RESULT_CODE_UPDATED = 4042/*更新*/, + RESULT_CODE_FAILD = 4044/*失败*/, + RESULT_CODE_SUCESS = 4046/*成功*/, + RESULT_CODE_CANCEL = 4043/*取消*/; + protected Context mContext; @Override @@ -30,5 +107,332 @@ e.printStackTrace(); } setContentView(binding.getRoot()); + mContext = this; + try { + //设置坚屏 一定要放到try catch里面,否则会崩溃 + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } catch (Exception e) { + } + TAG = this.getClass().getSimpleName(); } + + + public void setStatusBarTransparent(boolean isBlack){ + //透明状态栏 + getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + //透明导航栏 + getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); + } + + /** + * 修改状态栏颜色,支持4.4以上版本 + * @param colorId + */ + public void setStatusBarBgColor(@ColorRes int colorId) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + getWindow().setStatusBarColor(getResources().getColor(colorId)); + } + + /** + * 修改状态栏文本颜色 + * @param isBlack + */ + public void setStatusBarTextColor(boolean isBlack){ + View decor = getWindow().getDecorView(); + if (isBlack) { + 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); + } + } + + /** + * 隐藏虚拟按键 + */ + public void hideBottomUIMenu() { + //隐藏虚拟按键 + if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api + View v = getWindow().getDecorView(); + v.setSystemUiVisibility(View.GONE); + } else if (Build.VERSION.SDK_INT >= 19) { + //for new api versions. + View decorView = getWindow().getDecorView(); + int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY ; + decorView.setSystemUiVisibility(uiOptions); + } + + } + + /** + * 状态栏高度 + * @return + */ + public int getStatusBarHeight() { + int result = 0; + int resId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resId > 0) { + result = getResources().getDimensionPixelOffset(resId); + } + return result; + } + + + long mExitTime= 0 ; + /** + * 返回键退出程序 + */ + public void backExit() { + if ((System.currentTimeMillis() - mExitTime) > 2000) { + Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show(); + mExitTime = System.currentTimeMillis(); + } else { + //此方法导致app关闭后重启 + MyApplication.getApplication().quitApp(); + System.exit(0); + //quitApp(); + } + } + ApkUpGradeResult.AppInfo apkUpGrade; + ProgressDialog progressDialog ; + + public void showUpdateDialog(){ + if(apkUpGrade == null){ + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("新版本").setMessage("有新版更新\n"+apkUpGrade.content) + .setPositiveButton("", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + okHttpDownload(apkUpGrade.url, new ResPonse<String>() { + @Override + public void doSuccess(String path) { + apkUpGrade.remark = path; + openAPK(new File(path)); + } + + @Override + public void doError(String path) { + if(apkUpGrade.isImportant==1){ + showUpdateDialog(); + }else { + if(path != null) { + apkUpGrade.remark = path; + openAPK(new File(path)); + } + } + } + }); + } + }) + .setNegativeButton(apkUpGrade.isImportant==1?"退出":"取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if(apkUpGrade.isImportant==1){ + MyApplication.getApplication().quitApp(); + }else { + SpUtils.getInstance().putLongValOfProject(mContext,"version", new Date().getTime());//记录今天已经请求过更新 不在自动请求 + } + } + }); + } + + /** + * okhttp下载文件 + * @param downloadUrl + * @param resPonse + */ + protected void okHttpDownload(final String downloadUrl, final ResPonse<String> resPonse){ + PermissionX.init(this).permissions(FILE_PERMISSIONS).onExplainRequestReason(new ExplainReasonCallbackWithBeforeParam() { + @Override + public void onExplainReason(ExplainScope scope, List<String> deniedList, boolean beforeRequest) { + scope.showRequestReasonDialog(deniedList, "即将申请的权限是程序必须依赖的权限", "继续申请","我已明白"); + } + }).onForwardToSettings(new ForwardToSettingsCallback() { + @Override + public void onForwardToSettings(ForwardScope scope, List<String> deniedList) { + scope.showForwardToSettingsDialog(deniedList, "您需要去应用程序设置当中手动开启权限", "去设置","我已明白"); + } + }).request(new RequestCallback() { + @Override + public void onResult(boolean allGranted, List<String> grantedList, List<String> deniedList) { + if(allGranted){ + + OkHttpClient okHttpClient = new OkHttpClient.Builder().build(); + + Request request = new Request.Builder() + .url(downloadUrl) + .get() + .build(); + + okHttpClient.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException e) { + Log.e("tag", "onFailure: " + e.getMessage()); + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + ResponseBody body = response.body(); // 获取到请求体 + InputStream inputStream = body.byteStream(); // 转换成字节流 + progressDialog = new ProgressDialog(mContext); + progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + progressDialog.setTitle("正在下载..."); + progressDialog.setCancelable(false); + progressDialog.show(); + saveFile(inputStream, getSaveFilePath(downloadUrl), body.contentLength(),resPonse); + } + }); + } else { + Toast.makeText(mContext, "您拒绝了权限申请!", Toast.LENGTH_SHORT).show(); + } + } + }); + } + + /** + * @param inputStream + * @param filePath 存放的地址 + * @param l 文件的长度 + */ + private void saveFile(InputStream inputStream, final String filePath, final long l, final ResPonse<String> resPonse) { + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog.setMax((int)l);// 设置进度条最大值 + } + }); + long count = 0; + try { + File file = new File(filePath); + Log.i(TAG, "文件保存路径:" + filePath+" 文件是否存在:"+file.exists()); + if (!file.exists()) {//文件不存在 + file.createNewFile(); + }else{ + file.delete(); + } + // 获取到输出流,写入到的地址 + FileOutputStream outputStream = new FileOutputStream(file); + int length = -1; + byte[] bytes = new byte[1024 * 10]; + while ((length = inputStream.read(bytes)) != -1) { + // 写入文件 + outputStream.write(bytes, 0, length); + count += length; + + final long finalCount = count; + final int finalLenght = length; + runOnUiThread(new Runnable() { + @Override + public void run() { + progressDialog.setProgress((int) finalCount); // 设置进度 + } + }); + } + inputStream.close(); // 关闭输入流 + outputStream.close(); // 关闭输出流 + runOnUiThread(new Runnable() { + @Override + public void run() { + // 如果写入的进度值完毕,Toast + progressDialog.dismiss(); + resPonse.doSuccess(filePath); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 获取文件保存路径 sdcard根目录/download/文件名称 + * @param fileUrl + * @return + */ + public static String getSaveFilePath(String fileUrl){ + String fileName=fileUrl.substring(fileUrl.lastIndexOf("/")+1,fileUrl.length());//获取文件名称 + String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Download"; + File appDir = new File(storePath); + if (!appDir.exists()) { + appDir.mkdirs(); + } + return storePath + File.separator +fileName; + } + + /** + * 打开apk文件 + * @param file + */ + public void openAPK(final File file){ + + //android 8及以上需要设置权限 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !getPackageManager().canRequestPackageInstalls()) { + // 申请安装权限。 + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("需要允许安装权限").setMessage("应用需要手动设置,才能打开安装包升级应用").setCancelable(false) + .setNegativeButton("", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Uri packageUri = Uri.parse("package:" + getPackageName()); + Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageUri); + startActivityForResult(intent, REQUEST_INSTALL_PERMISSION); + dialog.dismiss(); + } + }) + .setPositiveButton(apkUpGrade.isImportant==1?"退出":"取消", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if(apkUpGrade.isImportant==1){ + MyApplication.getApplication().quitApp(); + } + } + }).create().show(); + return; + } + + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + Uri photoURI = null ; + if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) { //判读版本是否在7.0以上 + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + photoURI = FileProvider.getUriForFile(mContext, mContext.getApplicationContext().getPackageName() + ".provider", file);//添加这一句表示对目标应用临时授权该Uri所代表的文件 + + }else{ + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + photoURI = Uri.fromFile(file); + } + intent.setDataAndType(photoURI,"application/vnd.android.package-archive"); + startActivityForResult(intent,REQUEST_INSTALL_APK); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + MyLog.i(TAG,String.format("onActivityResult requestCode:%s, resultCode:%s, data:%s",requestCode, resultCode, data)); + if(requestCode == REQUEST_INSTALL_PERMISSION){ + openAPK(new File(apkUpGrade.remark)); + }else if(requestCode == REQUEST_INSTALL_APK && apkUpGrade.isImportant==1){ + /*showDialog("强制更新", "需要安装新版本才能继续使用","安装","退出", new ResPonse() { + @Override + public void doSuccess(Object obj) { + + } + + @Override + public void doError(Object obj) { + super.doError(obj); + } + });*/ + } + } + + + protected boolean onBackKeyDown() { + onBackPressed(); + return false; + } + } diff --git a/app/src/main/java/com/duqing/missions/base/BaseAdapter.java b/app/src/main/java/com/duqing/missions/base/BaseAdapter.java new file mode 100644 index 0000000..520e455 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/base/BaseAdapter.java @@ -0,0 +1,154 @@ +package com.duqing.missions.base; + +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewbinding.ViewBinding; + +import com.duqing.missions.R; +import com.duqing.missions.common.NullViewHolder; +import com.duqing.missions.databinding.LayoutNullBinding; +import com.duqing.missions.util.DeviceUtil; + +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2021/10/27 0027. + * T 数据类型 + * V 适配器视图 + */ +public abstract class BaseAdapter<B extends ViewBinding,A extends BaseActivity,T> extends RecyclerView.Adapter { + + protected List<T> mData = new ArrayList<>(); + + protected Drawable nullDrawable; + protected String nullTxt="暂无数据"; + protected String TAG = "BaseAdapter"; + protected A activity; + protected LayoutNullBinding nullBinding; + + public BaseAdapter(){ + } + + public BaseAdapter(@NonNull List<T> data){ + mData = data; + } + + public List<T> getData() { + return mData; + } + + public void setData(@NonNull List<T> data){ + mData = data; + notifyDataSetChanged(); + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + // get genericity "B" + Class<B> entityClass = (Class<B>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + try { + /* for(Method method: entityClass.getMethods()){ + StringBuilder sb = new StringBuilder(); + for(Class type : method.getParameterTypes()){ + sb.append(type.getSimpleName()+","); + } + Log.e(TAG,String.format("method:%s,return:%s,param:%s",method.getName(),method.getReturnType().getSimpleName(),sb.toString())); + }*/ + Method method = entityClass.getMethod("inflate", LayoutInflater.class,ViewGroup.class,boolean.class);//get method from name "inflate"; + B vBind = (B) method.invoke(entityClass,LayoutInflater.from(parent.getContext()),parent,false);//execute method to create a objct of viewbind; + return new ViewBindHolder(vBind); + } catch (Exception e) { + e.printStackTrace(); + } + return new NullViewHolder( LayoutNullBinding.inflate(LayoutInflater.from(parent.getContext()))); + } + + /** + * + * 创建视图 + * @param parent + * @param layout 视图文件 + * @param viewType 视图类型 1 加载正常视图 其他则加载空数据 + * @return + */ + protected View getRootView(@NonNull ViewGroup parent, @LayoutRes int layout,int viewType ){ + //MyLog.i(TAG,"getRootView viewType:"+viewType); + return LayoutInflater.from(parent.getContext()).inflate(viewType==1?layout: R.layout.layout_null,parent,false); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + //MyLog.i(TAG,"onBindViewHolder position:"+position+" "+mData.size()+" "+getItemViewType(position)); + if(getItemViewType(position)==0){ + return; + } + try { + activity = (A) holder.itemView.getContext(); + }catch (Exception e){} + bindView((ViewBindHolder) holder,mData.size()==0?null:mData.get(position),position); + } + + /** + * 设置最后一个底部间隔 + * @param holder + * @param position + */ + protected void setBottomMargin(ViewBindHolder holder, int position){ + setBottomMargin(holder,position,23); + } + + /** + * 设置最后一个底部间隔 + * @param holder + * @param position 位置 + * @param dp 间距 + */ + protected void setBottomMargin(RecyclerView.ViewHolder holder, int position,int dp){ + setBottomMargin(holder,position,dp,0); + } + protected void setBottomMargin(RecyclerView.ViewHolder holder, int position, int dp, int defaultDp){ + ViewGroup.MarginLayoutParams params1 = (ViewGroup.MarginLayoutParams) holder.itemView.getLayoutParams(); + if(position == mData.size() -1){ + params1.setMargins(params1.leftMargin, params1.topMargin, params1.rightMargin, DeviceUtil.convertDpToPixel(dp,holder.itemView.getContext())); + }else{ + params1.setMargins(params1.leftMargin, params1.topMargin, params1.rightMargin, DeviceUtil.convertDpToPixel(defaultDp,holder.itemView.getContext())); + } + } + protected abstract void bindView(ViewBindHolder holder,T data,int position); + + + @Override + public int getItemCount() { + //默认显示空视图,若不显示空视图则重写该方法,返回mData.size() + return mData == null || mData.size() == 0 ?1:mData.size(); + } + + + @Override + public int getItemViewType(int position) { + //当下标为0,数据集合为0 返回0(意味当前应显示空数据视图)) + //MyLog.i(TAG,"getItemViewType position:"+position+" mdata:"+mData.size()+" "+(position ==0 && mData.size()==0)); + return position ==0 && mData.size()==0?0:1; + } + + public class ViewBindHolder extends RecyclerView.ViewHolder{ + + B binding; + + public ViewBindHolder( B binding) { + super(binding.getRoot()); + this.binding = binding; + } + } + +} diff --git a/app/src/main/java/com/duqing/missions/base/BaseFragment.java b/app/src/main/java/com/duqing/missions/base/BaseFragment.java new file mode 100644 index 0000000..c4eccf8 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/base/BaseFragment.java @@ -0,0 +1,52 @@ +package com.duqing.missions.base; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.viewbinding.ViewBinding; + +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public abstract class BaseFragment<A extends BaseActivity,B extends ViewBinding> extends Fragment { + + protected A activity; + protected B binding; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + // get genericity "B" + Class<B> entityClass = (Class<B>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]; + try { + Method method = entityClass.getMethod("inflate", LayoutInflater.class,ViewGroup.class,boolean.class);//get method from name "inflate"; + binding = (B) method.invoke(entityClass,inflater,container,false);//execute method to create a objct of viewbind; + } catch (Exception e) { + e.printStackTrace(); + } + return binding.getRoot(); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + activity = (A) getActivity(); + initViews(); + } + + public abstract void initViews(); + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } + +} diff --git a/app/src/main/java/com/duqing/missions/common/NullViewHolder.java b/app/src/main/java/com/duqing/missions/common/NullViewHolder.java new file mode 100644 index 0000000..21bd137 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/common/NullViewHolder.java @@ -0,0 +1,18 @@ +package com.duqing.missions.common; + +import androidx.recyclerview.widget.RecyclerView; + +import com.duqing.missions.databinding.LayoutNullBinding; + +/** + * 空数据显示 + * Created by Administrator on 2021/10/28 0028. + */ +public class NullViewHolder extends RecyclerView.ViewHolder { + LayoutNullBinding binding; + + public NullViewHolder(LayoutNullBinding binding) { + super(binding.getRoot()); + this.binding = binding; + } +} diff --git a/app/src/main/java/com/duqing/missions/data/ApkUpGradeResult.java b/app/src/main/java/com/duqing/missions/data/ApkUpGradeResult.java new file mode 100644 index 0000000..27a34a8 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/data/ApkUpGradeResult.java @@ -0,0 +1,29 @@ +package com.duqing.missions.data; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public class ApkUpGradeResult extends BaseApiResult<ApkUpGradeResult.AppInfo> { + + public class AppInfo { + //以下为声明的参数 + public int type, isEnable, isImportant, id, code; + public String url,version, content, udate, remark; + + + @Override + public String toString() { + return "ApkUpGrade{" + + "type=" + type + "," + + "isEnable=" + isEnable + "," + + "isImportant=" + isImportant + "," + + "id=" + id + "," + + "url=" + url + "," + + "version=" + version + "," + + "content=" + content + "," + + "udate=" + udate + "," + + '}'; + } + + } +} diff --git a/app/src/main/java/com/duqing/missions/data/BaseApiResult.java b/app/src/main/java/com/duqing/missions/data/BaseApiResult.java new file mode 100644 index 0000000..ecd9acc --- /dev/null +++ b/app/src/main/java/com/duqing/missions/data/BaseApiResult.java @@ -0,0 +1,23 @@ +package com.duqing.missions.data; + +import java.io.Serializable; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public class BaseApiResult<D extends Object> implements Serializable { + public String msg; + public int code = 200; + public D data; + + + @Override + public String toString() { + return "BaseApiData{" + + "msg='" + msg + '\'' + + ", code=" + code + + ", data=" + data + + '}'; + } + +} diff --git a/app/src/main/java/com/duqing/missions/data/BasePageResult.java b/app/src/main/java/com/duqing/missions/data/BasePageResult.java new file mode 100644 index 0000000..6ae8be0 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/data/BasePageResult.java @@ -0,0 +1,21 @@ +package com.duqing.missions.data; + +import java.util.ArrayList; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public class BasePageResult<T> extends BaseApiResult<String>{ + public int pages; + public int total; + public int pageNum; + public ArrayList<T> rows; + + @Override + public String toString() { + return "PageBean{" + + ", total=" + total + + ", rows=" + rows + + '}'; + } +} diff --git a/app/src/main/java/com/duqing/missions/source/HttpPageSource.java b/app/src/main/java/com/duqing/missions/source/HttpPageSource.java new file mode 100644 index 0000000..fa15ca4 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/source/HttpPageSource.java @@ -0,0 +1,16 @@ +package com.duqing.missions.source; + +import com.duqing.missions.data.BasePageResult; + +import java.util.Observable; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public interface HttpPageSource<T extends BasePageResult> { + + Observable refresh(); + + Observable loadMore(int page,int size); + +} diff --git a/app/src/main/java/com/duqing/missions/ui/dashboard/DashboardViewModel.java b/app/src/main/java/com/duqing/missions/ui/dashboard/DashboardViewModel.java deleted file mode 100644 index 2b45769..0000000 --- a/app/src/main/java/com/duqing/missions/ui/dashboard/DashboardViewModel.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.duqing.missions.ui.dashboard; - -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; - -public class DashboardViewModel extends ViewModel { - - private MutableLiveData<String> mText; - - public DashboardViewModel() { - mText = new MutableLiveData<>(); - mText.setValue("This is dashboard fragment"); - } - - public LiveData<String> getText() { - return mText; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/duqing/missions/ui/home/HomeFragment.java b/app/src/main/java/com/duqing/missions/ui/home/HomeFragment.java deleted file mode 100644 index 9e8e621..0000000 --- a/app/src/main/java/com/duqing/missions/ui/home/HomeFragment.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.duqing.missions.ui.home; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProvider; -import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.duqing.missions.databinding.FragmentHomeBinding; -import com.scwang.smart.refresh.header.ClassicsHeader; -import com.scwang.smart.refresh.layout.SmartRefreshLayout; - -public class HomeFragment extends Fragment { - - private HomeViewModel homeViewModel; - private FragmentHomeBinding binding; - - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - homeViewModel = new ViewModelProvider(this).get(HomeViewModel.class); - - binding = FragmentHomeBinding.inflate(inflater, container, false); - View root = binding.getRoot(); - final SmartRefreshLayout smartRefresh = binding.smartRefresh; - smartRefresh.setRefreshHeader(new ClassicsHeader(getContext())); - final TextView textView = binding.textRecommend; - final ImageView imgSearch = binding.imgSearch; - RecyclerView recyclerClassify = binding.recyclerClassify; - RecyclerView recyclerTop = binding.recyclerTop; - final RecyclerView recyclerRecommend = binding.recyclerRecommend; - recyclerRecommend.setLayoutManager(new LinearLayoutManager(getContext())); - LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()); - layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); - recyclerClassify.setLayoutManager(layoutManager); - recyclerTop.setLayoutManager(new GridLayoutManager(getContext(),3)); - - homeViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() { - @Override - public void onChanged(@Nullable String s) { - textView.setText(s); - } - }); - return root; - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - binding = null; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/duqing/missions/ui/home/HomeViewModel.java b/app/src/main/java/com/duqing/missions/ui/home/HomeViewModel.java deleted file mode 100644 index 59bff9d..0000000 --- a/app/src/main/java/com/duqing/missions/ui/home/HomeViewModel.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.duqing.missions.ui.home; - -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; - -public class HomeViewModel extends ViewModel { - - private MutableLiveData<String> mText; - - public HomeViewModel() { - mText = new MutableLiveData<>(); - mText.setValue("This is home fragment"); - } - - public LiveData<String> getText() { - return mText; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/duqing/missions/ui/main/Text.java b/app/src/main/java/com/duqing/missions/ui/main/Text.java new file mode 100644 index 0000000..1ab6c35 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/ui/main/Text.java @@ -0,0 +1,7 @@ +package com.duqing.missions.ui.main; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public class Text { +} diff --git a/app/src/main/java/com/duqing/missions/ui/dashboard/DashboardFragment.java b/app/src/main/java/com/duqing/missions/ui/main/dashboard/DashboardFragment.java similarity index 91% rename from app/src/main/java/com/duqing/missions/ui/dashboard/DashboardFragment.java rename to app/src/main/java/com/duqing/missions/ui/main/dashboard/DashboardFragment.java index a63d963..a0d8ef3 100644 --- a/app/src/main/java/com/duqing/missions/ui/dashboard/DashboardFragment.java +++ b/app/src/main/java/com/duqing/missions/ui/main/dashboard/DashboardFragment.java @@ -1,10 +1,9 @@ -package com.duqing.missions.ui.dashboard; +package com.duqing.missions.ui.main.dashboard; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -12,7 +11,6 @@ import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; -import com.duqing.missions.R; import com.duqing.missions.databinding.FragmentDashboardBinding; public class DashboardFragment extends Fragment { diff --git a/app/src/main/java/com/duqing/missions/ui/main/home/HomeFragment.java b/app/src/main/java/com/duqing/missions/ui/main/home/HomeFragment.java new file mode 100644 index 0000000..665138e --- /dev/null +++ b/app/src/main/java/com/duqing/missions/ui/main/home/HomeFragment.java @@ -0,0 +1,113 @@ +package com.duqing.missions.ui.main.home; + +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.duqing.missions.MainActivity; +import com.duqing.missions.base.BaseFragment; +import com.duqing.missions.databinding.FragmentHomeBinding; +import com.duqing.missions.ui.main.home.adapter.MissiontTopAdapter; +import com.duqing.missions.ui.main.home.model.MissionDesc; +import com.scwang.smart.refresh.footer.ClassicsFooter; +import com.scwang.smart.refresh.header.ClassicsHeader; +import com.scwang.smart.refresh.layout.SmartRefreshLayout; +import com.scwang.smart.refresh.layout.api.RefreshLayout; +import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener; + +import java.util.List; + +public class HomeFragment extends BaseFragment<MainActivity,FragmentHomeBinding> { + + private HomeViewModel homeViewModel; + final String TAG = "HomeFragment"; + + + @Override + public void initViews() { + homeViewModel = new ViewModelProvider(this).get(HomeViewModel.class); + final SmartRefreshLayout smartRefresh = binding.smartRefresh; + smartRefresh.setRefreshHeader(new ClassicsHeader(getContext())); + smartRefresh.setRefreshFooter(new ClassicsFooter(getContext())); + final TextView textView = binding.textRecommend; + final ImageView imgSearch = binding.imgSearch; + RecyclerView recyclerClassify = binding.recyclerClassify; + RecyclerView recyclerTop = binding.recyclerTop; + final RecyclerView recyclerRecommend = binding.recyclerRecommend; + recyclerRecommend.setLayoutManager(new LinearLayoutManager(getContext())); + LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()); + layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + recyclerClassify.setLayoutManager(layoutManager); + recyclerTop.setLayoutManager(new GridLayoutManager(getContext(),3)); + smartRefresh.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() { + @Override + public void onLoadMore(@NonNull RefreshLayout refreshLayout) { + homeViewModel.onLoadMore(); + } + + @Override + public void onRefresh(@NonNull RefreshLayout refreshLayout) { + homeViewModel.onRefresh(); + } + }); + final MissiontTopAdapter topAdapter = new MissiontTopAdapter(); + recyclerTop.setAdapter(topAdapter); + homeViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() { + @Override + public void onChanged(@Nullable String s) { + textView.setText(s); + } + }); + homeViewModel.getMissions().observe(getViewLifecycleOwner(), new Observer<List<MissionDesc>>() { + @Override + public void onChanged(List<MissionDesc> missionDescs) { + smartRefresh.finishRefresh(); + smartRefresh.finishLoadMore(); + topAdapter.setData(missionDescs); + } + }); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + Log.e(TAG,"onCreateView"); + return super.onCreateView(inflater, container, savedInstanceState); + } + + @Override + public void onResume() { + super.onResume(); + Log.e(TAG,"onResume"); + } + + @Override + public void onPause() { + super.onPause(); + Log.e(TAG,"onPause"); + } + + @Override + public void onStop() { + super.onStop(); + Log.e(TAG,"onStop"); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + Log.e(TAG,"onDestroyView"); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/duqing/missions/ui/main/home/HomeViewModel.java b/app/src/main/java/com/duqing/missions/ui/main/home/HomeViewModel.java new file mode 100644 index 0000000..e76862b --- /dev/null +++ b/app/src/main/java/com/duqing/missions/ui/main/home/HomeViewModel.java @@ -0,0 +1,47 @@ +package com.duqing.missions.ui.main.home; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +import com.duqing.missions.ui.main.home.model.MissionDesc; + +import java.util.ArrayList; +import java.util.List; + +public class HomeViewModel extends ViewModel { + + private MutableLiveData<String> mText; + private MutableLiveData<List<MissionDesc>> missions = new MutableLiveData<>(); + + public HomeViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("This is home fragment"); + } + + public LiveData<String> getText() { + return mText; + } + + public MutableLiveData<List<MissionDesc>> getMissions() { + return missions; + } + + public void onRefresh(){ + List<MissionDesc> list = new ArrayList<>(); + list.add(new MissionDesc()); + list.add(new MissionDesc()); + list.add(new MissionDesc()); + list.add(new MissionDesc()); + missions.setValue(list); + } + + public void onLoadMore(){ + List<MissionDesc> list = missions.getValue(); + list.add(new MissionDesc()); + list.add(new MissionDesc()); + list.add(new MissionDesc()); + list.add(new MissionDesc()); + missions.postValue(list); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/duqing/missions/ui/main/home/adapter/MissiontTopAdapter.java b/app/src/main/java/com/duqing/missions/ui/main/home/adapter/MissiontTopAdapter.java new file mode 100644 index 0000000..de21915 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/ui/main/home/adapter/MissiontTopAdapter.java @@ -0,0 +1,18 @@ +package com.duqing.missions.ui.main.home.adapter; + +import com.duqing.missions.MainActivity; +import com.duqing.missions.base.BaseAdapter; +import com.duqing.missions.databinding.HomeItemTopBinding; +import com.duqing.missions.ui.main.home.model.MissionDesc; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public class MissiontTopAdapter extends BaseAdapter<HomeItemTopBinding, MainActivity, MissionDesc> { + + + @Override + protected void bindView(ViewBindHolder holder, MissionDesc data, int position) { + + } +} diff --git a/app/src/main/java/com/duqing/missions/ui/main/home/model/MissionDesc.java b/app/src/main/java/com/duqing/missions/ui/main/home/model/MissionDesc.java new file mode 100644 index 0000000..a67b8ba --- /dev/null +++ b/app/src/main/java/com/duqing/missions/ui/main/home/model/MissionDesc.java @@ -0,0 +1,12 @@ +package com.duqing.missions.ui.main.home.model; + +/** + * 任务列表数据数据 + * Created by Administrator on 2021/10/27 0027. + */ +public class MissionDesc { + public String title,type,label; + public double price; + public int participants,remaining,total; + +} diff --git a/app/src/main/java/com/duqing/missions/ui/main/home/model/TopItemViewModel.java b/app/src/main/java/com/duqing/missions/ui/main/home/model/TopItemViewModel.java new file mode 100644 index 0000000..8b2ab82 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/ui/main/home/model/TopItemViewModel.java @@ -0,0 +1,11 @@ +package com.duqing.missions.ui.main.home.model; + +import androidx.lifecycle.ViewModel; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public class TopItemViewModel extends ViewModel { + + +} diff --git a/app/src/main/java/com/duqing/missions/ui/notifications/NotificationsFragment.java b/app/src/main/java/com/duqing/missions/ui/main/notifications/NotificationsFragment.java similarity index 95% rename from app/src/main/java/com/duqing/missions/ui/notifications/NotificationsFragment.java rename to app/src/main/java/com/duqing/missions/ui/main/notifications/NotificationsFragment.java index 7ca38c9..e94c5af 100644 --- a/app/src/main/java/com/duqing/missions/ui/notifications/NotificationsFragment.java +++ b/app/src/main/java/com/duqing/missions/ui/main/notifications/NotificationsFragment.java @@ -1,4 +1,4 @@ -package com.duqing.missions.ui.notifications; +package com.duqing.missions.ui.main.notifications; import android.os.Bundle; import android.view.LayoutInflater; diff --git a/app/src/main/java/com/duqing/missions/ui/notifications/NotificationsViewModel.java b/app/src/main/java/com/duqing/missions/ui/main/notifications/NotificationsViewModel.java similarity index 89% rename from app/src/main/java/com/duqing/missions/ui/notifications/NotificationsViewModel.java rename to app/src/main/java/com/duqing/missions/ui/main/notifications/NotificationsViewModel.java index d28fa85..ed7c442 100644 --- a/app/src/main/java/com/duqing/missions/ui/notifications/NotificationsViewModel.java +++ b/app/src/main/java/com/duqing/missions/ui/main/notifications/NotificationsViewModel.java @@ -1,4 +1,4 @@ -package com.duqing.missions.ui.notifications; +package com.duqing.missions.ui.main.notifications; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; diff --git a/app/src/main/java/com/duqing/missions/util/DeviceUtil.java b/app/src/main/java/com/duqing/missions/util/DeviceUtil.java new file mode 100644 index 0000000..3679ee8 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/util/DeviceUtil.java @@ -0,0 +1,374 @@ +package com.duqing.missions.util; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.graphics.Point; +import android.os.Build; +import android.provider.Settings; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.Display; +import android.view.WindowManager; + +import androidx.core.app.ActivityCompat; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.math.BigDecimal; + + +/** + * Created by EDZ on 2018/1/30. + */ +public class DeviceUtil { + public static final String TAG = "DeviceUtil"; + + /** + * 设备信息 + * + * @param context + */ + public static void getDisplay(Context context) { + StringBuilder sb = new StringBuilder(); + sb.append("Version code is \n"); + sb.append("设备的Android版本号:");//设备的Android版本号 + sb.append(getSDKInt() + " " + getSDKVersion() + "\t");//设备的Android版本号 + sb.append("设备型号:");//设备型号 + sb.append(getDeviceModel() + "\t");//设备型号 + sb.append("设备厂商:");//设备型号 + sb.append(getDeviceBrand() + "\t");//设备型号 + sb.append("程序版本号:" + getAppVersionCode(context) + " " + getAppVersionName(context) + "\t");//程序版本号 + sb.append("设备唯一标识符:" + getSerialNumber(context)); + sb.append("\n设备imei:" + getIMEI(context)); + String str = sb.toString() + " \n"; + str += getDisplayInfomation(context) + " \n"; + str += getDensity(context) + " \n"; + str += "屏幕大小:" + getScreenInch(context) + "英寸 \n"; + str += getAndroiodScreenProperty(context) + "\n"; + Log.i(TAG, str); + } + + /** + * Double类型保留指定位数的小数,返回double类型(四舍五入) + * newScale 为指定的位数 + */ + private static double formatDouble(double d, int newScale) { + BigDecimal bd = new BigDecimal(d); + return bd.setScale(newScale, BigDecimal.ROUND_HALF_UP).doubleValue(); + } + + /** + * 设备型号 + * @return + */ + public static String getDeviceModel() { + return Build.MODEL; + } + + /** + * 设备厂商 + * @return + */ + public static String getDeviceBrand() { + return Build.BRAND; + } + + /** + * 设备的Android版本号 + * @return + */ + public static int getSDKInt() { + return Build.VERSION.SDK_INT; + } + + /** + * 设备的Android版本号 + * @return + */ + public static String getSDKVersion() { + return Build.VERSION.RELEASE; + } + + /** + * 程序版本号 + * @param context + * @return + */ + public static int getAppVersionCode(Context context) { + try { + return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return 1; + } + + /** + * 程序版本号 + * + * @param context + * @return + */ + public static String getAppVersionName(Context context) { + try { + return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return ""; + } + + /** + * 屏幕像素px + */ + @SuppressLint("NewApi") + public static String getDisplayInfomation(Context context) { + Point point = new Point(); + ((Activity) context).getWindowManager().getDefaultDisplay().getSize(point); + Log.d(TAG, "the screen size is " + point.toString()); + ((Activity) context).getWindowManager().getDefaultDisplay().getRealSize(point); + Log.d(TAG, "the screen real size is " + point.toString()); + return point.toString(); + } + + /** + * 屏幕信息 + * @param context + * @return + */ + public static String getAndroiodScreenProperty(Context context) { + int width = getScreenPixel(context).widthPixels; // 屏幕宽度(像素) + int height = getScreenPixel(context).heightPixels; // 屏幕高度(像素) + float density = getDensity(getScreenPixel(context)); // 屏幕密度(0.75 / 1.0 / 1.5) + int densityDpi = getDpi(context); // 屏幕密度dpi(120 / 160 / 240) + // 屏幕宽度算法:屏幕宽度(像素)/屏幕密度 + int screenWidth = getDp(context)[0]; // 屏幕宽度(dp) + int screenHeight = getDp(context)[1];// 屏幕高度(dp) + + + Log.d("h_bl", "屏幕宽度(像素):" + width); + Log.d("h_bl", "屏幕高度(像素):" + height); + Log.d("h_bl", "屏幕密度(0.75 / 1.0 / 1.5):" + density); + Log.d("h_bl", "屏幕密度dpi(120 / 160 / 240):" + densityDpi); + Log.d("h_bl", "屏幕宽度(dp):" + screenWidth); // 屏幕适配文件夹(例:layout-sw300dp),是以该属性为准则 + Log.d("h_bl", "屏幕高度(dp):" + screenHeight); + + StringBuilder sb = new StringBuilder(); + sb.append("屏幕宽度(像素):" + width + "\n"); + sb.append("屏幕高度(像素):" + height + "\n"); + sb.append("屏幕密度(0.75 / 1.0 / 1.5):" + density + "\n"); + sb.append("屏幕密度dpi(120 / 160 / 240):" + densityDpi + "\n"); + sb.append("屏幕宽度(dp):" + screenWidth + "\n"); + sb.append("屏幕高度(dp):" + screenHeight + "\n"); + return sb.toString(); + + } + + /** + * 通知栏高度 + * @param context + * @return + */ + public static int getStatusBarHeight(Context context) { + Class<?> c = null; + Object obj = null; + Field field = null; + int x = 0, statusBarHeight = 0; + try { + c = Class.forName("com.android.internal.R$dimen"); + obj = c.newInstance(); + field = c.getField("status_bar_height"); + x = Integer.parseInt(field.get(obj).toString()); + statusBarHeight = context.getResources().getDimensionPixelSize(x); + } catch (Exception e1) { + e1.printStackTrace(); + } + return statusBarHeight; + } + + /** + * 屏幕密度dpi + */ + public static int getDpi(Context context) { + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics dm = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(dm); + return dm.densityDpi; + } + + + /** + * 屏幕像素px + */ + @SuppressLint("NewApi") + public static Point getDisplayPixel(Context context) { + Point point = new Point(); + ((Activity) context).getWindowManager().getDefaultDisplay().getSize(point); + Log.d(TAG, "the screen size is " + point.toString()); + ((Activity) context).getWindowManager().getDefaultDisplay().getRealSize(point); + Log.d(TAG, "the screen real size is " + point.toString()); + return point; + } + + /** + * 屏幕像素px + */ + public static DisplayMetrics getScreenPixel(Context context) { + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics dm = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(dm); + return dm; + } + + /** + * 屏幕dp + */ + public static int[] getDp(Context context) { + int width = getScreenPixel(context).widthPixels; // 屏幕宽度(像素) + int height = getScreenPixel(context).heightPixels; // 屏幕高度(像素) + float density = getDensity(getScreenPixel(context)); // 屏幕密度(0.75 / 1.0 / 1.5) + // 屏幕宽度算法:屏幕宽度(像素)/屏幕密度 + int screenWidth = (int) (width / density); // 屏幕宽度(dp) + int screenHeight = (int) (height / density);// 屏幕高度(dp) + return new int[]{screenWidth, screenHeight}; + } + + /** + * 屏幕密度 + */ + public static float getDensity(DisplayMetrics dm) { + return dm.density; // 屏幕密度(0.75 / 1.0 / 1.5); + } + + /** + * 屏幕密度dpi + */ + public static String getDensity(Context context) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + Log.d(TAG, "Density is " + displayMetrics.density + " densityDpi is " + displayMetrics.densityDpi + " height: " + displayMetrics.heightPixels + + " width: " + displayMetrics.widthPixels); + return "Density is " + displayMetrics.density + " densityDpi is " + displayMetrics.densityDpi + " height: " + displayMetrics.heightPixels + + " width: " + displayMetrics.widthPixels; + } + + + /** + * 屏幕尺寸inch + */ + public static double getScreenInch(Context context) { + + try { + int realWidth = 0, realHeight = 0; + Display display = ((Activity) context).getWindowManager().getDefaultDisplay(); + DisplayMetrics metrics = new DisplayMetrics(); + display.getMetrics(metrics); + if (Build.VERSION.SDK_INT >= 17) { + Point size = new Point(); + display.getRealSize(size); + realWidth = size.x; + realHeight = size.y; + } else if (Build.VERSION.SDK_INT < 17 + && Build.VERSION.SDK_INT >= 14) { + Method mGetRawH = Display.class.getMethod("getRawHeight"); + Method mGetRawW = Display.class.getMethod("getRawWidth"); + realWidth = (Integer) mGetRawW.invoke(display); + realHeight = (Integer) mGetRawH.invoke(display); + } else { + realWidth = metrics.widthPixels; + realHeight = metrics.heightPixels; + } + + return formatDouble(Math.sqrt((realWidth / metrics.xdpi) * (realWidth / metrics.xdpi) + (realHeight / metrics.ydpi) * (realHeight / metrics.ydpi)), 1); + + + } catch (Exception e) { + e.printStackTrace(); + } + + return 0; + } + + /** + * dp获取dip + * @param dp + * @return + */ + public static int convertDpToPixel(float dp, Context context) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (dp * displayMetrics.density); + } + + /*** + * px获取dip + * @param pixel + * @return + */ + public static int convertPixelToDp(int pixel, Context context) { + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + return (int) (pixel / displayMetrics.density); + } + + public static String getSerialNumber(Context context) { + String serial = ""; + try { + if (Build.VERSION.SDK_INT >= 28) {//9.0+ + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { + Log.i(TAG, "getMEID meid: READ_PHONE_STATE" ); + ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_PHONE_STATE}, 1567); + } else { + serial = Build.getSerial(); + } + } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {//8.0+ + serial = Build.SERIAL; + } else {//8.0- + Class<?> c = Class.forName("android.os.SystemProperties"); + Method get = c.getMethod("get", String.class); + serial = (String) get.invoke(c, "ro.serialno"); + } + } catch (Exception e) { + Log.e("e", "读取设备序列号异常:" + e.toString()); + } + return serial; + } + + public static String getIMEI(Context context) { + String deviceId = ""; + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + if (null != tm) { + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { + Log.i(TAG, "getMEID meid: READ_PHONE_STATE" ); + ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_PHONE_STATE}, 1567); + } else { + if (tm.getDeviceId() != null) { + deviceId = tm.getDeviceId(); + } else { + deviceId = Settings.Secure.getString(context.getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID); + } + } + Log.d("deviceId--->", deviceId); + } + return ""; + } + + public static String getMEID() { + try { + Class clazz = Class.forName("android.os.SystemProperties"); + Method method = clazz.getMethod("get", String.class, String.class); + + String meid = (String) method.invoke(null, "ril.cdma.meid", ""); + if (!TextUtils.isEmpty(meid)) { + Log.d(TAG, "getMEID meid: " + meid); + return meid; + } + } catch (Exception e) { + e.printStackTrace(); + Log.w(TAG, "getMEID error : " + e.getMessage()); + } + return ""; + } +} diff --git a/app/src/main/java/com/duqing/missions/util/MyLog.java b/app/src/main/java/com/duqing/missions/util/MyLog.java new file mode 100644 index 0000000..521c63f --- /dev/null +++ b/app/src/main/java/com/duqing/missions/util/MyLog.java @@ -0,0 +1,42 @@ +package com.duqing.missions.util; + +import android.util.Log; + +import com.duqing.missions.BuildConfig; + + +/** + * My father is Object, ites purpose of + * + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2020-4-5. + */ +public class MyLog { + + + public static void i(String tag,String msg){ + if(BuildConfig.DEBUG) { + Log.i(tag, BuildConfig.BUILD_TYPE +" "+ msg); + } + } + + public static void e(String tag,String msg){ + if(BuildConfig.DEBUG) { + Log.e(tag, msg); + } + } + + + public static void d(String tag,String msg){ + if(BuildConfig.DEBUG) { + Log.d(tag, msg); + } + } + + + public static void v(String tag,String msg){ + if(BuildConfig.DEBUG) { + Log.v(tag, msg); + } + } + +} diff --git a/app/src/main/java/com/duqing/missions/util/ResPonse.java b/app/src/main/java/com/duqing/missions/util/ResPonse.java new file mode 100644 index 0000000..e7e53b5 --- /dev/null +++ b/app/src/main/java/com/duqing/missions/util/ResPonse.java @@ -0,0 +1,15 @@ +package com.duqing.missions.util; + +import java.io.Serializable; + +/** + * Created by Administrator on 2018/5/25. + */ + +public abstract class ResPonse<T> implements Serializable { + + public abstract void doSuccess(T obj); + + public void doError(T obj){}; + +} diff --git a/app/src/main/java/com/duqing/missions/util/SpUtils.java b/app/src/main/java/com/duqing/missions/util/SpUtils.java new file mode 100644 index 0000000..f3fd2fd --- /dev/null +++ b/app/src/main/java/com/duqing/missions/util/SpUtils.java @@ -0,0 +1,476 @@ +package com.duqing.missions.util; + +import android.content.Context; +import android.content.SharedPreferences; + +import androidx.collection.ArraySet; + +import java.util.Set; + +/** + * Created by Administrator on 2021/10/28 0028. + */ +public class SpUtils { + + static SpUtils instance; + + /** + * 获取SP实例 + * + * @return {@link SpUtils} + */ + public static SpUtils getInstance() { + if(instance == null){ + instance = new SpUtils(); + } + return instance; + } + + + public final String PROJECT = "project"; + public final String USER = "user"; + + + public boolean clearData(Context context, String keyShared){ + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + return settings.edit().clear().commit(); + } + + + public boolean clearData(Context context, String key, String keyShared){ + putString(context,key,null,keyShared); + return true; + } + + + + /** + * remove key preferences + * + * @param context + * @param key The name of the preference to modify + * @return True if the new values were successfully written to persistent storage. + */ + public void removeKey(Context context, String key, String keyShared){ + + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.remove(key); + } + + /** + * remove value preferences + * + * @param context + * @param value The name of the preference to modify + * @return True if the new values were successfully written to persistent storage. + */ + public void removeValue(Context context, String value, String keyShared){ + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.remove(value); + } + + + /** + * put string preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent storage. + */ + public boolean putString(Context context, String key, String value, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putString(key, value); + return editor.commit(); + } + + /** + * get string preferences + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value 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 String getString(Context context, String key, String keyShared) { + return getString(context, key, null,keyShared); + } + + /** + * get string preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with + * this name that is not a string + */ + public String getString(Context context, String key, String defaultValue, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + return settings.getString(key, defaultValue); + } + + /** + * put int preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent storage. + */ + public boolean putInt(Context context, String key, int value, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putInt(key, value); + return editor.commit(); + } + + /** + * get int preferences + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or -1. Throws ClassCastException if there is a preference with this + * name that is not a int + */ + public int getInt(Context context, String key, String keyShared) { + return getInt(context, key, -1,keyShared); + } + + /** + * get int preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with + * this name that is not a int + */ + public int getInt(Context context, String key, int defaultValue, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + try { + return settings.getInt(key, defaultValue); + }catch (ClassCastException e){ + try { + return Integer.parseInt(settings.getString(key,defaultValue+"")); + }catch (NumberFormatException en){ + return defaultValue; + } + } + } + + /** + * put long preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent storage. + */ + public boolean putLong(Context context, String key, long value, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putLong(key, value); + return editor.commit(); + } + + /** + * get long preferences + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or -1. Throws ClassCastException if there is a preference with this + * name that is not a long + */ + public long getLong(Context context, String key, String keyShared) { + return getLong(context, key, -1,keyShared); + } + + /** + * get long preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with + * this name that is not a long + */ + public long getLong(Context context, String key, long defaultValue, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + try { + return settings.getLong(key, defaultValue); + }catch (ClassCastException e){ + try { + return Long.parseLong(settings.getString(key,defaultValue+"")); + }catch (NumberFormatException en){ + return defaultValue; + } + } + } + + /** + * put float preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent storage. + */ + public boolean putFloat(Context context, String key, float value, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putFloat(key, value); + return editor.commit(); + } + + /** + * get float preferences + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or -1. Throws ClassCastException if there is a preference with this + * name that is not a float + */ + public float getFloat(Context context, String key, String keyShared) { + return getFloat(context, key, -1,keyShared); + } + + /** + * get float preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with + * this name that is not a float + */ + public float getFloat(Context context, String key, float defaultValue, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + try { + return settings.getFloat(key, defaultValue); + }catch (ClassCastException e){ + try { + return Float.parseFloat(settings.getString(key,defaultValue+"")); + }catch (NumberFormatException en){ + return defaultValue; + } + } + } + + /** + * put boolean preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference + * @return True if the new values were successfully written to persistent storage. + */ + public boolean putBoolean(Context context, String key, boolean value, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putBoolean(key, value); + return editor.commit(); + } + + /** + * get boolean preferences, default is false + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or false. Throws ClassCastException if there is a preference with this + * name that is not a boolean + */ + public boolean getBoolean(Context context, String key, String keyShared) { + return getBoolean(context, key, false,keyShared); + } + + /** + * get boolean preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with + * this name that is not a boolean + */ + public boolean getBoolean(Context context, String key, boolean defaultValue, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + try { + return settings.getBoolean(key, defaultValue); + }catch (ClassCastException e){ + try { + return Boolean.parseBoolean(settings.getString(key,defaultValue+"")); + }catch (NumberFormatException en){ + return defaultValue; + } + } + } + + /** + * put boolean preferences + * + * @param context + * @param key The name of the preference to modify + * @param value The new value for the preference , the value of set ,canot be the other class out of java collection + * @return True if the new values were successfully written to persistent storage. + */ + public boolean putStringSet(Context context, String key, Set value, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = settings.edit(); + editor.putStringSet(key, value); + return editor.commit(); + } + + /** + * get boolean preferences, default is false + * + * @param context + * @param key The name of the preference to retrieve + * @return The preference value if it exists, or false. Throws ClassCastException if there is a preference with this + * name that is not a boolean 获取出来的值最终被转换为hashset类型 + */ + public Set getStringSet(Context context, String key, String keyShared) { + return getStringSet(context, key,new ArraySet(),keyShared); + } + + /** + * get boolean preferences + * + * @param context + * @param key The name of the preference to retrieve + * @param defaultValue Value to return if this preference does not exist + * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with + * this name that is not a boolean 获取出来的值最终被转换为hashset类型 + */ + public Set getStringSet(Context context, String key, Set defaultValue, String keyShared) { + SharedPreferences settings = context.getSharedPreferences(keyShared, Context.MODE_PRIVATE); + return settings.getStringSet(key, defaultValue); + } + + public boolean getBooleanValOfUser(Context context, String key){ + return getBoolean(context,key,false,USER); + } + + public boolean getBooleanValOfProject(Context context, String key){ + return getBoolean(context,key,false,PROJECT); + } + + public String getStringValOfUser(Context context, String key){ + return getString(context,key,"",USER); + } + + public String getStringValOfProject(Context context, String key){ + return getString(context,key,"",PROJECT); + } + + public int getIntValOfProject(Context context, String key){ + return getInt(context,key,0,PROJECT); + } + + public Long getLongValOfProject(Context context, String key){ + return getLong(context,key,0,PROJECT); + } + + public float getFloatValOfProject(Context context, String key){ + return getFloat(context,key,0,PROJECT); + } + + public Set getStringSetValOfProject(Context context, String key){ + return getStringSet(context,key,PROJECT); + } + + public int getIntValOfUser(Context context, String key){ + return getInt(context,key,0,USER); + } + + public Long getLongValOfUser(Context context, String key){ + return getLong(context,key,0,USER); + } + + public float getFloatValOfUser(Context context, String key){ + return getFloat(context,key,0,USER); + } + + public Set getStringSetValOfUser(Context context, String key){ + return getStringSet(context,key,USER); + } + + + public void putBooleanValOfUser(Context context, String key ,Boolean value){ + putBoolean(context,key,value,USER); + } + + public void putBooleanValOfProject(Context context, String key,Boolean value){ + putBoolean(context,key,value,PROJECT); + } + + public void putStringValOfUser(Context context,String key,String value){ + putString(context,key,value,USER); + } + + public void putStringValOfProject(Context context,String key,String value){ + putString(context,key,value,PROJECT); + } + + public void putIntValOfProject(Context context,String key,int value){ + putInt(context,key,value,PROJECT); + } + + public void putLongValOfProject(Context context,String key,long value){ + putLong(context,key,value,PROJECT); + } + + public void putFloatValOfProject(Context context,String key,float value){ + putFloat(context,key,value,PROJECT); + } + + public void putStringSetValOfProject(Context context,String key,Set value){ + putStringSet(context,key,value,PROJECT); + } + + public void putIntValOfUser(Context context,String key,int value){ + putInt(context,key,value,USER); + } + + public void putLongValOfUser(Context context,String key,long value){ + putLong(context,key,value,USER); + } + + public void putFloatValOfUser(Context context,String key,float value){ + putFloat(context,key,value,USER); + } + + public void putStringSetValOfUser(Context context,String key, Set value){ + putStringSet(context,key,value,USER); + } + + + public void removeUserKey(Context context, String key){ + removeKey(context,key,USER); + } + + public void removeProjectKey(Context context, String key){ + removeKey(context,key,PROJECT); + } + + public void removeUserValue(Context context, String Value){ + removeValue(context,Value,USER); + } + + public void removeProjectValue(Context context, String Value){ + removeValue(context,Value,PROJECT); + } + + + public void clearProjectData(Context context){ + clearData(context,PROJECT); + } + public void clearUserData(Context context){ + clearData(context,USER); + } + +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 035ff13..177d7d2 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,34 +1,27 @@ <?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/container" android:layout_width="match_parent" - android:layout_height="match_parent" > - - <com.google.android.material.bottomnavigation.BottomNavigationView - android:id="@+id/nav_view" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginStart="0dp" - android:layout_marginEnd="0dp" - android:background="?android:attr/windowBackground" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent" - app:menu="@menu/bottom_nav_menu"/> + android:layout_height="match_parent" + android:orientation="vertical"> <fragment android:id="@+id/nav_host_fragment_activity_main" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" + android:layout_weight="1" app:defaultNavHost="true" - app:layout_constraintBottom_toTopOf="@id/nav_view" - app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent" - app:layout_constraintTop_toTopOf="parent" app:navGraph="@navigation/mobile_navigation" /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file + <com.google.android.material.bottomnavigation.BottomNavigationView + android:id="@+id/nav_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?android:attr/windowBackground" + app:menu="@menu/bottom_nav_menu"/> + +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml index c55e1b8..f1fff12 100644 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ b/app/src/main/res/layout/fragment_dashboard.xml @@ -5,7 +5,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.dashboard.DashboardFragment" > + tools:context=".ui.main.dashboard.DashboardFragment" > <com.google.android.material.tabs.TabLayout android:id="@+id/tablayout" diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 47973db..6ed5bfb 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> -<LinearLayout +<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" tools:ignore="MissingConstraints" - tools:context=".ui.home.HomeFragment" + tools:context=".ui.main.home.HomeFragment" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent"> @@ -12,11 +12,17 @@ android:id="@+id/img_search" android:layout_width="39dp" android:layout_height="35dp" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/smart_refresh" android:src="@android:drawable/ic_search_category_default"/> <com.scwang.smart.refresh.layout.SmartRefreshLayout android:id="@+id/smart_refresh" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@id/img_search" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintBottom_toBottomOf="parent" > <androidx.constraintlayout.widget.ConstraintLayout @@ -28,6 +34,7 @@ android:id="@+id/recycler_top" android:layout_width="match_parent" android:layout_height="wrap_content" + android:overScrollMode="never" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:spanCount="3" tools:itemCount="3" @@ -38,6 +45,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" + android:overScrollMode="never" tools:listitem="@layout/home_item_classify" app:layout_constraintTop_toBottomOf="@id/recycler_top" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" @@ -61,6 +69,7 @@ android:id="@+id/recycler_recommend" android:layout_width="match_parent" android:layout_height="wrap_content" + android:overScrollMode="never" tools:listitem="@layout/homt_item_recommend" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@id/text_recommend" @@ -69,4 +78,4 @@ </androidx.constraintlayout.widget.ConstraintLayout> </com.scwang.smart.refresh.layout.SmartRefreshLayout> -</LinearLayout> \ No newline at end of file +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_notifications.xml b/app/src/main/res/layout/fragment_notifications.xml index 47368bf..734378a 100644 --- a/app/src/main/res/layout/fragment_notifications.xml +++ b/app/src/main/res/layout/fragment_notifications.xml @@ -6,7 +6,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white_2" - tools:context=".ui.notifications.NotificationsFragment"> + tools:context=".ui.main.notifications.NotificationsFragment"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 567dacb..ebb9ec8 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -7,19 +7,19 @@ <fragment android:id="@+id/navigation_home" - android:name="com.duqing.missions.ui.home.HomeFragment" + android:name="com.duqing.missions.ui.main.home.HomeFragment" android:label="@string/title_home" tools:layout="@layout/fragment_home" /> <fragment android:id="@+id/navigation_dashboard" - android:name="com.duqing.missions.ui.dashboard.DashboardFragment" + android:name="com.duqing.missions.ui.main.dashboard.DashboardFragment" android:label="@string/title_dashboard" tools:layout="@layout/fragment_dashboard" /> <fragment android:id="@+id/navigation_notifications" - android:name="com.duqing.missions.ui.notifications.NotificationsFragment" + android:name="com.duqing.missions.ui.main.notifications.NotificationsFragment" android:label="@string/title_notifications" tools:layout="@layout/fragment_notifications" /> </navigation> \ No newline at end of file -- Gitblit v1.9.1