本項目只是單純的一個大作業,沒有考慮實際的需求,所以有設計不合理的地方,請見諒。 這個項目有三大功能,首先有單詞查詢,其次是天氣查詢,後來是機器聊天功能。單詞查詢是使用了扇貝單詞提供的免費API;天氣查詢是使用了聚合數據提供的天氣API,這裡需要註冊使用(有限的免費使用);機器聊天是使 ...
簡介
現在來分享期末做的安卓大作業——生活百科。
本項目只是單純的一個大作業,沒有考慮實際的需求,所以有設計不合理的地方,請見諒。
這個項目有三大功能(因為是使用了側邊欄所以是可以繼續往裡面添加功能的),首先有單詞查詢,其次是天氣查詢,後來是機器聊天功能。單詞查詢是使用了扇貝單詞提供的免費API;天氣查詢是使用了聚合數據提供的天氣API,這裡需要註冊使用(有限的免費使用);機器聊天是使用了圖靈機器人的API。所以,總結一下,這裡我的主要工作不會很多,主要是調用API然後進行數據的分析和顯示工作。
本次使用的IDE是idea(Android studio)。
文章的最後將會給出源碼,但是一些API介面需要自己去申請Key
在項目開始前的學習階段
安卓基礎入門 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
以上便是我著手項目的累積步驟,希望有幫助
1. 項目準備階段
1.1. 新建項目
使用Android Studio(IDEA)新建安卓項目->選擇SDK版本(Android 4.0為好)->選擇Navigation Drawer Activity模板->完成項目創建。項目新建之後就會得到我們基本的界面模板了。而後,只需要刪除右側邊和底部的元素就可得到下圖所示的界面
當然,這裡使用Android ADT也是可以的,不過好像新建出來的模板不一樣,比較醜一點(自己對於Android的UI不太行),所以就使用了Android Studio。
1.2. 添加依賴
由於需要使用省市聯動的功能,所以需要添加外部依賴,在上面給出的鏈接上有詳細說明,因此需要在app
文件夾下的build.gradle
裡面的dependencies
加入
compile 'com.contrarywind:Android-PickerView:3.2.5'//自定義控制項
compile 'com.google.code.gson:gson:2.7'//解析JSON
做完了準備工作之後就進入主題
2. 單詞查詢功能
考慮文章的篇幅過長,所以有些詳細的過程可能會省略(像界面的修改工作等等)。
當我們輸入了單詞之後點擊查詢是需要訪問網路的,這裡採用了非同步的任務機制去訪問網路並且得出結果,部分代碼如下:
//這是繼承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,部分代碼如下:
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,當然了,這就是我的經歷。
還有就是可能我對於面向對象還是理解上有所偏差,對於抽象還是做得很爛,接下來希望看看別人的源碼來改善這個問題。
項目源碼已上傳GitHub和CSDN資源,如果資源分很多的朋友就使用CSDN下載吧。下載後需要去註冊相應的Key之後填入,否則無法使用,註冊地址在簡介中已經給出