Android开发实战《智慧北京》——7.项目拓展

文章目录

  • 1.极光推送
    • 1.1 基本使用
    • 1.2 极光推送的高级使用
    • 1.3 推送原理介绍
  • 2.科大讯飞
    • 2.1 语音听写
    • 2.2 语音合成
    • 2.3 聊天机器人:布局搭建
    • 2.4 聊天机器人:数据填充
    • 2.5 聊天机器人:语音数据解析 & 展示提问对象
    • 2.6 聊天机器人:展示回答对象 & 朗读回答
  • 3.友盟统计
    • 3.1 介绍 & SDK使用
    • 3.2 友盟指数
  • 4.ZXing
  • 5.DynamicGrid

1.极光推送

1.1 基本使用

消息推送,类似于社交工具中QQ、微信中的聊天功能,即消息之间的传输,其原理图如下所示:

Android开发实战《智慧北京》——7.项目拓展_第1张图片

消息推送的主要特点,是指客户端被动接收服务端的消息,即使客户端服务端没有相连。而消息推送的应用也不局限于聊天功能,还应用在广告推送、私信推送等

要实现消息推送的技术,就需要引入一个第三方的框架:JPush(极光推送),而JPush的使用,可以参考此篇集成文档:http://docs.jiguang.cn/jpush/client/Android/android_guide/,这里不再详述。

而想用快速创建demo,则可参考http://docs.jiguang.cn/jpush/client/Android/android_3m/来实现,这里不再详述

1.2 极光推送的高级使用

想要进行极光推送的高级使用,可参考http://docs.jiguang.cn/jpush/client/Android/android_api/,这里不再详述

1.3 推送原理介绍

在客户端和服务端之间,一般进行一次数据的发送和接收后就会断开相互的连接。然而,在消息推送中,这样的连接在数据传输的过程中不会断开,则称为长连接

  • Http1.1之后,支持长连接

  • xmpp协议,专门适用于消息推送,此种协议更加精简,没有过多冗余的数据

  • socket,套接字,网络底层实现

  • TCPUDP,传输协议

  • 心跳包:客户端每隔一段时间(比如说30秒)向服务器发送一段极短的数据,来证明自己还“活着”

2.科大讯飞

2.1 语音听写

要实现这个功能,同样需要借助一个第三方框架——科大讯飞语音云,官方网站为:https://www.xfyun.cn/

在这里要实现语音听写的功能,网站为:https://www.xfyun.cn/services/voicedictation

这里不再详述

2.2 语音合成

在这里要实现语音合成的功能,网站为:https://www.xfyun.cn/services/online_tts

这里不再详述

2.3 聊天机器人:布局搭建

通过科大讯飞的这些api,可以实现一个简单的聊天机器人的应用

聊天菜单可用ListView来实现,而每一条聊天记录可用item来实现

  1. 新建一个项目,导入科大讯飞的jar包,然后修改activity_main.xml,在此之前导入相关图片资源,代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ListView
        android:id="@+id/lv_list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:divider="@null"
        android:layout_weight="1"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/bottom_bar">

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/btn_selector"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:onClick="startVoice"
            android:text="点击开始语音识别"/>
    RelativeLayout>
LinearLayout>
  1. 在drawable目录下建立按钮的状态选择器文件btn_selector.xml,代码如下:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true" android:drawable="@drawable/btn_voice_search_pressed"/>
    <item android:drawable="@drawable/btn_voice_search_normal"/>

selector>

2.4 聊天机器人:数据填充

前面将布局搭建好了,接下来就是为ListView填充数据

  1. 修改MainActivity,获取ListView的实例,并且注册适配器,代码如下:
package com.example.chatrobot;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;


public class MainActivity extends AppCompatActivity {

    private ListView lvList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lvList = findViewById(R.id.lv_list);
    }

    public void startVoice(View view){

    }

    class ChatAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return 0;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return null;
        }
    }
}
  1. 建立ListView的子布局文件list_item.xml,代码如下:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv_ask"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:background="@drawable/asker_bubble"
        android:gravity="center"
        android:paddingLeft="10dp"
        android:paddingRight="15dp"
        android:textColor="#000"
        android:textSize="16sp"
        android:text="提问"/>

    <LinearLayout
        android:id="@+id/ll_answer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:paddingLeft="15dp"
        android:paddingRight="10dp"
        android:layout_below="@id/tv_ask"
        android:background="@drawable/answer_bubble"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_answer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textColor="#000"
            android:textSize="16sp"
            android:text="回答"/>

        <ImageView
            android:id="@+id/iv_answer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            android:src="@drawable/p1"/>
    LinearLayout>
RelativeLayout>
  1. 修改MainActivity,引用刚刚创建好的布局,并创建内部类ViewHolder,代码如下:
package com.example.chatrobot;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;


public class MainActivity extends AppCompatActivity {

    private ListView lvList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lvList = findViewById(R.id.lv_list);
    }

    public void startVoice(View view){

    }

    class ChatAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return 0;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null){
                convertView = View.inflate(getApplicationContext(),R.layout.list_item,null);
                holder = new ViewHolder();
                holder.tvAsk = convertView.findViewById(R.id.tv_ask);
                holder.tvAnswer = convertView.findViewById(R.id.tv_answer);
                holder.llAnswer = convertView.findViewById(R.id.ll_answer);
                holder.ivAnswer = convertView.findViewById(R.id.iv_answer);
                convertView.setTag(holder);
            }else {
                holder = (ViewHolder) convertView.getTag();
            }
            return convertView;
        }
    }

    static class ViewHolder{
        public TextView tvAsk;
        public TextView tvAnswer;
        public LinearLayout llAnswer;
        public ImageView ivAnswer;
    }
}
  1. 建立TalkBean类,作为每句对话的实体类对象,代码如下:
package com.example.chatrobot;

public class TalkBean {

    public String content;
    public boolean isAsk;
    public int imageId = -1;

    public TalkBean(String content, boolean isAsk, int imageId) {
        this.content = content;
        this.isAsk = isAsk;
        this.imageId = imageId;
    }
}
  1. 修改MainActivity,用ArrayList来存储刚刚创建好的对象,并且进行相应调用,将ListView和Adapter进行匹配,代码如下:
package com.example.chatrobot;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;


public class MainActivity extends AppCompatActivity {

    private ListView lvList;

    private ArrayList<TalkBean> mTalkList = new ArrayList<>();

    private ChatAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lvList = findViewById(R.id.lv_list);
        mAdapter = new ChatAdapter();
        lvList.setAdapter(mAdapter);
    }

    public void startVoice(View view){

    }

    class ChatAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return mTalkList.size();
        }

        @Override
        public TalkBean getItem(int position) {
            return mTalkList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null){
                convertView = View.inflate(getApplicationContext(),R.layout.list_item,null);
                holder = new ViewHolder();
                holder.tvAsk = convertView.findViewById(R.id.tv_ask);
                holder.tvAnswer = convertView.findViewById(R.id.tv_answer);
                holder.llAnswer = convertView.findViewById(R.id.ll_answer);
                holder.ivAnswer = convertView.findViewById(R.id.iv_answer);
                convertView.setTag(holder);
            }else {
                holder = (ViewHolder) convertView.getTag();
            }

            TalkBean item = getItem(position);
            if (item.isAsk){
                // 提问
                holder.tvAsk.setVisibility(View.VISIBLE);
                holder.llAnswer.setVisibility(View.GONE);
                holder.tvAsk.setText(item.content);
            }else {
                holder.tvAsk.setVisibility(View.GONE);
                holder.llAnswer.setVisibility(View.VISIBLE);
                holder.tvAnswer.setText(item.content);
                if (item.imageId > 0){
                    // 有图片
                    holder.ivAnswer.setVisibility(View.VISIBLE);
                    holder.ivAnswer.setImageResource(item.imageId);
                }else {
                    // 无图片
                    holder.ivAnswer.setVisibility(View.GONE);
                }
            }
            return convertView;
        }
    }

    static class ViewHolder{
        public TextView tvAsk;
        public TextView tvAnswer;
        public LinearLayout llAnswer;
        public ImageView ivAnswer;
    }
}

2.5 聊天机器人:语音数据解析 & 展示提问对象

现在我们完成了数据的填充,接下来就要开始运用到科大讯飞的语音听写api了

  1. 修改MainActivity,完善startVoice()方法,代码如下:
