即時通訊im原始碼(開源的社群交友聊天系統原始碼uniapp)詳析

xsjsta發表於2022-05-18

  在本文中,我們可以瞭解多人之間即時通訊系統搭建,他們可以在彼此之間共享文字。應用程式或圖片,因此一旦使用者通過應用程式將訊息傳送給朋友,朋友將在給定時間收到推送通知。即時應用程式等應用程式的精髓是可用的,並對正在進行的操作做出反應。此外,推送通知可以成為一種出色的促銷工具,可用於通知使用者有關更新和新功能的資訊。

  倉庫原始碼:ms.jstxym.top

  CloudDB API - Cloud DB 用於儲存使用者資料、使用者聊天以及管理使用者與其他使用者的聊天記錄。

  a、更新插入

  i、Insert data of the users from the profile.
  ii、Create and insert room id, room id is consider as a reference between two users chat. Using room id will store all the respective chat data in the DB.
  iii、 Insert Chat data between two users based on the room id.

  b、查詢

  i、 Get list of Contacts for chat.
  ii、Get list of users with whom logged in user chatted before.
  ii、Get details of the chat screen with all the chat messages which includes images, text and location.

  認證服務——我們使用認證服務在生態系統上註冊使用者。我們正在使用電話號碼身份驗證服務來接收 OTP 並在此處驗證使用者。

  雲功能——我們使用雲功能觸發推送通知系統。

  推送工具包 - 推送工具包用於將訊息通知推送給其他使用者。因此,當一個使用者傳送訊息時,它將僅通過推送通知通知其他使用者。

  使用雲功能的休息端點在訊息結束後傳送推送通知,從裝置觸發。

  On HMSMessage Received 這是在實現上根據我們的需要解析一次資料,所以我們需要在其他成功共享時解析影像和位置。

  資料庫結構 現在是在控制檯上建立專案和開發 整合準備 您必須完成以下準備工作:

  在控制檯註冊為開發者。

  在 AppGallery Connect 中建立一個專案和一個應用程式。

  生成並配置簽名證照指紋。

  啟用 Auth 服務、Push 和 Cloud DB。

  詳情請參考在AppGallery Connect中為HMS配置應用資訊

  首先建立雲資料庫區域

  建立 3 種物件型別

  ChatRoomId:包含所有聊天室id。

  使用者:所有註冊使用者的詳細資訊。

  UserChat:所有使用者的聊天詳情。

  讓我們從登入頁面開始開發

  我們將使用 HMS Auth 服務使用電話號碼登入。

  啟用電話號碼驗證模式,如下圖所示。

  新增依賴

  // HMS dependencies
  implementation "com.huawei.agconnect:agconnect-database:$rootProject.ext.agdatabase"
  implementation "com.huawei.agconnect:agconnect-auth:$rootProject.ext.agauth"
  implementation "com.huawei.hms:push:$rootProject.ext.pushkit"

  輸入有效的電話號碼,我們將使用以下方法在同一號碼上獲得 OTP。

  獲取一次性密碼

  VerifyCodeSettings settings = new VerifyCodeSettings.Builder()
  .action(VerifyCodeSettings.ACTION_REGISTER_LOGIN)
  .sendInterval(30)
  .locale(Locale.getDefault())
  .build();
  Task<VerifyCodeResult> task = AGConnectAuth.getInstance().requestVerifyCode(countryCodeStr, phoneNumberStr, settings);
  task.addOnSuccessListener(TaskExecutors.immediate(), verifyCodeResult -> {
  if (null != verifyCodeResult) {
  verifyCodeResultMutableLiveData.postValue(verifyCodeResult);
  }
  });
  task.addOnFailureListener(e ->
  AppLog.logE(TAG, "onFailure: " + e.getCause()));

  驗證聯絡方式

  PhoneUser phoneUser = new PhoneUser.Builder()
  .setCountryCode(countryCodeStr)
  .setPhoneNumber(phoneNumberStr)
  .setVerifyCode(code)
  .build();
  AGConnectAuth.getInstance().createUser(phoneUser)
  .addOnSuccessListener(signInResult -> {
  if (signInResult != null) {
  User user = new User();
  user.setUsername(signInResult.getUser().getDisplayName());
  user.setPhoneNumber(phoneNumberStr);
  userMutableLiveData.postValue(user);
  }
  })
  .addOnFailureListener(e -> {
  Log.e(TAG, "verifyContactDetails: " + e.getStackTrace());
  User user = new User();
  user.setPhoneNumber(phoneNumberStr);
  userMutableLiveData.setValue(user);
  });

  驗證後,使用者可以認證成功。

  現在我們必須完成使用者配置檔案,如下圖所示,您可以看到我們只有電話號碼。

  建立/更新配置檔案

  public void saveUser(User user, Context context) {
  CloudDBHelper.getInstance().openDb((isConnected, cloudDBZone) -> {
  if (isConnected && cloudDBZone != null) {
  if (cloudDBZone == null) {
  return;
  } else {
  Task<Integer> insertTask = cloudDBZone.executeUpsert(user);
  insertTask.addOnSuccessListener(integer -> {
  userMutableLiveData.setValue(true);
  CloudDBHelper.getInstance().closeDb(context);
  }).addOnFailureListener(e -> {
  userMutableLiveData.setValue(false);
  CloudDBHelper.getInstance().closeDb(context);
  });
  }
  }
  });
  }

  生成推送令牌

  GetToken getToken = new GetToken(app_id, UserProfileActivity.this);
  getToken.setGetTokenListener(this);
  getToken.execute();

  GetToken 類是生成推送令牌的服務類

  public class GetToken extends AsyncTask<Void, Void, String> {
  private static final String TAG = GetToken.class.getSimpleName();
  private Context context;
  private String appId;
  private GetTokenListener getTokenListener;
  public GetToken(String appId, Context context) {
  this.appId = appId;
  this.context = context;
  }
  public void setGetTokenListener(GetTokenListener getTokenListener) {
  this.getTokenListener = getTokenListener;
  }
  @Override
  protected void onPreExecute() {
  super.onPreExecute();
  }
  @Override
  protected String doInBackground(Void... voids) {
  try {
  String pushToken = HmsInstanceId.getInstance(context).getToken(appId, HmsMessaging.DEFAULT_TOKEN_SCOPE);
  AppLog.logD(TAG, pushToken);
  getTokenListener.getToken(pushToken);
  return pushToken;
  } catch (ApiException e) {
  e.printStackTrace();
  }
  return null;
  }
  @Override
  protected void onPostExecute(String s) {
  super.onPostExecute(s);
  }
  }

  它將建立使用者配置檔案並將資料更新到 Cloud DB。

  第一次開始聊天

  我們必須為兩個人之間的聊天建立房間 ID。

  public void callCreateRoomId(final String userMobileTo, final String userMobileFrom) {
  CloudDBHelper.getInstance().openDb(new OnDBZoneOpen() {
  @Override
  public void isDBZoneOpen(boolean isConnected, CloudDBZone cloudDBZone) {
  if (cloudDBZone != null) {
  ChatRoomId roomId = new ChatRoomId();
  mRoomDataIndex = mRoomDataIndex + 1;
  AppLog.logE(TAG, "New ROOM IS WILL BE ===> " + mRoomDataIndex);
  roomId.setRoom_id(String.valueOf(mRoomDataIndex));
  roomId.setUser_mobile_to(userMobileTo);
  roomId.setUser_mobile_from(userMobileFrom);
  roomId.setUpdate_shadow_flag(true);
  Task<Integer> insertTask = cloudDBZone.executeUpsert(roomId);
  insertTask.addOnSuccessListener(insertSuccessListener(roomId))
  .addOnFailureListener(new OnFailureListener() {
  @Override
  public void onFailure(Exception e) {
  AppLog.logE(TAG, "Exception in creating room id " + e.getLocalizedMessage());
  }
  }).addOnCanceledListener(new OnCanceledListener() {
  @Override
  public void onCanceled() {
  AppLog.logE(TAG, "Inside on cancel listener");
  }
  });
  } else {
  if (mOnApiError != null) {
  mOnApiError.onError("Cloud database zone is null", new Throwable("CloudDBZone is null"));
  }
  }
  }
  });
  }


  從 cloudDB 獲取以前的聊天記錄

  public void getUserChatByRoomID(String roomId, Context context) {
  CloudDBZoneQuery<UserChat> query = CloudDBZoneQuery.where(UserChat.class).equalTo(DBConstants.roomId, roomId).orderByAsc(DBConstants.MESSAGE_TIMESTAMP);
  getUserChat(query, context);
  }
  private void getUserChat(CloudDBZoneQuery<UserChat> userQuery, Context context) {
  CloudDBHelper.getInstance().openDb((isConnected, cloudDBZone) -> {
  Task<CloudDBZoneSnapshot<UserChat>> queryTask = cloudDBZone.executeQuery(userQuery,
  CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY);
  queryTask.addOnSuccessListener(userChatCloudDBZoneSnapshot -> {
  processSnapShot(userChatCloudDBZoneSnapshot.getSnapshotObjects(), context);
  });
  });
  }
  private void processSnapShot(CloudDBZoneObjectList<UserChat> userCloudDBZoneSnapshot, Context context) {
  if (userCloudDBZoneSnapshot != null) {
  ArrayList<UserChat> users = new ArrayList<>();
  while (userCloudDBZoneSnapshot.hasNext()) {
  UserChat user = null;
  try {
  user = userCloudDBZoneSnapshot.next();
  users.add(user);
  } catch (AGConnectCloudDBException e) {
  e.printStackTrace();
  CloudDBHelper.getInstance().closeDb(context);
  }
  }
  userChatMutableLiveData.setValue(users);
  CloudDBHelper.getInstance().closeDb(context);
  }
  }

  開始傳送聊天訊息

  messageType:使用者可以以文字、影像、位置或視訊型別傳送訊息。

  private void setMessage(String messageType) {
  Util.showProgressBar(MessageActivity.this);
  UserChat userChat = new UserChat();
  userChat.setRoom_id(roomId);
  userChat.setMessage_timestamp(Long.parseLong(Util.getTimeStamp()));
  userChat.setChat_id(Util.getRandomNumber());
  userChat.setReceiver_name(receiverText);
  userChat.setReceiver_phone(receiverPhoneNumber);
  userChat.setSender_name(ChitChatSharedPref.getInstance().getString(Constants.USER_NAME, ""));
  userChat.setSender_phone(ChitChatSharedPref.getInstance().getString(Constants.PHONE_NUMBER, ""));
  userChat.setMessage_type(messageType);
  switch (messageType) {
  case Constants.MESSAGE_TYPE_TEXT:
  userChat.setMessage_data(textSend.getText().toString());
  messageViewModel.saveUserChat(userChat);
  messageViewModel.userUpdatedSuccessfully.observe(MessageActivity.this, aBoolean -> {
  if (aBoolean) {
  Util.stopProgressBar();
  getChatList();
  } else {
  Util.stopProgressBar();
  }
  });
  break;
  }
  messageViewModel.queryForToken(receiverPhoneNumber, MessageActivity.this);
  }

  它將使用者資料儲存到雲端 dB

  public void saveUserChat(UserChat userChat) {
  CloudDBHelper.getInstance().openDb((isConnected, cloudDBZone) -> {
  if (cloudDBZone != null) {
  Task<Integer> insertTask = cloudDBZone.executeUpsert(userChat);
  insertTask
  .addOnSuccessListener(integer ->
  userUpdatedSuccessfully.setValue(true))
  .addOnFailureListener(e -> {
  userUpdatedSuccessfully.setValue(false);
  AppLog.logE(TAG, e.getMessage());
  });
  } else {
  userUpdatedSuccessfully.setValue(false);
  }
  });
  }
  是時候傳送推送通知了
  public void queryForToken(String phoneNumber, Context context) {
  CloudDBZoneQuery<User> query = CloudDBZoneQuery.where(User.class).equalTo(DBConstants.userNumber, phoneNumber);
  processNumberCheck(query, context);
  }
  messageViewModel.tokenMutableLiveData.observe(MessageActivity.this, s -> {
  PushApis pushApis = new PushApis(MessageActivity.this);
  if (messageType.equalsIgnoreCase(Constants.MESSAGE_TYPE_TEXT)) {
  pushApis.sendPushNotification(roomId, messageType, "104739093", MessageActivity.this.textSend.getText().toString(), s);
  textSend.setText("");
  }
  });
  設定推送訊息 API
  public class PushApis {
  private Context context;
  public PushApis(Context context) {
  this.context = context;
  }
  public void sendPushNotification(String chatId, String message, String appId, String messageData, String userPushTokens) {
  try {
  StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
  StrictMode.setThreadPolicy(policy);
  String response = "";
  URL url = new URL(Constants.TOKEN_URL);
  HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  connection.setDoOutput(true);
  connection.setInstanceFollowRedirects(false);
  connection.setRequestMethod("POST");
  connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  connection.setRequestProperty("POST", "/oauth2/v3/token   HTTP/1.1");
  connection.setRequestProperty("Host", "oauth-login.cloud.huawei.com");
  HashMap<String, String> params = new HashMap<>();
  params.put("grant_type", "client_credentials");
  params.put("client_secret", Constants.CLIENT_SECRET);
  params.put("client_id", Constants.CLIENT_ID);
  String postDataLength = getDataString(params);
  OutputStream os = connection.getOutputStream();
  BufferedWriter writer = new BufferedWriter(
  new OutputStreamWriter(os, "UTF-8"));
  writer.write(postDataLength);
  writer.flush();
  writer.close();
  os.close();
  int responseCode = connection.getResponseCode();
  if (responseCode == HttpsURLConnection.HTTP_OK) {
  String line;
  BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  while ((line = br.readLine()) != null) {
  response += line;
  }
  } else {
  response = "";
  }
  AppLog.logE("Response", response);
  Gson gson = new Gson();
  BearerRequest bearerRequest = gson.fromJson(response, BearerRequest.class);
  triggerPush(bearerRequest.getAccess_token(), appId, chatId, message, messageData, userPushTokens);
  } catch (Exception e) {
  e.printStackTrace();
  }
  }
  private String getDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
  StringBuilder result = new StringBuilder();
  boolean first = true;
  for (Map.Entry<String, String> entry : params.entrySet()) {
  if (first)
  first = false;
  else
  result.append("&");
  result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
  result.append("=");
  result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
  }
  return result.toString();
  }
  private void triggerPush(String bearer, String appId, String chatId, String messageType, String messageData, String userPushTokens) {
  try {
  StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
  StrictMode.setThreadPolicy(policy);
  String response = null;
  URL url = new URL(");
  HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  connection.setDoOutput(true);
  connection.setInstanceFollowRedirects(false);
  connection.setRequestMethod("POST");
  connection.setDoOutput(true);
  connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  connection.setRequestProperty("Authorization", "Bearer " + bearer);
  connection.setRequestProperty("Host", "oauth-login.cloud.huawei.com");
  connection.setRequestProperty("POST", "/oauth2/v2/token   HTTP/1.1");
  OutputStream os = connection.getOutputStream();
  Data data = new Data();
  data.message = messageType;
  data.roomId = chatId;
  data.messageData = messageData;
  data.sender_name = senderName;
  data.sender_phone = senderPhone;
  data.title = context.getResources().getString(R.string.app_name);
  ArrayList<String> token = new ArrayList<>();
  token.add(userPushTokens);
  Message message = new Message();
  message.tokens = token;
  message.data = data.toString();
  PushMessageRequest pushMessageRequest = new PushMessageRequest();
  pushMessageRequest.message = message;
  pushMessageRequest.validate_only = false;
  BufferedWriter writer = new BufferedWriter(
  new OutputStreamWriter(os, "UTF-8"));
  Gson gson = new Gson();
  JSONObject jsonObject = new JSONObject(gson.toJson(pushMessageRequest, PushMessageRequest.class));
  writer.write(jsonObject.toString());
  writer.flush();
  writer.close();
  os.close();
  int responseCode = connection.getResponseCode();
  String line = null;
  BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  while ((line = br.readLine()) != null) {
  response += line;
  }
  AppLog.logE("Response", response);
  } catch (Exception e) {
  e.getStackTrace();
  }
  }
  }

  結論:

  在本文中,我們瞭解瞭如何使用 Cloud dB、身份驗證服務和推送工具包建立簡單的訊息傳遞應用程式。我們還可以使用雲端儲存來儲存個人資料圖片、位置、文件或音訊和視訊檔案。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70017920/viewspace-2894979/,如需轉載,請註明出處,否則將追究法律責任。

相關文章