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.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.Toast; import androidx.annotation.ColorRes; import androidx.annotation.Nullable; import androidx.annotation.StringRes; 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. */ public abstract class BaseActivity 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 protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // get genericity "B" Class entityClass = (Class) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; try { Method method = entityClass.getMethod("inflate", LayoutInflater.class);//get method from name "inflate"; binding = (B) method.invoke(entityClass,getLayoutInflater());//execute method to create a objct of viewbind; } catch (Exception e) { e.printStackTrace(); } setContentView(binding.getRoot()); mContext = this; try { //设置坚屏 一定要放到try catch里面,否则会崩溃 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } catch (Exception e) { } TAG = this.getClass().getSimpleName(); initViews(); } public abstract void initViews(); 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); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { //把操作放在用户点击的时候 View v = getCurrentFocus(); //得到当前页面的焦点,ps:有输入框的页面焦点一般会被输入框占据 if (isShouldHideKeyboard(v, ev)) { //判断用户点击的是否是输入框以外的区域 hideSoftKeyboard (); //收起键盘 } } return super.dispatchTouchEvent(ev); } /** * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时则不能隐藏 * * @param v * @param event * @return */ private boolean isShouldHideKeyboard(View v, MotionEvent event) { if (v != null && (v instanceof EditText)) { //判断得到的焦点控件是否包含EditText int[] l = {0, 0}; v.getLocationInWindow(l); int left = l[0], //得到输入框在屏幕中上下左右的位置 top = l[1], bottom = top + v.getHeight(), right = left + v.getWidth(); if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) { // 点击位置如果是EditText的区域,忽略它,不收起键盘。 return false; } else { return true; } } // 如果焦点不是EditText则忽略 return false; } /** * 判断软键盘输入法是否弹出 */ public boolean isKeyboardVisbility(Context context, View v) { InputMethodManager imm = (InputMethodManager) context.getSystemService(context.INPUT_METHOD_SERVICE); if (imm.hideSoftInputFromWindow(v.getWindowToken(), 0)) { imm.showSoftInput(v, 0); return true;//键盘显示中 } else { return false;//键盘未显示 } } protected void hideSoftKeyboard() { if (getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) { if (getCurrentFocus() != null) ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } /** * 状态栏高度 * @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(); } } public void showToast(String message){ Toast.makeText(this,message,Toast.LENGTH_SHORT).show(); } public void showToast(@StringRes int msg){ showToast(getString(msg)); } 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() { @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 resPonse){ PermissionX.init(this).permissions(FILE_PERMISSIONS).onExplainRequestReason(new ExplainReasonCallbackWithBeforeParam() { @Override public void onExplainReason(ExplainScope scope, List deniedList, boolean beforeRequest) { scope.showRequestReasonDialog(deniedList, "即将申请的权限是程序必须依赖的权限", "继续申请","我已明白"); } }).onForwardToSettings(new ForwardToSettingsCallback() { @Override public void onForwardToSettings(ForwardScope scope, List deniedList) { scope.showForwardToSettingsDialog(deniedList, "您需要去应用程序设置当中手动开启权限", "去设置","我已明白"); } }).request(new RequestCallback() { @Override public void onResult(boolean allGranted, List grantedList, List 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 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; } }