我正在制作一个android聊天应用程序,使用mysql作为服务器,并且还在sqlite上提供离线功能。当我发送消息时,有时数据发送一次,但有时却发送两次或更多次。所以我想知道我的问题是什么原因?
Here is the picture of the database
这是服务器的php代码(syncing.php)
<?php
$data = json_decode(file_get_contents('php://input'), true);
$connect = mysqli_connect("localhost","root","","chatdb");
date_default_timezone_set('Asia/Jakarta');
$date = date("Y-m-d H:i:s");
if (is_array($data) || is_object($data))
{
foreach($data as $kk){
if($kk['syncdate']=="false"){
$query = "INSERT IGNORE INTO message (user_id,from_user,sent_by,message,seen,timestamp,type,syncdate) VALUES ('".$kk['user_id']."','".$kk['from_user']."','".$kk['sent_by']."','".$kk['message']."','".$kk['seen']."','".$date."','".$kk['type']."','true')";
$query1 = "INSERT IGNORE INTO message (user_id,from_user,sent_by,message,seen,timestamp,type,syncdate) VALUES ('".$kk['from_user']."','".$kk['user_id']."','".$kk['sent_by']."','".$kk['message']."','".$kk['seen']."','".$date."','".$kk['type']."','true')";
mysqli_query($connect,$query);
mysqli_query($connect,$query1);
}
}
}
else echo "empty table";
?>
这是移动应用程序的Java代码
public class chat extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
scheduleFunction();
chatMsgView.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int length = chatMsgView.length();
String convert = String.valueOf(length);
tvremainingchars.setText(convert);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
chatSendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - lastClickTime < 1000){
return;
}
lastClickTime = SystemClock.elapsedRealtime();
sendTextMessage();
}
});
chatAddBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CharSequence sendfile[] = new CharSequence[]{"Send an image", "Send a file"};
final AlertDialog.Builder builder = new AlertDialog.Builder(chat.this);
builder.setTitle("Select an option...");
builder.setItems(sendfile, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (i == 0) {
Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(galleryIntent, "SELECT IMAGE"), GALLERY_PICK);
}
else if (i == 1) {
Intent galleryIntent = new Intent();
galleryIntent.setType("text/*");
String[] mimetypes = {"text/*", "application/pdf"};
galleryIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(galleryIntent, "SELECT FILE"), FILE_PICK);
}
}
});
builder.show();
}
});
}
private void loadAllChatsFromServer(){
Thread thread = new Thread() {
public void run() {
try{
runOnUiThread(() -> pDialog.show());
chatMessagesList = new ArrayList<>();
String result = ss.getChats(user_id,sent_to_id);
Log.v("chatPOST get json",result);
JSONArray jsonarray = new JSONArray(result);
if(jsonarray.length()>0) {
for (int i = 0; i < jsonarray.length(); i++) {
JSONObject jsonobject = jsonarray.getJSONObject(i);
String user_id = jsonobject.getString("user_id");
String from_user = jsonobject.getString("from_user");
String message_id = jsonobject.getString("message_id");
String message = jsonobject.getString("message");
String sent_by = jsonobject.getString("sent_by");
String seen = jsonobject.getString("seen");
String timestamp = jsonobject.getString("timestamp");
String type = jsonobject.getString("type");
String syncdate = jsonobject.getString("syncdate");
ChatMessages tmp = new ChatMessages(message, type, timestamp, "download_link", seen, sent_by, from_user, user_id, syncdate);
chatMessagesList.add(tmp);
}
syncWithServer();
runOnUiThread(() -> {
adapter = new ChatMessageAdapter(chatMessagesList, chat.this);
adapter.notifyDataSetChanged();
linearLayout = new LinearLayoutManager(chat.this);
messageList = (RecyclerView) findViewById(R.id.message_list);
messageList.setHasFixedSize(true);
messageList.setLayoutManager(linearLayout);
messageList.setAdapter(adapter);
messageList.scrollToPosition(chatMessagesList.size()-1);
pDialog.dismiss();
messageList.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
messageList.scrollToPosition(chatMessagesList.size()-1);
}
});
messageList.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
return false;
}
});
});
}
else{
}
}
catch (IOException e){
Log.v("chatPOST ioex", "@ chat.java: "+e.toString());
runOnUiThread(() -> {
pDialog.dismiss();
eDialog.setMessage("Please check your internet connection and try again. (Code: 3)");
eDialog.show();
});
}
catch (JSONException e){
Log.v("chatPOST jsonex", "@ chat.java: "+e.toString());
}
catch (final Exception e){
Log.v("chatPOST exception", "@ chat.java: "+e.toString());
}
}
};
thread.start();
}
private void autoReply(){
Thread thread = new Thread() {
public void run() {
try{
String result = ss.triggersohard();
Log.v("chatPOST get json",result);
JSONArray jsonarray = new JSONArray(result);
for(int i=0;i<jsonarray.length();i++){
JSONObject jsonobject = jsonarray.getJSONObject(i);
//user_id,from_user,message_id,sent_by,message,seen,timestamp,type,syncdate
String user_id = jsonobject.getString("user_id");
String from_user = jsonobject.getString("from_user");
String message_id = jsonobject.getString("message_id");
String message = jsonobject.getString("message");
String sent_by = jsonobject.getString("sent_by");
String seen = jsonobject.getString("seen");
String timestamp = jsonobject.getString("timestamp");
String type = jsonobject.getString("type");
String syncdate = jsonobject.getString("syncdate");
ChatMessages tmp = new ChatMessages(message,type,timestamp,"download_link",seen,sent_by,from_user,user_id,syncdate);
chatMessagesList.add(tmp);
}
runOnUiThread(() -> {
adapter = new ChatMessageAdapter(chatMessagesList, chat.this);
adapter.notifyDataSetChanged();
linearLayout = new LinearLayoutManager(chat.this);
messageList = (RecyclerView) findViewById(R.id.message_list);
messageList.setHasFixedSize(true);
messageList.setLayoutManager(linearLayout);
messageList.setAdapter(adapter);
messageList.scrollToPosition(chatMessagesList.size()-1);
pDialog.dismiss();
});
}
catch (IOException e){
Log.v("chatPOST ioex", "@ reply.java: "+e.toString());
runOnUiThread(() -> {
pDialog.dismiss();
eDialog.setMessage("Please check your internet connection and try again. (Code: 3)");
eDialog.show();
});
}
catch (JSONException e){
Log.v("chatPOST jsonex", "@ chat.java: "+e.toString());
}
catch (final Exception e){
Log.v("chatPOST exception", "@ chat.java: "+e.toString());
}
}
};
thread.start();
}
private void sendTextMessage(){
Thread thread = new Thread() {
public void run() {
try{
String message = chatMsgView.getText().toString();
String currentTimestamp = getCurrentTimestamp();
String dllink="";
if(!TextUtils.isEmpty(message)){
ChatMessages temp = new ChatMessages(message,"text",currentTimestamp,dllink,"false",user_id,sent_to_id,user_id,"false");
chatMessagesList.add(temp);
chatdb.insertMessage(temp);
try{
ss.uploadChatsToServer(chatdb.composeJSONfromSQLite());
chatdb.syncdateTrue(temp,"false");
autoReply();
}
catch (IOException e){
Log.e("chat network error",e.toString());
}
catch (Exception e){
Log.e("unable to send chat",e.getMessage());
}
}
runOnUiThread(() -> {
chatMsgView.setText("");
adapter = new ChatMessageAdapter(chatMessagesList, chat.this);
adapter.notifyDataSetChanged();
linearLayout = new LinearLayoutManager(chat.this);
messageList = (RecyclerView) findViewById(R.id.message_list);
messageList.setHasFixedSize(true);
messageList.setLayoutManager(linearLayout);
messageList.setAdapter(adapter);
messageList.scrollToPosition(chatMessagesList.size()-1);
});
}
catch (final Exception e){
Log.v("chat text exception", "@ chat.java: "+e.toString());
}
}
};
thread.start();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.v("chat request code", "@ chat.java: "+requestCode + "");
Log.v("chat result code", "@ chat.java: "+resultCode + "");
if(requestCode == FILE_PICK && resultCode == RESULT_OK && data != null){
Cursor cursor = null;
Uri fileUri = data.getData();
tempUri = fileUri.toString();
String storedURI = getRealPathFromURI(fileUri);
File file = new File(tempUri);
if (tempUri.startsWith("content://")) {
try {
cursor = getContentResolver().query(fileUri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
} else if (tempUri.startsWith("file://")) {
filename = file.getName();
}
final String message = filename.toString();
ChatMessages temp = new ChatMessages(message,"file",getCurrentTimestamp(),storedURI,"false",user_id,sent_to_id,user_id,"false");
chatMessagesList.add(temp);
chatdb.insertMessage(temp);
adapter.notifyDataSetChanged();
messageList.scrollToPosition(chatMessagesList.size()-1);
}
else if(requestCode == GALLERY_PICK && resultCode == RESULT_OK && data != null){
Thread thread = new Thread() {
public void run() {
try{
runOnUiThread(() -> pDialog.show());
Cursor cursor = null;
Uri imageUri = data.getData();
tempUri = imageUri.toString();
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
ByteArrayOutputStream baos= new ByteArrayOutputStream(); ;
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] byteArrayVar = baos.toByteArray();
String blob = Base64.encodeToString(byteArrayVar, Base64.DEFAULT).replaceAll("\\s+","");
ChatMessages temp = new ChatMessages(blob,"image",getCurrentTimestamp(),blob,"false",user_id,sent_to_id,user_id,"false");
chatMessagesList.add(temp);
chatdb.insertMessage(temp);
ss.uploadChatsToServer(chatdb.composeJSONfromSQLite());
chatdb.syncdateTrue(temp,"false");
autoReply();
runOnUiThread(() -> {
pDialog.dismiss();
adapter = new ChatMessageAdapter(chatMessagesList, chat.this);
adapter.notifyDataSetChanged();
linearLayout = new LinearLayoutManager(chat.this);
messageList = (RecyclerView) findViewById(R.id.message_list);
messageList.setHasFixedSize(true);
messageList.setLayoutManager(linearLayout);
messageList.setAdapter(adapter);
messageList.scrollToPosition(chatMessagesList.size()-1);
});
}
catch (IOException e) {
Log.e("chatdb bitmap error",e.toString());
e.printStackTrace();
}
catch (final Exception e){
Log.v("chat image exception", "@ chat.java: "+e.toString());
}
}
};
thread.start();
}
}
private String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
if (cursor == null) {
return contentUri.getPath();
}
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
public void scheduleFunction() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
syncWithServer();
handler.postDelayed(this, SYNC_PERIOD);
}
}, SYNC_PERIOD);
}
public class ChatDBSyncTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
syncWithServer();
return "finished syncing chats to server";
}
@Override
protected void onPostExecute(String str) {
}
@Override
protected void onPreExecute() {
}
}
public void syncWithServer(){
Thread thread = new Thread() {
public void run() {
try{
if(chatdb.toBeSynced()>0){
ss.uploadChatsToServer(chatdb.composeJSONfromSQLite());
chatdb.syncWithSQLite(chatMessagesList);
Log.v("chatdb","chats synced! (uploaded to server, sqlite rewritten, syncdate true @ chat.java)");
}
}
catch (IOException e){
Log.v("chatdb synctoserver", "@ chat.java: "+e.toString());
}
catch (final Exception e){
Log.v("chatdb synctoserver", "@ chat.java: "+e.toString());
}
}
};
thread.start();
}
}
也用于数据库SQLITE的处理程序
public class CHAT_DB_HANDLER extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "chat_db";
private static final int DATABASE_VERSION = 3;
private static final String TABLE_NAME = "message";
public CHAT_DB_HANDLER(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_CHAT_TABLE = "CREATE TABLE message ("
+ "user_id" + " TEXT,"
+ "from_user" + " TEXT,"
+ "message_id" + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "sent_by" + " TEXT,"
+ "message" + " TEXT,"
+ "seen" + " TEXT,"
+ "timestamp" + " TEXT,"
+ "type" +" TEXT,"
+ "syncdate" +" TEXT);";
db.execSQL(CREATE_CHAT_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
public void updateTable(List<ChatMessages> msg){
SQLiteDatabase db = this.getWritableDatabase();
for(int i=0;i<msg.size();i++){
insertMessage(msg.get(i));
}
}
public String composeJSONfromSQLite(){
ArrayList<HashMap<String, String>> chatdata;
chatdata = new ArrayList<HashMap<String, String>>();
String selectQuery = "SELECT * FROM `message`";
SQLiteDatabase database = this.getWritableDatabase();
Cursor cursor = database.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
do {
HashMap<String, String> map = new HashMap<String, String>();
map.put("user_id", cursor.getString(0));
map.put("from_user", cursor.getString(1));
map.put("sent_by", cursor.getString(3));
map.put("message", cursor.getString(4));
map.put("seen", cursor.getString(5));
map.put("type", cursor.getString(7));
map.put("syncdate", cursor.getString(8));
chatdata.add(map);
} while (cursor.moveToNext());
}
database.close();
Gson gson = new GsonBuilder().create();
return gson.toJson(chatdata);
}
public void syncWithSQLite(List<ChatMessages> msg){
Log.v("chatdb","dropped and rewritten according to what's on screen @ chat.java");
for(int i=0;i<msg.size();i++) {
syncdateTrue(msg.get(i), "false");
if(msg.get(i).getSyncdate()=="false"){
insertMessage(msg.get(i));
}
}
}
public boolean syncdateTrue(ChatMessages msg, String condition){//parameters: message obj, false (string)
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("user_id", msg.getUser_id());
values.put("from_user",msg.getTo());//dikirim ke siapa. kenapa namanya bisa from_user
values.put("sent_by", msg.getFrom());
values.put("message", msg.getMessage());
values.put("seen", msg.getSeen());
values.put("type", msg.getType());
values.put("syncdate","true");
try{
db.update(TABLE_NAME, values, "syncdate = ?",new String[] { condition });
Log.v("chatdb syncdate","@ CHAT_DB_HANDLER.java: syncdate updated at sqlite table "+TABLE_NAME);
}
catch (Exception e){
Log.e("chatdb SYNCDATE FAILED","@ CHAT_DB_HANDLER.java:"+e.getMessage());
}
return true;
}
public long insertMessage(ChatMessages msg){
long id=0;
Date ct = new java.sql.Timestamp(Calendar.getInstance().getTime().getTime());
String currentTimestamp = ct.toString();
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
//insert with id
values.put("user_id", msg.getUser_id());
values.put("from_user",msg.getTo());//dikirim ke siapa
values.put("sent_by", msg.getFrom());
values.put("message", msg.getMessage());
values.put("seen", msg.getSeen());
values.put("timestamp",currentTimestamp);
values.put("type", msg.getType());
values.put("syncdate",msg.getSyncdate());
try{
id = db.insertWithOnConflict(TABLE_NAME, null, values, CONFLICT_IGNORE);
}
catch (Exception e){
Log.e("chatdb INSERT ERROR","@ CHAT_DB_HANDLER.java:"+e.getMessage());
}
db.close();
return id;
}
public List<Integer> getDatePositions(){
List<Integer> pos = new ArrayList<>();
String COUNT_DATES = "SELECT count(*) FROM "+TABLE_NAME+" GROUP BY SUBSTRING(timestamp,0,9)";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(COUNT_DATES, null);
if (cursor.moveToFirst()) {
do {
pos.add(Integer.parseInt(cursor.getString(cursor.getColumnIndex("count(*)"))));
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return pos;
}
public int toBeSynced(){
int count = 0;
String selectQuery = "SELECT * FROM `message` where `syncdate` = '"+"false"+"'";
SQLiteDatabase database = this.getWritableDatabase();
Cursor cursor = database.rawQuery(selectQuery, null);
count = cursor.getCount();
database.close();
return count;
}
}