public void startVoice(View view){
        RecognizerDialog mDialog = new RecognizerDialog(this, null);
        mDialog.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
        mDialog.setParameter(SpeechConstant.ACCENT,"mandarin");
        mDialog.setListener(new RecognizerDialogListener() {
            @Override
            public void onResult(RecognizerResult recognizerResult, boolean b) {
                String result = recognizerResult.getResultString();
            }

            @Override
            public void onError(SpeechError speechError) {

            }
        });
        mDialog.show();
    }
  1. 由于要使用GSON来解析语音识别后的JSON数据,这里需要创建一个实体类VoiceBean,代码如下:
package com.example.chatrobot;

import java.util.ArrayList;

public class VoiceBean {

    public ArrayList<WsBean> ws;

    public class WsBean{
        public ArrayList<CwBean> cw;
    }

    public class CwBean{
        public String w;
    }
}
  1. 修改MainActivity,添加processData()方法,引入GSON来解析json数据,代码如下:
package com.example.chatrobot;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.google.gson.Gson;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;

import java.util.ArrayList;


public class MainActivity extends AppCompatActivity {

    private ListView lvList;

    private ArrayList<TalkBean> mTalkList = new ArrayList<>();

    private ChatAdapter mAdapter;

    private StringBuffer mBuffer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SpeechUtility.createUtility(this, SpeechConstant.APPID +"=5bfca40b");
        lvList = findViewById(R.id.lv_list);
        mAdapter = new ChatAdapter();
        lvList.setAdapter(mAdapter);

    }

    public void startVoice(View view){
        RecognizerDialog mDialog = new RecognizerDialog(this, null);
        mDialog.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
        mDialog.setParameter(SpeechConstant.ACCENT,"mandarin");
        mBuffer = new StringBuffer();
        mDialog.setListener(new RecognizerDialogListener() {
            @Override
            public void onResult(RecognizerResult recognizerResult, boolean b) {
                String result = recognizerResult.getResultString();
                String resultStriing = processData(result);
                mBuffer.append(resultStriing);
                if (b){
                    // 话已经说完了
                    String finalResult = mBuffer.toString();
                }
            }

            @Override
            public void onError(SpeechError speechError) {

            }
        });
        mDialog.show();
    }

    private String processData(String result) {
        Gson gson = new Gson();
        VoiceBean voiceBean = gson.fromJson(result, VoiceBean.class);
        StringBuffer sb = new StringBuffer();
        for (VoiceBean.WsBean ws : voiceBean.ws) {
            String word = ws.cw.get(0).w;
            sb.append(word);
        }
        return sb.toString();
    }

    class ChatAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return mTalkList.size();
        }

        @Override
        public TalkBean getItem(int position) {
            return mTalkList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null){
                convertView = View.inflate(getApplicationContext(),R.layout.list_item,null);
                holder = new ViewHolder();
                holder.tvAsk = convertView.findViewById(R.id.tv_ask);
                holder.tvAnswer = convertView.findViewById(R.id.tv_answer);
                holder.llAnswer = convertView.findViewById(R.id.ll_answer);
                holder.ivAnswer = convertView.findViewById(R.id.iv_answer);
                convertView.setTag(holder);
            }else {
                holder = (ViewHolder) convertView.getTag();
            }

            TalkBean item = getItem(position);
            if (item.isAsk){
                // 提问
                holder.tvAsk.setVisibility(View.VISIBLE);
                holder.llAnswer.setVisibility(View.GONE);
                holder.tvAsk.setText(item.content);
            }else {
                holder.tvAsk.setVisibility(View.GONE);
                holder.llAnswer.setVisibility(View.VISIBLE);
                holder.tvAnswer.setText(item.content);
                if (item.imageId > 0){
                    // 有图片
                    holder.ivAnswer.setVisibility(View.VISIBLE);
                    holder.ivAnswer.setImageResource(item.imageId);
                }else {
                    // 无图片
                    holder.ivAnswer.setVisibility(View.GONE);
                }
            }
            return convertView;
        }
    }

    static class ViewHolder{
        public TextView tvAsk;
        public TextView tvAnswer;
        public LinearLayout llAnswer;
        public ImageView ivAnswer;
    }
}
  1. 修改MainActivity,修改startVoice()方法,将解析后的字符串初始化为提问语句,并添加到集合中,代码如下:
