移动设备交互应用 大作业

Posted 上山打老虎D

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了移动设备交互应用 大作业相关的知识,希望对你有一定的参考价值。

我的垃圾分类APP

一、期末大作业的目的与要求:

1. 垃圾分类界面

请尽量模拟如下垃圾分类APP的功能,即参考如下的界面展示形式及功能模块:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 具体要求

模拟图1所示垃圾分类APP,介绍垃圾分类与回收相关的一些知识点并能提供相应服务:
1) 建议包含的一些功能:活动之间的转换与数据传递;能适应不同的展示界面;有登录功能,强制下线功能;数据有多样化的持久化功能;能跨程序提供与共享数据;有展示一些多媒体的功能;

2) 较好的实现了书本上介绍的一些较成熟的功能,并能较好的把这些功能融合在一个完整且无大bug的APP里;

3) 能在此基础上构建自己的报告亮点,如实现了书本不一样的功能模块,或者为某个知识点找到一些新的应用场景,或者能解决同学们普遍存在的一些问题等;

4) 模拟的APP不局限于所参照APP的功能,即尽量模拟这些功能,不要求将每个功能都实现,如果某个功能不能体现已学知识点,可以不用考虑,当然如果能想办法实现出来,可以作为报告亮点;即不必与这些功能完全一样,可在这些功能基础上进行变通,达到类似的效果就可以;可以设计一些该APP没有的功能,并能清楚说明这些功能的实现方式、潜在的用途等;同时布局的设计也不必与参考APP完全一样,可根据自己需要适当调整;

5) 总体目标是灵活利用所学的知识点,做到每个功能各种实现方式的丰富化(如数据的持久化的三种实现方式都能在APP中有所体现),并且能体现不同实现方式的优劣,如果能在APP上体现会更好;

3. 部分参考

1)功能实现参考:图1第2列图尽量参考第6章数据持久化技术的各个知识点;第3列尽量参考布局及活动之间的跳转,碎片的实现,多媒体展示功能;第4列可以利用数据持久化技术;

2)潜在的扩展功能:图1第4列尽量参考android基于位置的服务;添加一个小功能,整合网络技术的应用,即将一个html网页文件中的文本与图片网址进行分离,并将文本与图片用不同文件夹分开保持;利用数据后台下载的功能;

3)可以借鉴的部分章节内容,第12章可以让你的APP界面变得更美观;第14章展示了一个大型的工程,可以学习下多个功能怎样在一个工程里体现;

4. 其它要求

1)构建的APP要格式工整,美观;

2)实验报告中需要有功能的描述、实验结果的截屏图像及详细说明;结果展示要具体,图文交叉解释;代码与文本重点要突出;

3)也欢迎采用课程后续章节的知识点完成本次大作业,如果实现的功能言之合理,会考虑酌情加分;

4)每位同学在最后一次课都需要上台报告,并且最好能现场演示APP的功能等,没上台报告的同学分数会受一定的影响;

5)报告由个人独立完成。

5. 评分标准

  1. APP协议完成度高,与参考APP有一定的相似度,功能完善、丰富。能实现活动的编写、自定义用户界面的开发、碎片开发、广播机制、数据持久化与共享技术、网络技术、后台服务的应用等。
    -------------(60分)

  2. 模拟APP结构合理,代码规范,界面美观易用。项目报告撰写规范、美观整齐,内容详实且能准备描述项目内容和设计思想、原理、框架等,项目报告要求5号字、除前两页外A4版面不低于10页的长度。
    -------------(15分)

  3. 提供程序源代码和可执行程序(或安装程序);报告文档采用单独的word文档,项目所有代码(不是整个工程文件,应该总共不超过5M)在第17周之前打包作为附件进行上传blackboard系统;纸质版交到任课老师处。
    -------------(10分)

  4. 项目报告能够详细,准确的描述项目内容,并在最后一堂课有较好的展示效果。
    -------------(15分)

二、实验过程和代码与结果

1. 实验亮点:

①通过数据持久化与共享技术使用SQLite完成了历史搜索的功能;

②通过调用API网络接口完成对垃圾类别的判断;

③完成创新性功能——图片识别和语音识别,以及对应权限的申请;

④使用广播系统对网络进行判断,给出有无网络的提示;

⑤代码文件进行分文件夹分层存储,代码有易懂的结构;

⑥通过动态绘图进行布局,对不同种设备进行自适应匹配;

⑦使用更精美的UI动画(例如加载动画);

⑧通过代码托管平台实现了程序的版本更新;

⑨通过链接APPStore实现了对APP进行评分的可行性;

⑩完成了更细节的优化(如连续两次返回才退出,并在第一次时提示再滑动一次以退出);

⑪通过使用本地创建的秘钥将文件打包成APK;

⑫所有代码都有大量的注释,方便又易懂;

⑬实现了各个Adapter与Json处理工具,极大方便了开发过程;

⑭通过使用Intent进行Activity传值完成垃圾详情的查看;

⑮使用Fragment完成垃圾详情的查看;

⑯通过Logcat完成对整个项目的调试;

⑰采用LinearLayout进行布局。

2. “我的垃圾分类APP”的构建过程及结果

(1)欢迎页面的实现:

在日常使用中,为了使用APP更美观,并给APP内部数据加载预留时间,应设置一欢迎界面。在本次大作业中也有体现。
通过自动计时两秒,两秒后实现Activity的自动跳转。

public class WelcomeActivity extends BaseActivity {  
 @Override  
 protected void onCreate(Bundle savedInstanceState) {  
     requestWindowFeature(Window.FEATURE_NO_TITLE);  
     super.onCreate(savedInstanceState);  
     setContentView(R.layout.activity_welcome);  
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  
         getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);  
         getWindow().setStatusBarColor(Color.TRANSPARENT);  
     }  
     RxCountDown.countdown(2).doOnSubscribe(disposable -> {  
     }).subscribe(new Observer<Integer>() {  
         @Override  
         public void onSubscribe(Disposable d) {}  
  
         @Override  
         public void onNext(Integer integer) {}  
  
         @Override  
         public void onError(Throwable e) {}  
  
         @Override  
         public void onComplete() {  
             startActivity(new Intent(WelcomeActivity.this, HomeActivity.class));  
             finish();  
         }  
     });  
 } 

采用了ConstraintLayout进行布局:

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    tools:context=".ui.activity.WelcomeActivity">  
</android.support.constraint.ConstraintLayout> 

(2)垃圾分类的实现:

为了实现垃圾分类,我使用了一种互联网技术——API接口,并通过接口与服务器的数据交互完成对垃圾分类的判断。实现分获取API数据,显示和查询详细三个连续操作,下面分开介绍。

①获取API数据:

   private void loadData() {  
    String serachStr = mEtSearch.getText().toString();  
    if (StringUtils.isEmpty(serachStr)) {  
        showToast("请输入搜索内容", mRelTops);  
    } else {  
        if (OrcLoadUtils.isWifiProxy(RkApplication.getInstance())) {  
            showToast("请先关闭代理等", mRelTops);  
        } else {  
            showStatus(mViewLottie, new LoadAbstract(this));  
            OrcLoadUtils.searchName(serachStr).subscribe(o -> {  
                try {  
                    hideStatus(mViewLottie);  
                    TrashResultEntity entity = (TrashResultEntity) o;  
                    if (entity != null) {  
                        if (entity.Ok) {  
                            if (entity.Data != null && entity.Data.size() > 0) {  
                                String serachStr2 = mEtSearch.getText().toString();  
                                if (!StringUtils.isEmpty(serachStr2)) {  
                                    setRestData(entity.Data);  
                                }  
                            } else {  
                                loadDataTwo(serachStr);  
                            }  
                        } else {  
                            loadDataTwo(serachStr);  
                        }  
                    }  
                } catch (Exception e) {  
                    loadDataTwo(serachStr);  
                    e.printStackTrace();  
                }  
            });  
        }  
    }  
}  

在获取API数据时,定义了TrashResultEntity类用以接受返回的结果,并将各个获取的数据写回到该类中。

②进行数据展示:

要显示数据即在对应的Adapter中写入数据即可,通过函数传参进入即可。此外,如果查询结果为空,则需要进行特判,并显示未查询到结果。

private void setRestData(List<TrashResultEntity.DataBean> data) {  
     mTypeRecycle.setVisibility(View.GONE);  
     mResAdapter.setHeaderView(headerView);  
     mResAdapter.setNewData(data);  
 }  
private void setRestData(String search, String message) {  
     if (StringUtils.isEmpty(message)) {  
         message = "未查询到结果";  
     }  
     List<TrashResultEntity.DataBean> list = new ArrayList<>();  
     TrashResultEntity.DataBean data = new TrashResultEntity.DataBean();  
     data.Kind = 1008;  
     data.msg = message;  
     data.Name = search;  
     list.add(data);  
     mTypeRecycle.setVisibility(View.GONE);  
     mResAdapter.setHeaderView(headerView);  
     mResAdapter.setNewData(list);  
 }  

③查询详细信息:

此时只需判断传入的垃圾的种类,如果为合法种类,则通过intent传值打开对应的Activity即可。

private void openDetails(int type) {  
     if (type == 1 || type == 2 || type == 3 || type == 4) {  
         Intent intent = new Intent(this, RefuseDetailActivity.class);  
         intent.putExtra("type", type);  
         startActivity(intent);  
     }  
 }  

(3)语音识别:

在本次大作业中,为了方便各种用户不同的数据输入需求,我引用百度语音来进行语音识别并进行垃圾分类。进行语音识别的顺序大致如下:

①首先申请录音权限:

如果获得了录音权限,则将百度语音就绪;若无法获得录音权限,则弹出提示“权限不足”。

private void openBdAudio() {  
     PermissionUtils.permission(Manifest.permission.RECORD_AUDIO,  
             Manifest.permission.ACCESS_NETWORK_STATE,  
             Manifest.permission.INTERNET,  
             Manifest.permission.READ_PHONE_STATE,  
             Manifest.permission.WRITE_EXTERNAL_STORAGE)  
             .callback(new PermissionUtils.FullCallback() {  
                 @Override  
                 public void onGranted(List<String> permissionsGranted) {  
                     mLottigSound.setVisibility(View.VISIBLE);  
                     mImSound.setVisibility(View.GONE);  
                     asr.send(SpeechConstant.ASR_START, "{}", null, 0, 0);  
                     mTvSoundTips.setText("按下结束说话");  
                 }  
  
                 @Override  
                 public void onDenied(List<String> permissionsDeniedForever, List<String> permissionsDenied) {  
                     LogUtils.e("权限不足");  
                     showToast("权限不足");  
                 }  
             }).request();  
 }  

②判断服务器是否就绪,若就绪则可以获取用户语音输入:

if(name.equals(SpeechConstant.CALLBACK_EVENT_ASR_READY)){  
             // 引擎就绪,可以说话,一般在收到此事件后通过UI通知用户可以说话了  
             LogUtils.e("引擎就绪,可以说话,一般在收到此事件后通过UI通知用户可以说话了");  
             mLottigSound.setVisibility(View.VISIBLE);  
             mImSound.setVisibility(View.GONE);  
         }  

③当用户语音输入时,要提示出开始录音与录音结束

此处判断是否识别结束,如果已经识别结束,则给出提示“识别结束”,并将按钮的文字重新写为“按下说话”。

if(name.equals(SpeechConstant.CALLBACK_EVENT_ASR_FINISH)){  
             // 识别结束  
             LogUtils.e("识别结束");  
             mLottigSound.setVisibility(View.GONE);  
             mTvSoundTips.setText("按下说话");  
             mImSound.setVisibility(View.VISIBLE);  
         }  

④当用户输入完成时,及判断是否为有效输入

如果输入有效,则调用API对垃圾的类别进行判断。在判断数据是否有效输入时,可以判断数据长度不为空且字符数组长度大于0

if(name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)){  
             LogUtils.e(params);  
             RecogResult recogResult = RecogResult.parseJson(params);  
             // 识别结果  
             String[] results = recogResult.getResultsRecognition();  
             if (null != results && results.length > 0) {  
                 mEtSearch.setText(results[0]);  
             }  
             //LogUtils.e(results);  
         }  

(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

以上是关于移动设备交互应用 大作业的主要内容,如果未能解决你的问题,请参考以下文章

移动设备交互应用 实验三 我的校园

移动设备交互应用 实验二 我的头条

添加两个窗格的平板电脑布局会导致在移动设备中找不到视图(小于w600dp)

HTML5期末大作业:餐饮美食网站设计——咖啡(10页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 咖啡网页设计 美食餐饮网页设计...(代码片段

几个非常实用的JQuery代码片段

手机端&PC端鼠标和手势交互异同辨析(一)