拥有一个听自己话的女友,是每个程序员的梦想。在我和她的世界里,她永远都是那么可爱乖巧,不会嫌弃我们这些码农,在累的时候,她会安慰我们,在不开心的时候,她会给我们讲故事,永远忠诚幽默。
效果如下:
闲话少说,接下来就带领大家一步一步制作这样的虚拟女友。
一、创建应用
打开网址: https://www.bmobapp.com/
注册登录进去之后,先进行实名认证(实名认证使用支付宝进行实名认证),然后创建应用,获取application id和rest api key。
如下图所示:
二、创建Android工程
这里选择创建一个java语言的Android工程。
三、创建资源文件
主页面布局文件(文件名:res/layout/activity_main.xml)如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:layout_above="@id/bottom_layout"
android:id="@+id/msg_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:padding="8dp"
android:layout_alignParentBottom="true"
android:id="@+id/bottom_layout">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:id="@+id/message_edit_text"
android:background="@drawable/rounded_corner"
android:layout_toLeftOf="@id/send_bt"
android:hint="输入问题"
android:padding="16dp"/>
<ImageButton
android:layout_width="48dp"
android:layout_height="48dp"
android:id="@+id/send_bt"
android:layout_alignParentEnd="true"
android:layout_centerInParent="true"
android:padding="8dp"
android:src="@drawable/baseline_send_24"
android:background="?attr/selectableItemBackgroundBorderless"
android:layout_marginStart="10dp"/>
</RelativeLayout>
</RelativeLayout>
聊天组件资源文件(文件名:res/layout/chat_item.xml)如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
<LinearLayout
android:id="@+id/left_chat_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="30dp"
android:background="@drawable/rounded_corner"
android:backgroundTint="#1E88E5"
android:padding="15dp">
<TextView
android:id="@+id/left_chat_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="@color/white"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_alignParentEnd="true"
android:id="@+id/right_chat_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:background="@drawable/rounded_corner"
android:backgroundTint="#7cb342"
android:padding="15dp">
<TextView
android:id="@+id/right_chat_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="@color/white"
android:textSize="18sp" />
</LinearLayout>
</RelativeLayout>
发送按钮资源文件(文件名:res/drawable/baseline_send_24.xml)如下:
<vector android:autoMirrored="true" android:height="48dp"
android:tint="#1A95BB" android:viewportHeight="24"
android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>
圆角资源文件(文件名:res/drawable/rounded_corner.xml)如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp"/>
<stroke android:width="1dp"/>
<solid android:color="@color/white"/>
</shape>
四、导入Jar包
从Github中下载jar包(Libs文件夹下)和so包(JniLibs文件夹下),下载地址:Bmob-Android-AI/app/src/main at main · bmob/Bmob-Android-AI · GitHubBmob安卓AI示例. Contribute to bmob/Bmob-Android-AI development by creating an account on GitHub.https://github.com/bmob/Bmob-Android-AI/tree/main/app/src/main
下载之后,在自己的工程中相应创建同样的文件夹,并把对应的jar包和so包放进去。
五、新增依赖
修改build.gradle文件里面的dependencies节点,新增内容如下:
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
implementation 'com.squareup.okio:okio:2.2.2'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'androidx.recyclerview:recyclerview:1.3.0'
implementation files('src\\main\\Libs\\BmobSDK_3.9.0.jar')
}
六、创建Application子类
新建一个类,名为BmobApp,继承自Application类,代码如下:
import android.app.Application;
import cn.bmob.v3.Bmob;
public class BmobApp extends Application {
@Override
public void onCreate() {
super.onCreate();
//初始化
Bmob.initialize(this,"第一步获取的application id内容");
}
}
七、新增聊天内容对象类
新建一个类,名为 Message,代码如下:
/**
* 聊天内容类
*/
public class Message {
public static String SEND_BY_ME="me";
public static String SEND_BY_BOT="bot";
String message;
/**
* 获取聊天内容
* @return
*/
public String getMessage() {
return message;
}
/**
* 设置聊天内容
* @param message
*/
public void setMessage(String message) {
this.message = message;
}
/**
* 获取发送者
* @return
*/
public String getSendBy() {
return sendBy;
}
/**
* 设置发送者
* @param sendBy
*/
public void setSendBy(String sendBy) {
this.sendBy = sendBy;
}
/**
* 发送者
*/
String sendBy;
/**
* 聊天内容的构造函数
* @param message 聊天内容
* @param sendBy 发送者
*/
public Message(String message, String sendBy) {
this.message = message;
this.sendBy = sendBy;
}
}
八、新增RecycleView适配器的子类
新增一个类,名字为 MessageAdapter,代码如下:
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
/**
* 聊天内容的适配器类
*/
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MyViewHolder> {
List<Message> messageList;
public MessageAdapter(List<Message> messageList) {
this.messageList = messageList;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View chatView = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_item,null);
MyViewHolder myViewHolder = new MyViewHolder(chatView);
return myViewHolder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Message message = messageList.get(position);
if(message.getSendBy().equals(Message.SEND_BY_ME)){
holder.leftChatView.setVisibility(View.GONE);
holder.rightChatView.setVisibility(View.VISIBLE);
holder.rightTextView.setText(message.getMessage());
}else{
holder.rightChatView.setVisibility(View.GONE);
holder.leftChatView.setVisibility(View.VISIBLE);
holder.leftTextView.setText(message.getMessage());
}
}
@Override
public int getItemCount() {
return messageList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder{
LinearLayout leftChatView,rightChatView;
TextView leftTextView,rightTextView;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
leftChatView = itemView.findViewById(R.id.left_chat_view);
rightChatView = itemView.findViewById(R.id.right_chat_view);
leftTextView = itemView.findViewById(R.id.left_chat_text_view);
rightTextView = itemView.findViewById(R.id.right_chat_text_view);
}
}
}
九、修改配置文件
修改AndroidManifest.xml配置文件,添加权限和application的名字。
新增权限如下:
<!--允许联网 -->
<uses-permission android:name="android.permission.INTERNET" />
<!--获取GSM(2g)、WCDMA(联通3g)等网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--获取wifi网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
application节点内新增android:name,代码如下:
android:name=".BmobApp"
application节点内新增provider节点,代码如下:
<application>
<provider
android:name="cn.bmob.v3.util.BmobContentProvider"
android:authorities="你自己的应用包名.BmobContentProvider">
</provider>
</application>
这里要改为你自己的应用包名。
十、修改主页面代码
修改MAinActivity类,代码如下:
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageButton;
import java.util.ArrayList;
import java.util.List;
import cn.bmob.v3.ai.BmobAI;
import cn.bmob.v3.ai.ChatMessageListener;
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
EditText messageEditText;
ImageButton sendButton;
List<Message> messageList;
MessageAdapter messageAdapter;
BmobAI bmobAI;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建Bmob AI实例
bmobAI = new BmobAI();
//初始化AI内容问答存储
messageList = new ArrayList<>();
recyclerView = findViewById(R.id.msg_recycler_view);
messageEditText = findViewById(R.id.message_edit_text);
sendButton = findViewById(R.id.send_bt);
messageAdapter = new MessageAdapter(messageList);
recyclerView.setAdapter(messageAdapter);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setStackFromEnd(true);
recyclerView.setLayoutManager(llm);
bmobAI.setPrompt("你叫琪琪,是我的女朋友,年轻漂亮贴心,说话也很幽默,接下来的每一个回复,你都要叫我宝贝");
//点击发送提问到AI服务器的按钮
sendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendButton.setEnabled(false);
//获取问题
String quesion = messageEditText.getText().toString().trim();
if(quesion.isEmpty() || quesion.trim()=="")
return;
//连接AI服务器(这个代码为了防止AI连接中断)
bmobAI.Connect();
//显示问题
addToChat(quesion,Message.SEND_BY_ME);
messageEditText.setText("");
//发送内容到AI中
bmobAI.Chat(quesion, "test_user",new ChatMessageListener() {
@Override
public void onMessage(String s) {
//消息流的形式返回AI的结果
addToLastMessage(s);
Log.d("ai",s);
}
@Override
public void onFinish(String s) {
//一次性返回全部结果,这个方法需要等待一段时间,友好性较差
//addToChat(s,Message.SEND_BY_BOT);
sendButton.setEnabled(true);
}
@Override
public void onClose() {
//连接关闭了
Log.d("ai","close");
sendButton.setEnabled(true);
}
});
}
});
}
/**
* 支持流的形式呈现内容到界面
* @param s
*/
public void addToLastMessage(String s)
{
runOnUiThread(new Runnable() {
@Override
public void run() {
if(messageList.size()<=0) return;
Message message = messageList.get(messageList.size()-1);
if(message.sendBy==Message.SEND_BY_ME){
Message newmessage = new Message(s,Message.SEND_BY_BOT);
messageList.add(newmessage);
messageAdapter.notifyDataSetChanged();
recyclerView.smoothScrollToPosition(messageAdapter.getItemCount());
}else{
message.setMessage(message.getMessage() + s);
messageAdapter.notifyDataSetChanged();
recyclerView.smoothScrollToPosition(messageAdapter.getItemCount());
}
}
});
}
/**
* 一次性将全部内容呈现到界面
* @param message
* @param sendBy
*/
void addToChat(String message,String sendBy){
runOnUiThread(new Runnable() {
@Override
public void run() {
messageList.add(new Message(message,sendBy));
messageAdapter.notifyDataSetChanged();
recyclerView.smoothScrollToPosition(messageAdapter.getItemCount());
}
});
}
}
我们可以看到,最重要的一点就是,BmobAI.setPrompt方法,你可以设置一些你想要的调教词进去,做出各种有趣的产品出来。
最后的尾声
最后放出整个项目的源代码给大家:
https://www.bmobapp.com/欢迎大家私聊(wechat: xiaowon12 )AI改变生活的各种想法。