(4)图片识别:
本次大作业中,额外更部署了图片识别功能,也通过调用对应API接口来完成图片的识别,并完成对识别出结果的垃圾分类。
①与语音识别相同,首先要申请权限,如果获得权限则接口就绪,否则弹出权限不足的提示。
private void opemCamera() { PermissionUtils.permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA) .callback(new PermissionUtils.FullCallback() { @Override public void onGranted(List<String> permissionsGranted) { PictureSelector.create(HomeActivity.this) .openGallery(PictureMimeType.ofImage()) .maxSelectNum(1) .selectionMode(PictureConfig.SINGLE) .forResult(9); } @Override public void onDenied(List<String> permissionsDeniedForever, List<String> permissionsDenied) { LogUtils.e("权限不足"); showToast("权限不足"); } }).request(); }
②获取上传的图片后,调用对应的API接口,然后获取返回数据,并进行垃圾种类的判断。
private void loadImage(String image) { showStatus(mViewLottie, new LoadAbstract(this)); OrcLoadUtils.imageTAg(image).subscribe(o -> { LogUtils.e(o.toString()); if (o != null && !StringUtils.isEmpty(o.toString())) { mEtSearch.setText(o.toString()); } else { hideStatus(mViewLottie); } }); }
(5)网络监测:
这里我使用了广播系统对网络进行判断,并在没有网络的时候toast出提示信息。
public class NetWorkStateReceiver extends BaseBroadcastReceiver { @Override public void onReceive(Context context, Intent intent, int flag) { if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { // 发送网络改变事件 ConnectivityManager manager = (ConnectivityManager) Utils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE); //没有网络链接的时候 activeNetwork=null NetworkInfo activeNetwork = manager.getActiveNetworkInfo(); if (activeNetwork == null){ ToastUtils.showShort("没有网络"); }else { //ToastUtils.showShort("有网络"); } } }
(6)版本更新
在我们使用其他APP时,经常会遇到需要版本更新的情况,在本次大作业中,也有类似的设计。在本大作业中,我通过使用蒲公英代码托管平台托管最新版本,并通过对应API接口完成版本号获取,并完成更新。
①首先定义获取更新类:
public static class DataBean { public boolean isForce;//是否强制更新 public int version;//版本号 public String message;//更新信息 public String url;//API接口链接 }
②更新检测(判断是否有更新版本):
此处即进行版本号判断,如果没有更新版本,则提示“你已经是最新版本”。否则调用APP更新类对APP进行更新。
public static void checkUpdateVersion(final BaseActivity context) { JKX_API.getInstance().getAppVersion("", new Observer() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(Object o) { try { VersionEntity versionEntity = (VersionEntity) o; String newVersion = versionEntity.data.version + ""; boolean isShowUpdate = AppUpdateUtils.newInstance().isCanUpdateApp(newVersion, context); SPUtils.getInstance().put("is_update", isShowUpdate); if (isShowUpdate) AppUpdateUtils.newInstance().updateApp(context, versionEntity.data.version + "", versionEntity.data.isForce , versionEntity.data.message, versionEntity.data.url); else context.showToast("你已经是最新版本"); } catch (Exception e) { e.printStackTrace(); } } @Override public void onError(Throwable e) { LogUtils.e(e); SPUtils.getInstance().put("is_update", false); } @Override public void onComplete() { } });
③弹出更新对话框:
更新时需要弹出更新对话框让用户知晓,因此需要设计一个对话框,让用户明确即将进行版本更新,若为非强制更新,则让用户选择是否进行更新。
public void showDownLoadDialog(final BaseActivity activity, final boolean isForce, String message, final String url) { final WeakReference<BaseActivity> activityWeak = new WeakReference<BaseActivity>(activity); final IosPopupDialog dialog = new IosPopupDialog(activity); if (isForce) {//如果是非强制更新则让用户可以选择更新或取消 dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); } else { dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(true);//取消使能 } dialog.setTextColor(R.id.tv_title, Color.parseColor("#333333")); dialog.setTextColor(R.id.tv_message, Color.parseColor("#333333")); //弹出对话框 dialog.setTitle("新版本更新说明") .setMessage(message) .setPositiveButton("确定", true, new View.OnClickListener() { @Override public void onClick(View v) { downLoadApk(activityWeak, isForce, url); } }); if (!isForce) { dialog.setNegativeButton("稍后再说", true, new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); } dialog.show(); }
下载对话框为一个弹窗,布局使用LinearLayout进行布局。
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="正在下载" android:textColor="@color/black" android:textSize="16sp"/> <TextView android:id="@+id/tv_update_app_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="0%" android:textColor="@color/black" android:textSize="14sp"/> <me.android.materialprogressbar.MaterialProgressBar android:id="@+id/mpb_update_app_progress" style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginTop="8dp" android:max="100" app:mpb_progressBackgroundTint="#f0f0f5" app:mpb_progressStyle="horizontal" app:mpb_progressTint="@color/colorPrimary"/>
④开始下载更新文件:
此处通过API接口完成更新数据流的链接,不断从API中获取更新数据。对于非强制更新,需要在更新时赋予用户取消使能。此时可以重用②中弹出对话框的代码。
显示之后即可新建线程,对线程启用监听,获取下载状态。
baseDownloadTask = FileDownloader.getImpl() .create(url) .setPath(FileDownloadUtils.getDefaultSaveRootPath() + "/" + "download") .setForceReDownload(true) .setListener(new FileDownloadListener()
若未处于下载状态则提示“等待中”字样。
protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) { LogUtils.d("BaseDownloadTask:pending"); }
若处于下载状态,则显示当前下载进度
protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) { int percent = (int) ((double) soFarBytes / (double) totalBytes * 100); LogUtils.d("BaseDownloadTask:" + percent); bar.setProgress(percent); progress.setText(percent + "%"); }
⑤此外,如果发生错误或警告,需要提示用户取消
protected void error(BaseDownloadTask task, Throwable e) { downDialog.dismiss(); } protected void warn(BaseDownloadTask task) { downDialog.dismiss(); }
(7)调用商店进行评分
在日常中我们使用的APP都会包含评分功能,通过调用系统的APP商店进行评分。本大作业也实现了这个功能。
只需调用对应的url并加载对应的Activity即可。此处使用了Intent进行传值。
Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse("market://details?id=" + AppUtils.getAppPackageName())); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i);
(8)退出提示:
在我们日常使用APP的过程中经常遇到,为了防止用户误操作,造成意外退出的情况,此时需要当用户在主页面上连续两次点击返回而不是一次才能进行退出操作。
为了实现这个操作,只需判断用户是否在连续两秒内连续点击回退按钮即可。
public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { long time = System.currentTimeMillis(); if (time - firstTime > 2000) { showToast("再按一次退出"); firstTime = time; return true; } else { finish(); } } return super.onKeyDown(keyCode, event); }
(9)打包成APK:
为了方便发布本APP,需要将APP打包成APK的格式,此处需要使用数字秘钥,选择Build->Generate Signed Bundle/APK 并选择APK,点击Next。
然后由于本地没有数字秘钥,可以创建一个,点击new按钮。并在弹出页面中输入对应的信息和密码(此处密码都为SZUDYH)后点击OK,即可创建。到对应目录下即可看到打包好的APK文件