消息推送,类似于社交工具中QQ、微信中的聊天功能,即消息之间的传输,其原理图如下所示:
消息推送的主要特点,是指客户端被动接收服务端的消息,即使客户端和服务端没有相连。而消息推送的应用也不局限于聊天功能,还应用在广告推送、私信推送等
要实现消息推送的技术,就需要引入一个第三方的框架:JPush(极光推送),而JPush的使用,可以参考此篇集成文档:http://docs.jiguang.cn/jpush/client/Android/android_guide/,这里不再详述。
而想用快速创建demo,则可参考http://docs.jiguang.cn/jpush/client/Android/android_3m/来实现,这里不再详述
想要进行极光推送的高级使用,可参考http://docs.jiguang.cn/jpush/client/Android/android_api/,这里不再详述
在客户端和服务端之间,一般进行一次数据的发送和接收后就会断开相互的连接。然而,在消息推送中,这样的连接在数据传输的过程中不会断开,则称为长连接
在Http1.1之后,支持长连接
xmpp协议,专门适用于消息推送,此种协议更加精简,没有过多冗余的数据
socket,套接字,网络底层实现
TCP、UDP,传输协议
心跳包:客户端每隔一段时间(比如说30秒)向服务器发送一段极短的数据,来证明自己还“活着”
要实现这个功能,同样需要借助一个第三方框架——科大讯飞语音云,官方网站为:https://www.xfyun.cn/
在这里要实现语音听写的功能,网站为:https://www.xfyun.cn/services/voicedictation
这里不再详述
在这里要实现语音合成的功能,网站为:https://www.xfyun.cn/services/online_tts
这里不再详述
通过科大讯飞的这些api,可以实现一个简单的聊天机器人的应用
聊天菜单可用ListView来实现,而每一条聊天记录可用item来实现
<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>
<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>
前面将布局搭建好了,接下来就是为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;
}
}
}
<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>
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;
}
}
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;
}
}
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;
}
}
现在我们完成了数据的填充,接下来就要开始运用到科大讯飞的语音听写api了
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();
}
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;
}
}
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;
}
}
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();
}
之前创建好了提问的对象,现在就来创建回答的对象
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;
}
}
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;
}
}
统计,顾名思义,作用是统计应用的各种访问流量数据,这里要使用一个第三方的SDK——友盟统计,官网为:https://www.umeng.com/,官网上有相关使用教程
这里不再详述
友盟指数(现在更名为全域罗盘),是友盟自己对于应用这个SDK所进行的各种统计数据,可以在友盟的官网上查看:https://compass.umeng.com/
二维码,在日常生活中很常见,一般扫描后会显示详情信息,如图所示:
其中,位于左上、左下、右上角都有一个独特的黑点,是作为二维码的特有标识点,而黑白相继出现的方块,则代表着计算机中的0和1
同样的,由于二维码底层实现复杂,因此这里同样引入一个第三方框架——ZXing来实现二维码的逻辑
DynamicGrid,是一种可拖拽的GridVew,可以用于实现频道的管理,如图所示: