Я работаю над приложением чата для Android, для которого я использую Fire Base и DialogFlow.
То, что он делает, в основном во время записи аудио показывает микрофонное изображение на кнопке, а при отправке текста показывает изображение стрелки, как, например, WhatsApp.
Я не могу отобразить макет чата, как показано в:
https://android.jlelse.eu/building-chatbot-with-firebase-and-api-ai-5b787fe693a9 GUI (Нет изображений, потому что нет 10 повторений)
Iполучаю чат, сохраненный в моей учетной записи FireBase, я не могу просто отобразить его на экране своего внешнего интерфейса.
app.gradle зависимости:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0-rc02'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.google.firebase:firebase-database:18.0.0'
// FirebaseUI for Firebase Realtime Database
implementation 'com.firebaseui:firebase-ui-database:5.0.0'
implementation 'com.google.firebase:firebase-messaging:19.0.1'
//implementation 'com.firebaseui:firebase-ui-database:2.3.0'
implementation 'ai.api:sdk:2.0.7@aar'
//implementation
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'commons-io:commons-io:2.4'
implementation "ai.api:libai:1.6.12"
implementation 'com.google.firebase:firebase-core:17.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:recyclerview-v7:28.0.0'
}
apply plugin: 'com.google.gms.google-services'
activity_main.xml: (базовый макетдля экрана с текстовым полем для ввода сообщения и кнопки отправки)
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.internchatbot.MainActivity"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="10dp"
android:paddingBottom="50dp"
android:clipToPadding="false"
android:background="#f4f6f7"
/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="10dp"
android:elevation="2dp"
android:background="@drawable/back_addtask"
android:layout_toStartOf="@+id/addBtn"
android:layout_toLeftOf="@id/addBtn"
android:layout_centerVertical="true"
>
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:background="#ffffff"
android:hint="Type a Message"
android:textSize="18sp"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/addBtn"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:background="@drawable/back_fab"
android:layout_marginBottom="10dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:elevation="4dp"
android:layout_centerInParent="true"
>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/fab_img"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerInParent="true"
android:src="@drawable/ic_mic_white_24dp"
android:tint="#ffffff"/>
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
msg_list.xml: содержит макет с полями с закругленными краями, в которых отображаются отправленное и полученное сообщения.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/leftText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:text="KG Precision Moulders"
android:padding="8dp"
android:textColor="#212121"
android:background="@drawable/left_background"
android:elevation="2dp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/rightText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:text="Query Center"
android:background="@drawable/right_background"
android:textColor="#ffffff"
android:padding="8dp"
android:elevation="2dp"/>
</RelativeLayout>
И вот, наконец, мой activity_main.java (при условии, что все заголовочные файлы импортированы)
import android.*;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import ai.api.AIDataService;
import ai.api.AIListener;
import ai.api.AIServiceException;
import ai.api.android.AIConfiguration;
import ai.api.android.AIService;
import ai.api.model.AIRequest;
import ai.api.model.AIResponse;
import ai.api.model.Result;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
//import com.google.firebase.database.core.Context;
import com.google.firebase.database.Query;
А теперь основной класс:
public class MainActivity extends AppCompatActivity implements AIListener{ //because I am recording audio too
RecyclerView recyclerView;
EditText editText;
RelativeLayout addBtn;
private DatabaseReference ref;
Boolean flagFab = true;
final AIConfiguration config = new AIConfiguration("47f72f4d39b548edbbd11f123d3a40cb ",
AIConfiguration.SupportedLanguages.English,
AIConfiguration.RecognitionEngine.System);
private AIService aiService;
final AIDataService aiDataService = new AIDataService(config);
final AIRequest aiRequest = new AIRequest();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO},1);
recyclerView = findViewById(R.id.recyclerView);
editText = findViewById(R.id.editText);
addBtn = findViewById(R.id.addBtn);
recyclerView.setHasFixedSize(true);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
ref=FirebaseDatabase.getInstance().getReference();
final Query query=ref.child("chat").limitToLast(50);
query.keepSynced(true);
aiService = AIService.getService(this, config);
aiService.setListener(this);
addBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String message = editText.getText().toString().trim();
if (!message.equals("")) {
ChatMessage chatMessage = new ChatMessage(message, "user");
ref.child("chat").push().setValue(chatMessage);
aiRequest.setQuery(message);
MyAsyncTask myasynctask = new MyAsyncTask();
myasynctask.execute();
}
else {
aiService.startListening();
}
editText.setText("");
}
});
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
ImageView fab_img = findViewById(R.id.fab_img);
Bitmap img = BitmapFactory.decodeResource(getResources(),R.drawable.ic_send_white_24dp);
Bitmap img1 = BitmapFactory.decodeResource(getResources(),R.drawable.ic_mic_white_24dp);
if (s.toString().trim().length()!=0 && flagFab){
ImageViewAnimatedChange(MainActivity.this,fab_img,img);
flagFab=false;
}
else if (s.toString().trim().length()==0){
ImageViewAnimatedChange(MainActivity.this,fab_img,img1);
flagFab=true;
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
FirebaseRecyclerOptions<ChatMessage> options = new FirebaseRecyclerOptions.Builder<ChatMessage>().setQuery(query,ChatMessage.class).build();
final FirebaseRecyclerAdapter<ChatMessage, chat_rec> adapter = new FirebaseRecyclerAdapter<ChatMessage, chat_rec>(options) {
@NonNull
@Override
public chat_rec onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.msglist,parent,false);
return new chat_rec(view);
}
@Override
protected void onBindViewHolder(@NonNull chat_rec holder, int position, ChatMessage model) {
if (model.getMsgUser().equals("user")) {
holder.rightText.setText(model.getMsgText());
holder.rightText.setVisibility(View.VISIBLE);
holder.leftText.setVisibility(View.GONE);
}
else {
holder.leftText.setText(model.getMsgText());
holder.rightText.setVisibility(View.GONE);
holder.leftText.setVisibility(View.VISIBLE);
}
}
};
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int msgCount = adapter.getItemCount();
int lastVisiblePosition = linearLayoutManager.findLastCompletelyVisibleItemPosition();
if (lastVisiblePosition == -1 ||
(positionStart >= (msgCount - 1) &&
lastVisiblePosition == (positionStart - 1))) {
recyclerView.scrollToPosition(positionStart);
}
}
});
recyclerView.setAdapter(adapter);
}//onCreate ends here
public class MyAsyncTask extends AsyncTask<AIRequest,Void,AIResponse>{
@Override
protected AIResponse doInBackground(AIRequest... aiRequests) {
try {
final AIResponse response = aiDataService.request(aiRequest);
return response;
} catch (AIServiceException e) {
System.out.print("Error in Aync Task. Please check!"+e);
}
return null;
}
@Override
protected void onPostExecute(AIResponse response) {
if (response != null) {
Result result = response.getResult();
String reply = result.getFulfillment().getSpeech();
ChatMessage chatMessage = new ChatMessage(reply, "bot");
ref.child("chat").push().setValue(chatMessage);
}
}
}
public void ImageViewAnimatedChange(Context c, final ImageView v, final Bitmap new_image) {
final Animation anim_out = AnimationUtils.loadAnimation(c, R.anim.zoom_out);
final Animation anim_in = AnimationUtils.loadAnimation(c, R.anim.zoom_in);
anim_out.setAnimationListener(new Animation.AnimationListener()
{
@Override public void onAnimationStart(Animation animation) {}
@Override public void onAnimationRepeat(Animation animation) {}
@Override public void onAnimationEnd(Animation animation)
{
v.setImageBitmap(new_image);
anim_in.setAnimationListener(new Animation.AnimationListener() {
@Override public void onAnimationStart(Animation animation) {}
@Override public void onAnimationRepeat(Animation animation) {}
@Override public void onAnimationEnd(Animation animation) {}
});
v.startAnimation(anim_in);
}
});
v.startAnimation(anim_out);
}
@Override
public void onResult(ai.api.model.AIResponse response) {
Result result = response.getResult();
String message = result.getResolvedQuery();
ChatMessage chatMessage0 = new ChatMessage(message, "user");
Log.d("REQUEST",chatMessage0.toString());
ref.child("chat").push().setValue("Request"+chatMessage0);
String reply = result.getFulfillment().getSpeech();
ChatMessage chatMessage = new ChatMessage(reply, "bot");
Log.d("Reply",chatMessage.toString());
ref.child("chat").push().setValue(chatMessage);
}
@Override
public void onError(ai.api.model.AIError error) {
}
@Override
public void onAudioLevel(float level) {
}
@Override
public void onListeningStarted() {
}
@Override
public void onListeningCanceled() {
}
@Override
public void onListeningFinished() {
}
}
В основном яЯ не получаю макет чата в моем интерфейсе, остальное весь код работает правильно.Почему я не получаю помощь, пожалуйста?