public void startVoice(View view){
        RecognizerDialog mDialog = new RecognizerDialog(this, null);
        mDialog.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
        mDialog.setParameter(SpeechConstant.ACCENT,"mandarin");
        mBuffer = new StringBuffer();
        mDialog.setListener(new RecognizerDialogListener() {
            @Override
            public void onResult(RecognizerResult recognizerResult, boolean b) {
                String result = recognizerResult.getResultString();
                String resultStriing = processData(result);
                mBuffer.append(resultStriing);
                if (b){
                    // 话已经说完了
                    String finalResult = mBuffer.toString();

                    // 初始化提问对象
                    TalkBean askBean = new TalkBean(finalResult,true,-1);
                    mTalkList.add(askBean);
                    mAdapter.notifyDataSetChanged(); // 刷新ListView
                }
            }

            @Override
            public void onError(SpeechError speechError) {

            }
        });
        mDialog.show();
    }

2.6 聊天机器人:展示回答对象 & 朗读回答

之前创建好了提问的对象,现在就来创建回答的对象

  1. 修改MainActivity,修改startVoice()方法,初始化提问对象,编写回话逻辑,代码如下:
package com.example.chatrobot;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.google.gson.Gson;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;

import java.util.ArrayList;


public class MainActivity extends AppCompatActivity {

    private ListView lvList;

    private ArrayList<TalkBean> mTalkList = new ArrayList<>();

    private ChatAdapter mAdapter;

    private StringBuffer mBuffer;

    private String[] mAnswers = new String[]{"约吗?","这张怎么样?","100块啦","不要再要啦","最后一张啦"};

    private int[] mImageIds = new int[]{R.drawable.p1,R.drawable.p2,R.drawable.p3,R.drawable.p4};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SpeechUtility.createUtility(this, SpeechConstant.APPID +"=5bfca40b");
        lvList = findViewById(R.id.lv_list);
        mAdapter = new ChatAdapter();
        lvList.setAdapter(mAdapter);

    }

    public void startVoice(View view){
        RecognizerDialog mDialog = new RecognizerDialog(this, null);
        mDialog.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
        mDialog.setParameter(SpeechConstant.ACCENT,"mandarin");
        mBuffer = new StringBuffer();
        mDialog.setListener(new RecognizerDialogListener() {
            @Override
            public void onResult(RecognizerResult recognizerResult, boolean b) {
                String result = recognizerResult.getResultString();
                String resultStriing = processData(result);
                mBuffer.append(resultStriing);
                if (b){
                    // 话已经说完了
                    String finalResult = mBuffer.toString();

                    // 初始化提问对象
                    TalkBean askBean = new TalkBean(finalResult,true,-1);
                    mTalkList.add(askBean);

                    // 初始化回答对象
                    String answerContent = "没听清";
                    int imageId = -1;
                    if (finalResult.contains("你好")){
                        answerContent = "你好呀!";
                    }else if (finalResult.contains("你是谁")){
                        answerContent = "我是你的小助手!";
                    }else if (finalResult.contains("美女")){
                        // 随机回答
                        int i = (int) (Math.random() * mAnswers.length);
                        answerContent = mAnswers[i];
                        // 随机图片
                        int j = (int) (Math.random() * mImageIds.length);
                        imageId = mImageIds[j];
                    }else if (finalResult.contains("天王盖地虎")){
                        answerContent = "小鸡炖蘑菇";
                        imageId = R.drawable.m;
                    }
                    TalkBean answerBean = new TalkBean(answerContent,false,imageId);
                    mTalkList.add(answerBean);
                    mAdapter.notifyDataSetChanged(); // 刷新ListView
                    lvList.setSelection(mTalkList.size() - 1);// 显示在最后一个Item上
                }
            }

            @Override
            public void onError(SpeechError speechError) {

            }
        });
        mDialog.show();
    }

    private String processData(String result) {
        Gson gson = new Gson();
        VoiceBean voiceBean = gson.fromJson(result, VoiceBean.class);
        StringBuffer sb = new StringBuffer();
        for (VoiceBean.WsBean ws : voiceBean.ws) {
            String word = ws.cw.get(0).w;
            sb.append(word);
        }
        return sb.toString();
    }

    class ChatAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return mTalkList.size();
        }

        @Override
        public TalkBean getItem(int position) {
            return mTalkList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null){
                convertView = View.inflate(getApplicationContext(),R.layout.list_item,null);
                holder = new ViewHolder();
                holder.tvAsk = convertView.findViewById(R.id.tv_ask);
                holder.tvAnswer = convertView.findViewById(R.id.tv_answer);
                holder.llAnswer = convertView.findViewById(R.id.ll_answer);
                holder.ivAnswer = convertView.findViewById(R.id.iv_answer);
                convertView.setTag(holder);
            }else {
                holder = (ViewHolder) convertView.getTag();
            }

            TalkBean item = getItem(position);
            if (item.isAsk){
                // 提问
                holder.tvAsk.setVisibility(View.VISIBLE);
                holder.llAnswer.setVisibility(View.GONE);
                holder.tvAsk.setText(item.content);
            }else {
                holder.tvAsk.setVisibility(View.GONE);
                holder.llAnswer.setVisibility(View.VISIBLE);
                holder.tvAnswer.setText(item.content);
                if (item.imageId > 0){
                    // 有图片
                    holder.ivAnswer.setVisibility(View.VISIBLE);
                    holder.ivAnswer.setImageResource(item.imageId);
                }else {
                    // 无图片
                    holder.ivAnswer.setVisibility(View.GONE);
                }
            }
            return convertView;
        }
    }

    static class ViewHolder{
        public TextView tvAsk;
        public TextView tvAnswer;
        public LinearLayout llAnswer;
        public ImageView ivAnswer;
    }
}
  1. 修改MainActivity,添加startSpeak()方法,用于将回答内容朗诵出来,代码如下:
