Android项目实践:黄金报价

来源:互联网 发布:c语言的发展历程 编辑:程序博客网 时间:2024/04/27 20:32

最近和朋友合作给别人写了一个APP,该APP功能比较简单,主要实现了一下功能:从网络获取黄金的现价,展示在主界面并实现自动播报该价格,并不断循环这个过程。现在开始逐步分析各个功能该如何实现。


一、从网络获取黄金的现价

1、下面先完成执行网络请求的工具类:GetUtil.java

<span style="font-size:14px;">public class GetUtil {    public static String sendGet(String url)    {        String result="";        BufferedReader in=null;        try{            String urlName=url;            URL realUrl=new URL(urlName);            //打开和URL之间的连接            URLConnection conn=realUrl.openConnection();            //设置通用的请求属性            conn.setRequestProperty("accept", "*/*");            conn.setRequestProperty("connection", "Keep-Alive");            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible;MSIE 6.0;Windows NT 5.1;SV1)");            //建立实际连接            conn.connect();            //定义BufferedReader输入流来读取URL响应            in=new BufferedReader(new InputStreamReader(conn.getInputStream()));            String line;            //逐行读取数据,如果数据不为空,则放入result中            while((line=in.readLine())!=null)            {                result+="\n"+line;            }        } catch (MalformedURLException e) {            e.printStackTrace();        } catch (IOException e) {            //如果网络异常,获取数据失败,返回空            result="";            return result;            //e.printStackTrace();        }        finally {            //释放资源            try{                if(in!=null)                {                    in.close();                }            } catch (IOException e) {                e.printStackTrace();            }        }        return result;    }}</span>
2、对特定网页进行解析,由于黄金的实时价格在某个网站上实时刷新,所以我们可以抓取这个网页的html源码,然后利用正则表达式匹配出需要提取的内容:

这里给出一个网页:http://www.sincerehk.com/zh-hk/index.aspx

对其HTML源码进行分析:

<td  width=22% height=18 valign=top class=big>      <div align=left>港金</div>    </td>     <td width=35% valign=top class=big_b>      <div align=left>11,376<!--買 / 賣--></div>

<td  width=22% height=18 valign=top class=big>       <div align=left>倫敦金</div>    </td> <td width=35% valign=top class=big_b>      <div align=left>1225.40<!--買 / 賣--></div>

我们需要提取的是其中的数字,所以正则表达式可以写成这样:

<.*?>\\w*金<.*?><.*?> <.*?><.*?>(.*?)<!--.*?/.*?--><.*?>

得到正则表达式后,我们可以利用java的Pattern类和Matcher类实现匹配,代码片段如下:

Pattern p = Pattern.compile("<.*?>\\w*金<.*?><.*?> <.*?><.*?>(.*?)<!--.*?/.*?--><.*?>");Matcher m = p.matcher(response);  //response为获取的数据字符串while (m.find()) {    MatchResult mr = m.toMatchResult();    gold[i] = mr.group(1);      //将匹配成功的字符串放进一个字符串数组    i++;    }
3、由于网路操作是耗时操作,所以我们需要在子线程完成以上操作:以下是部分的MainActivity.java:
thread =  new Thread()     {        @Override        public void run() {            while (true){                try {                    lock.lock();  //对该线程进行加锁                    int i = 0;                    gold = new String[2];                    response = GetUtil.sendGet("http://www.sincerehk.com/zh-hk/index.aspx");                      //如果获取数据失败                                     if(response=="") {                        handler.sendEmptyMessage(0x123);                        break; //直接跳出循环                        }                    //正则表达匹配数据                    Pattern p = Pattern.compile("<.*?>\\w*金<.*?><.*?> <.*?><.*?>(.*?)<!--.*?/.*?--><.*?>");                    Matcher m = p.matcher(response);                        while (m.find()) {                            MatchResult mr = m.toMatchResult();                            gold[i] = mr.group(1);                            i++;                            }                    //发送通知,告诉主线程刷新数据以及播报语音                    handler.sendEmptyMessage(0x123);                    //阻塞该线程,等待通知                    cond.await();                    }catch (InterruptedException e){                        e.printStackTrace();                    }catch (JSONException e) {                        e.printStackTrace();                    }finally {                        lock.unlock();                            }                        }                    }                };thread.start();

二、语音播报获取的数据
  这里使用百度语音在线合成的API,先去百度语音开放平台注册成为开发者,然后他会有详细教程,这里不再赘述。导入所需的sdk包后,在MainActivity.java文件里面,只需写下如下代码即可:
speechSynthesizer  = new SpeechSynthesizer(getApplicationContext(),"holder" ,MainActivity.this);speechSynthesizer.setApiKey("TBSiHQcwMTsAmDUzh386tash", "40cd364811b4933b2133ff3qw313ceff");speechSynthesizer.speak(floatGoldPrice); //这里传入需要读出的内容
三、循环
  为了实现播放完语音后,自动开始获取新的数据并且再次刷新以及播报,我们需要在主线程和子线程之间进行通信,思路如下:在子线程获取数据结束后,即如上面代码所示,将该线程await()阻塞,然后在Handler中,写刷新数据和播报语音的代码,由于播报语音使用了百度在线语音合成的SDK,该SDK提供了一个监听语音的接口:SpeechSynthesizerListener,实现该接口以及其未完成的方法,其中有一个方法是onSpeechFinish(SpeechSynthesizer synthesizer)用于实现朗读完成后的方法,所以我们可以在这个方法内写入如下代码:
@Overridepublic void onSpeechFinish(SpeechSynthesizer synthesizer) {        try{            lock.lock();     //加锁            cond.signalAll(); //唤醒子线程            lock.unlock();  //释放锁        }catch (Exception e){            e.printStackTrace();        }    }
以上,就是完成该项目的全部思路和流程,下面附上完整的MainActivity.java,由于UI界面过于简单,只有两个按钮,一个文本框,所以就不提供了。
package org.gold.goldpriceplay;import android.annotation.TargetApi;import android.os.Build;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.speech.tts.TextToSpeech;import android.speech.tts.UtteranceProgressListener;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import com.baidu.speechsynthesizer.SpeechSynthesizer;import com.baidu.speechsynthesizer.SpeechSynthesizerListener;import com.baidu.speechsynthesizer.publicutility.SpeechError;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import java.math.BigDecimal;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;import java.util.regex.MatchResult;import java.util.regex.Matcher;import java.util.regex.Pattern;//import com.baidu.tts.client.SpeechError;//import com.baidu.tts.client.SpeechSynthesizer;//import com.baidu.tts.client.SpeechSynthesizerListener;public class MainActivity extends AppCompatActivity implements SpeechSynthesizerListener {    Button get;    Button stop ;    TextToSpeech tts;    private SpeechSynthesizer speechSynthesizer;    //    0代表执行抓取    boolean flag = false ;    private final Lock lock = new ReentrantLock();    private final Condition cond = lock.newCondition();    Thread thread;    TextView London;    //代表服务器响应的字符串    String response;    String[] gold = new String[2];    Handler handler=new Handler() {        @TargetApi(Build.VERSION_CODES.LOLLIPOP)        @Override        public void handleMessage(Message msg) {            if(msg.what==0x123)            {                if(response=="")                {                    get.setEnabled(true);                    stop.setEnabled(false);                    Toast.makeText(MainActivity.this,"您的网络连接有问题,请重试",Toast.LENGTH_SHORT).show();                }else {                    speechSynthesizer.speak(gold[0]);                    London.setText(gold[0]);                }            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.content_main);        get= (Button) findViewById(R.id.start);        stop = ( Button )findViewById(R.id.stop);        stop.setEnabled(false);        speechSynthesizer  = new SpeechSynthesizer(getApplicationContext(),"holder" ,MainActivity.this);        speechSynthesizer.setApiKey("TBSiHQcwMTsAmDUzh386t7hh", "40cd364811b4933b2133ff35d313ceff");        London= (TextView) findViewById(R.id.LondonPrice);        get.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                get.setEnabled(false);                flag = true;                stop.setEnabled(true);                thread =  new Thread() {                    @Override                    public void run() {                        while (flag){                            try {                                lock.lock();                                int i = 0;                                gold = new String[2];                                response = GetUtil.sendGet("http://www.sincerehk.com/zh-hk/index.aspx");                                if(response=="") {                                    handler.sendEmptyMessage(0x123);                                    break;                                }                               Pattern p = Pattern.compile("<.*?>\\w*金<.*?><.*?> <.*?><.*?>(.*?)<!--.*?/.*?--><.*?>");                               Matcher m = p.matcher(response);                                while (m.find()) {                                    MatchResult mr = m.toMatchResult();                                    gold[i] = mr.group(1);                                    i++;                                }                                handler.sendEmptyMessage(0x123);                                cond.await();                            }catch (InterruptedException e){                                e.printStackTrace();                            } catch (JSONException e) {                                Log.d("chenyu", "json错误");                                e.printStackTrace();                            }finally {                                lock.unlock();                            }                        }                    }                };                thread.start();            }        });        stop.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                flag = false;                get.setEnabled(true);                stop.setEnabled(false);            }        });    }    @Override    public void onStartWorking(SpeechSynthesizer synthesizer) {//        logDebug("开始工作,请等待数据...");    }    @Override    public void onSpeechStart(SpeechSynthesizer synthesizer) {//        logDebug("朗读开始");    }    @Override    public void onSpeechResume(SpeechSynthesizer synthesizer) {//        logDebug("朗读继续");    }    @Override    public void onSpeechProgressChanged(SpeechSynthesizer synthesizer,                                        int progress) {        // TODO Auto-generated method stub    }    @Override    public void onSpeechPause(SpeechSynthesizer synthesizer) {//        logDebug("朗读已暂停");    }    @Override    public void onSynthesizeFinish(SpeechSynthesizer arg0) {        // TODO Auto-generated method stub    }    @Override    public void onSpeechFinish(SpeechSynthesizer synthesizer) {//        logDebug("朗读已停止");        try{            lock.lock();            cond.signalAll();            lock.unlock();        }catch (Exception e){            e.printStackTrace();        }    }    @Override    public void onBufferProgressChanged(SpeechSynthesizer synthesizer,                                        int progress) {        // TODO Auto-generated method stub    }    @Override    public void onCancel(SpeechSynthesizer synthesizer) {//        logDebug("已取消");    }    @Override    public void onError(SpeechSynthesizer synthesizer, SpeechError error) {//        logError("发生错误:" + error.errorDescription + "(" + error.errorCode + ")");    }    @Override    public void onNewDataArrive(SpeechSynthesizer synthesizer,                                byte[] audioData, boolean isLastData) {//        logDebug("新的音频数据:" + audioData.length + (isLastData ? "(end)" : ""));    }}






  


2 0
原创粉丝点击