gpt4 book ai didi

java - 消息聊天不太好用

转载 作者:行者123 更新时间:2023-12-01 09:42:44 25 4
gpt4 key购买 nike

通过我的应用程序,我将消息和通知从我的智能手机(称为 PHONE1)发送到另一个智能手机(称为 PHONE2)。该消息由 PHONE2 接收。 PHONE2 向 PHONE1 发送回复消息。 PHONE1 收到通知并读取消息。 PHONE1 向 PHONE2 发送回复消息,应用程序崩溃。

Messages.java:

public class Messages extends AppCompatActivity {

private static final String TAG = "ChatActivity";

Context context;
private ChatArrayAdapter chatArrayAdapter;
private ListView listView;
private EditText chatText;
private Button buttonSend;
private boolean side = false;
String from, to, mess;


@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messages);


buttonSend = (Button) findViewById(R.id.send);

listView = (ListView) findViewById(R.id.chatMessage);

chatArrayAdapter = new ChatArrayAdapter(getApplicationContext(), R.layout.row_messages_right);
listView.setAdapter(chatArrayAdapter);

chatText = (EditText) findViewById(R.id.msg);
chatText.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
return sendChatMessage();
}
return false;
}
});
buttonSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
sendChatMessage();
}
});

listView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
listView.setAdapter(chatArrayAdapter);

//to scroll the list view to bottom on data change
chatArrayAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
listView.setSelection(chatArrayAdapter.getCount() - 1);
}
});


Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
receiveChatMessage();
}
}, 0, 1000);



}





@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private boolean receiveChatMessage(){
InternalDatabaseOperations DB = new InternalDatabaseOperations(this);
Cursor CR = DB.getInformation(DB);
CR.moveToLast();
from = CR.getString(0);
to = CR.getString(1);
if(!Objects.equals(mess, CR.getString(2))){
mess = CR.getString(2);
chatArrayAdapter.add(new ChatMessage(!side, mess));
return true;
}
return false;
}

//Send chat message
private boolean sendChatMessage() {
mess = chatText.getText().toString();
chatArrayAdapter.add(new ChatMessage(side,mess));
chatText.setText("");
InternalDatabaseOperations DB = new InternalDatabaseOperations(this);
Cursor CR = DB.getInformation(DB);
CR.moveToLast();
from = CR.getString(1);
to = CR.getString(0);
BackgroundTaskSendingMessage sendingMessage = new BackgroundTaskSendingMessage(this);
sendingMessage.execute(to, from, mess);
return true;

} }

chatArrayAdapter.java:

class ChatArrayAdapter extends ArrayAdapter<ChatMessage> {

private TextView chatText;
private List<ChatMessage> chatMessageList = new ArrayList<>();
private Context context;

@Override
public void add(ChatMessage object) {
chatMessageList.add(object);
super.add(object);
}

public ChatArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
this.context = context;
}

public int getCount() {
return this.chatMessageList.size();
}

//Retrieve message position
public ChatMessage getItem(int index) {
return this.chatMessageList.get(index);
}

//Change layout inflater if necessary
public View getView(int position, View convertView, ViewGroup parent) {
ChatMessage chatMessageObj = getItem(position);
View row = convertView;
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (chatMessageObj.left) {
row = inflater.inflate(R.layout.row_messages_right, parent, false);
}else{
row = inflater.inflate(R.layout.row_messages_left, parent, false);
}
chatText = (TextView) row.findViewById(R.id.msgr);
chatText.setText(chatMessageObj.message);
return row;
}
}

消息服务通知:

    public class MyFirebaseMessagingService extends FirebaseMessagingService{


@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

String message = remoteMessage.getData().get("message");
String from = remoteMessage.getData().get("From");
String to = remoteMessage.getData().get("to");
InternalDatabaseOperations DB = new InternalDatabaseOperations(this);
DB.putInformation(DB, from, to, message);

showNotification(message);
}

private void showNotification(String message) {

Intent i = new Intent(this, Messages.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setAutoCancel(true)
.setContentTitle("BookStore")
.setContentText(message)
.setSmallIcon(R.drawable.book)
.setContentIntent(pendingIntent);

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(0, builder.build());

}


}

logcat:

 14007-14681/gamingproject.sellmybooks E/AndroidRuntime: FATAL EXCEPTION: Timer-0
Process: gamingproject.sellmybooks, PID: 14007
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6353)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:875)
at android.view.View.requestLayout(View.java:17524)
at android.view.View.requestLayout(View.java:17524)
at android.view.View.requestLayout(View.java:17524)
at android.view.View.requestLayout(View.java:17524)
at android.view.View.requestLayout(View.java:17524)
at android.view.View.requestLayout(View.java:17524)
at android.view.View.requestLayout(View.java:17524)
at android.widget.AbsListView.requestLayout(AbsListView.java:2027)
at android.widget.AbsListView.setSelectionFromTop(AbsListView.java:7045)
at android.widget.ListView.setSelection(ListView.java:2018)
at gamingproject.sellmybooks.Messages$3.onChanged(Messages.java:74)
at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
at android.widget.ArrayAdapter.notifyDataSetChanged(ArrayAdapter.java:286)
at android.widget.ArrayAdapter.add(ArrayAdapter.java:182)
at gamingproject.sellmybooks.ChatArrayAdapter.add(ChatArrayAdapter.java:22)
at gamingproject.sellmybooks.Messages.receiveChatMessage(Messages.java:104)
at gamingproject.sellmybooks.Messages.access$300(Messages.java:23)
at gamingproject.sellmybooks.Messages$4.run(Messages.java:83)
at java.util.Timer$TimerImpl.run(Timer.java:284)

提前感谢您的帮助。

最佳答案

问题是您的计时器正在使用后台线程,并且您正在尝试从该后台线程更新您的 ChatArrayAdapter。

来自the documentation :

Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially.

如果您将计时器的代码保留为原样:

Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
receiveChatMessage();
}
}, 0, 1000);

看起来您只需将向 UI 线程上的适配器添加项目的代码即可:

private boolean receiveChatMessage() {
InternalDatabaseOperations DB = new InternalDatabaseOperations(this);
Cursor CR = DB.getInformation(DB);
CR.moveToLast();
from = CR.getString(0);
to = CR.getString(1);
if(!Objects.equals(mess, CR.getString(2))){
mess = CR.getString(2);

//modified:
runOnUiThread(new Runnable() {
@Override
public void run() {
chatArrayAdapter.add(new ChatMessage(!side, mess));
}
});

CR.close(); //close your cursor to avoid memory leaks!
return true;
}
CR.close(); //close your cursor to avoid memory leaks!
return false;
}

关于java - 消息聊天不太好用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38335486/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com