package com.example.chatrobot;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.google.gson.Gson;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;

import java.util.ArrayList;


public class MainActivity extends AppCompatActivity {

    private ListView lvList;

    private ArrayList<TalkBean> mTalkList = new ArrayList<>();

    private ChatAdapter mAdapter;

    private StringBuffer mBuffer;

    private String[] mAnswers = new String[]{"约吗?","这张怎么样?","100块啦","不要再要啦","最后一张啦"};

    private int[] mImageIds = new int[]{R.drawable.p1,R.drawable.p2,R.drawable.p3,R.drawable.p4};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SpeechUtility.createUtility(this, SpeechConstant.APPID +"=5bfca40b");
        lvList = findViewById(R.id.lv_list);
        mAdapter = new ChatAdapter();
        lvList.setAdapter(mAdapter);

    }

    public void startVoice(View view){
        RecognizerDialog mDialog = new RecognizerDialog(this, null);
        mDialog.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
        mDialog.setParameter(SpeechConstant.ACCENT,"mandarin");
        mBuffer = new StringBuffer();
        mDialog.setListener(new RecognizerDialogListener() {
            @Override
            public void onResult(RecognizerResult recognizerResult, boolean b) {
                String result = recognizerResult.getResultString();
                String resultStriing = processData(result);
                mBuffer.append(resultStriing);
                if (b){
                    // 话已经说完了
                    String finalResult = mBuffer.toString();

                    // 初始化提问对象
                    TalkBean askBean = new TalkBean(finalResult,true,-1);
                    mTalkList.add(askBean);

                    // 初始化回答对象
                    String answerContent = "没听清";
                    int imageId = -1;
                    if (finalResult.contains("你好")){
                        answerContent = "你好呀!";
                    }else if (finalResult.contains("你是谁")){
                        answerContent = "我是你的小助手!";
                    }else if (finalResult.contains("美女")){
                        // 随机回答
                        int i = (int) (Math.random() * mAnswers.length);
                        answerContent = mAnswers[i];
                        // 随机图片
                        int j = (int) (Math.random() * mImageIds.length);
                        imageId = mImageIds[j];
                    }else if (finalResult.contains("天王盖地虎")){
                        answerContent = "小鸡炖蘑菇";
                        imageId = R.drawable.m;
                    }
                    TalkBean answerBean = new TalkBean(answerContent,false,imageId);
                    mTalkList.add(answerBean);
                    mAdapter.notifyDataSetChanged(); // 刷新ListView
                    lvList.setSelection(mTalkList.size() - 1);// 显示在最后一个Item上
                    startSpeak(answerContent);
                }
            }

            @Override
            public void onError(SpeechError speechError) {

            }
        });
        mDialog.show();
    }

    private void startSpeak(String answerContent) {
        SpeechSynthesizer synthesizer = SpeechSynthesizer.createSynthesizer(this, null);
        synthesizer.setParameter(SpeechConstant.VOICE_NAME,"xiaoyan");
        synthesizer.setParameter(SpeechConstant.SPEED,"50");
        synthesizer.setParameter(SpeechConstant.VOLUME,"80");
        synthesizer.setParameter(SpeechConstant.ENGINE_TYPE,SpeechConstant.TYPE_CLOUD);
        synthesizer.setParameter(SpeechConstant.TTS_AUDIO_PATH,"./sdcard/iflytek.pcm");
        synthesizer.startSpeaking(answerContent,null);
    }

    private String processData(String result) {
        Gson gson = new Gson();
        VoiceBean voiceBean = gson.fromJson(result, VoiceBean.class);
        StringBuffer sb = new StringBuffer();
        for (VoiceBean.WsBean ws : voiceBean.ws) {
            String word = ws.cw.get(0).w;
            sb.append(word);
        }
        return sb.toString();
    }

    class ChatAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return mTalkList.size();
        }

        @Override
        public TalkBean getItem(int position) {
            return mTalkList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null){
                convertView = View.inflate(getApplicationContext(),R.layout.list_item,null);
                holder = new ViewHolder();
                holder.tvAsk = convertView.findViewById(R.id.tv_ask);
                holder.tvAnswer = convertView.findViewById(R.id.tv_answer);
                holder.llAnswer = convertView.findViewById(R.id.ll_answer);
                holder.ivAnswer = convertView.findViewById(R.id.iv_answer);
                convertView.setTag(holder);
            }else {
                holder = (ViewHolder) convertView.getTag();
            }

            TalkBean item = getItem(position);
            if (item.isAsk){
                // 提问
                holder.tvAsk.setVisibility(View.VISIBLE);
                holder.llAnswer.setVisibility(View.GONE);
                holder.tvAsk.setText(item.content);
            }else {
                holder.tvAsk.setVisibility(View.GONE);
                holder.llAnswer.setVisibility(View.VISIBLE);
                holder.tvAnswer.setText(item.content);
                if (item.imageId > 0){
                    // 有图片
                    holder.ivAnswer.setVisibility(View.VISIBLE);
                    holder.ivAnswer.setImageResource(item.imageId);
                }else {
                    // 无图片
                    holder.ivAnswer.setVisibility(View.GONE);
                }
            }
            return convertView;
        }
    }

    static class ViewHolder{
        public TextView tvAsk;
        public TextView tvAnswer;
        public LinearLayout llAnswer;
        public ImageView ivAnswer;
    }
}

3.友盟统计

3.1 介绍 & SDK使用

统计,顾名思义,作用是统计应用的各种访问流量数据,这里要使用一个第三方的SDK——友盟统计,官网为:https://www.umeng.com/,官网上有相关使用教程

这里不再详述

3.2 友盟指数

友盟指数(现在更名为全域罗盘),是友盟自己对于应用这个SDK所进行的各种统计数据,可以在友盟的官网上查看:https://compass.umeng.com/

4.ZXing

二维码,在日常生活中很常见,一般扫描后会显示详情信息,如图所示:

Android开发实战《智慧北京》——7.项目拓展_第2张图片

其中,位于左上、左下、右上角都有一个独特的黑点,是作为二维码的特有标识点,而黑白相继出现的方块,则代表着计算机中的0和1

同样的,由于二维码底层实现复杂,因此这里同样引入一个第三方框架——ZXing来实现二维码的逻辑

5.DynamicGrid

DynamicGrid,是一种可拖拽的GridVew,可以用于实现频道的管理,如图所示:

Android开发实战《智慧北京》——7.项目拓展_第3张图片

你可能感兴趣的