简易安卓APP

简介

  如今来分享期末作的安卓大做业——生活百科。
  本项目只是单纯的一个大做业,没有考虑实际的需求,因此有设计不合理的地方,请见谅。
  这个项目有三大功能(由于是使用了侧边栏因此是能够继续往里面添加功能的),首先有单词查询,其次是天气查询,后来是机器聊天功能。单词查询是使用了扇贝单词提供的免费API;天气查询是使用了聚合数据提供的天气API,这里须要注册使用(有限的无偿使用);机器聊天是使用了图灵机器人的API。因此,总结一下,这里个人主要工做不会不少,主要是调用API而后进行数据的分析和显示工做。
  本次使用的IDE是idea(Android studio)。
  
  文章的最后将会给出源码,可是一些API接口须要本身去申请Keyhtml

在项目开始前的学习阶段
安卓基础入门 http://www.runoob.com/android/android-tutorial.html
安卓省市联动(天气的位置选择) http://blog.csdn.net/qq_20521573/article/details/51914180
安卓fragment的使用 http://www.jikexueyuan.com/course/708.html
机器聊天界面的HTML源码 http://www.lanrenzhijia.com/js/3930.html
以上即是我着手项目的累积步骤,但愿有帮助android

1. 项目准备阶段

1.1. 新建项目

  使用Android Studio(IDEA)新建安卓项目->选择SDK版本(Android 4.0为好)->选择Navigation Drawer Activity模板->完成项目建立。项目新建以后就会获得咱们基本的界面模板了。然后,只须要删除右侧边和底部的元素就可获得下图所示的界面git

固然,这里使用Android ADT也是能够的,不过好像新建出来的模板不同,比较丑一点(本身对于Android的UI不太行),因此就使用了Android Studio。github

1.2. 添加依赖

  因为须要使用省市联动的功能,因此须要添加外部依赖,在上面给出的连接上有详细说明,所以须要在app文件夹下的build.gradle里面的dependencies加入
  web

compile 'com.contrarywind:Android-PickerView:3.2.5'//自定义控件
    compile 'com.google.code.gson:gson:2.7'//解析JSON

  作完了准备工做以后就进入主题api

2. 单词查询功能

  考虑文章的篇幅过长,因此有些详细的过程可能会省略(像界面的修改工做等等)。网络

  当咱们输入了单词以后点击查询是须要访问网络的,这里采用了异步的任务机制去访问网络而且得出结果,部分代码以下:
  app

//这是继承OnQueryTextListener 的内部类,用于处理搜索框监听事件
public class SearchViewClickListener implements SearchView.OnQueryTextListener {

        @Override
        public boolean onQueryTextSubmit(String s) {
            if (!lastSearchResult.equals(s)){//判断上一个结果和目前查询的是否相同
                System.out.println("上个结果:"+lastSearchResult);
                SearchWordTask task = new SearchWordTask();//新建查询任务
                task.execute("https://api.shanbay.com/bdc/search/?word="+s);//访问网络的地址
                searchResult.setVisibility(View.VISIBLE);//设置查询结果的TextView可见
            }
            lastSearchResult = s;//更新最后查询结果
            System.out.println("最新结果:"+s);
            return true;
        }

        @Override
        public boolean onQueryTextChange(String s) {
            return true;
        }
    }

在访问网络然后传回数据我这里将这个功能提取到了一个工具类,代码以下:异步

public class HttpUtil {

    /**
     * 获取访问网络后传回的数据
     * @param urlString URL
     * @return String
     */
    public static String getJSONResult(String urlString){
        try {
            URL url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36");

            InputStream is = conn.getInputStream();
            byte[] buff = new byte[1024];
            int hasRead;
            StringBuilder result = new StringBuilder("");
            while ((hasRead = is.read(buff)) > 0) {
                result.append(new String(buff, 0, hasRead));
            }
            return result.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

在上面中SearchWordTask是一个继承了AsyncTask的内部类,主要是实现了访问扇贝提供的英文单词查询API,部分代码以下:ide

class SearchWordTask extends AsyncTask<String, Void, String> {

        
        @Override
        protected String doInBackground(String... arg0) {
            //arg0是执行AsyncTask的execute函数传入的可变参数
            //这里arg0[0]是"https://api.shanbay.com/bdc/search/?word="+s
            return HttpUtil.getJSONResult(arg0[0]);
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            if (result == null || "".equals(result)){
                Toast.makeText(getActivity(), "查询出错!", Toast.LENGTH_LONG).show();
            }else
                fillResultForJSON(result);

        }

        /**
         * 解析查询的结果
         * @param JSON JSON数据
         */
        private void fillResultForJSON(String JSON){
            try {
                JSONObject object = new JSONObject(JSON);
                if ("SUCCESS".equals(object.getString("msg"))){
                    final JSONObject dataObject = object.getJSONObject("data");
                    paraphrase.setText("基本释义:"+dataObject.getString("definition"));
                    final String uk_audio = dataObject.getString("uk_audio");
                    final String us_audio = dataObject.getString("us_audio");
                    detail.setOnClickListener(new View.OnClickListener() {
                        //若是详细释义按钮点击则访问以下页面
                        @Override
                        public void onClick(View view) {

                            webView.setVisibility(View.VISIBLE);
                            webView.loadUrl("https://www.shanbay.com/bdc/mobile/preview/word?word="+lastSearchResult);
                            webView.setWebViewClient(new WebViewClient());
                        }
                    });
                    //如下是发音按钮被点击时的监听事件
                    UKButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            try {
                                //使用UKMediaPlayer 播放声音
                                UKMediaPlayer = new MediaPlayer();
                                UKMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                                UKMediaPlayer.setDataSource(uk_audio);
                                UKMediaPlayer.prepare(); // 这个过程可能须要一段时间,例如网上流的读取
                                UKMediaPlayer.start();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    });

                    USButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                           //同上面的播放声音步骤
                           ...
                    });

                    JSONObject pronunciations =dataObject.getJSONObject("pronunciations");
                    UKPronunciation.setText("英式发音:["+pronunciations.getString("uk")+"]");
                    USPronunciation.setText("美式发音:["+pronunciations.getString("us")+"]");
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

以上即是单词查询的主体功能了,固然,考虑文章篇幅因此不能一一解析。

3. 天气查询功能

  在天气查询功能中比较重要的就是使用了网友所写的省市联动功能,这里请参考上面连接中的文章。下面我将不会涉及这方面的讲解,这里主要是说一下访问聚合数据所提供的API,这个功能的效果以下图:

  在上面功能中的业务代码主要是跟上面的单词查询差很少,都是使用了异步查询,由内部类实现,代码以下:
  

class WeatherTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... arg0) {

            try {
                return HttpUtil.getJSONResult(arg0[0] + URLEncoder.encode(arg0[1], "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            if (result != null){
                parseWeatherJSON(result);
            }
        }

        /**
         * 根据JSON数据解析
         * @param result JSON
         */
        private void parseWeatherJSON(String result){
            try {
                JSONObject object = new JSONObject(result);
                if (object.getInt("error_code") == 0){
                    JSONObject resultObj = object.getJSONObject("result");
                    JSONObject todayObj = resultObj.getJSONObject("today");
                    String weatherResult = "温度:"+todayObj.getString("temperature")+"\n";
                    weatherResult += "天气情况:"+todayObj.getString("weather")+"\n";
                    weatherResult += "风向:"+todayObj.getString("wind")+"\n";
                    weatherResult += "穿衣建议:"+todayObj.getString("dressing_advice");
                    todayWeather.setText(weatherResult);
                }else {
                    todayWeather.setText("请求出错!");
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

4. 机器聊天功能

  机器聊天功能是使用了HTML页面来进行人机交互,因此,这里基本上没有涉及到Java上面的问题,主要是加载HTML页面以及开启JavaScript功能,代码以下:

WebView webView = (WebView) rootView.findViewById(R.id.chat_robot);
//加载本地的HTML页面(将文件置于src/main/assets/)       webView.loadUrl("file:///android_asset/chat_robot.html");
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());

  功能的实现效果如图:

  固然了,要是用以上的聊天功能须要注册图灵机器人申请Key,源码中不会提供Key,因此请自行注册。
  在接收图灵机器人返回的数据时,它会有代码来肯定返回的是什么类型,因此,须要咱们来判断类型来进行相应的解析(这里的JS代码就不贴出来了)。

5. 总结

  此次的是一个安卓的期末做业,可是却没有很认真的对待的样子,并且项目仍是不完善的,好比,在查询了单词后作其余功能的操做再次返回单词查询功能则以前的数据不可以保存,用户体验很差。这里固然我也知道一些解决的方案,保存当前的fragment状态,可是,我仍是偷懒了。懒惰真的是宿敌。
  文章上写的详细程度不够,可是主要的代码都已经写出。我知道,有时候解决一个功能并非功能自己,而是要防止功能附带出来的bug,固然了,这就是个人经历。
  还有就是可能我对于面向对象仍是理解上有所误差,对于抽象仍是作得很烂,接下来但愿看看别人的源码来改善这个问题。
  

项目源码已上传GitHubCSDN资源,若是资源分不少的朋友就使用CSDN下载吧。下载后须要去注册相应的Key以后填入,不然没法使用,注册地址在简介中已经给出

相关文章
相关标签/搜索