HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

即时通讯聊天系统源码下载带教程

IM 即时通信 源码分享

本文将讨论实现一套即时通讯聊天系统源码并附部署教程,该im源码具有以下功能:
带app源码:im.jstxym.top
我们将创建一个聊天布局,并在聊天发送消息。
●用户可以发送消息或图像。
●用户可以使用相机或图库发送图像。
●首先,请求许可将被要求发送图像使用图库或点击图像后使用相机。
●如果允许,那么用户可以发送图像,或者它将再次请求请求许可。
分步实施
步骤1:创建两个新的布局资源文件,命名为row_chat_left和row_chat_right
使用row_chat_left.xml文件。收到的信息将在左侧。类似地,使用row_chat_right.xml文件。发送给用户的消息将在右边。下面是row_chat_left.xml文件和row_chat_right.xml文件的代码。
<LinearLayout
android:id="@+id/msglayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profilec"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/profile_image"
app:civ_border_color="@null"/>
<TextView
android:id="@+id/msgc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/bg_receiver"
android:padding="15dp"
android:text="HisMessage"
android:textColor="@color/colorBlack"
android:textSize="16sp"
android:visibility="gone"/>
<ImageView
android:id="@+id/images"
android:layout_width="200dp"
android:layout_height="200dp"
android:adjustViewBounds="true"
android:background="@drawable/bg_receiver"
android:padding="15dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_images"/>
<TextView
android:id="@+id/timetv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="02/01/199006:19PM"
android:textColor="@color/colorBlack"
android:textSize="12sp"/>
</LinearLayout>
<TextView
android:id="@+id/isSeen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Delivered"
android:textAlignment="textEnd"
android:visibility="gone"/>
</LinearLayout>
步骤2:使用activity_chat.xml文件
在RecyclerView中,我们将显示所有的消息。在TextView中,用户将键入消息,并使用发送按钮,用户将发送消息。下面是activity_chat.xml文件的代码。
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ChatActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@color/colorPrimaryDark"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profiletv"
android:layout_width="35dp"
android:layout_height="35dp"
android:scaleType="centerCrop"
android:src="@drawable/profile_image"
app:civ_circle_background_color="@color/colorPrimaryDark"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/nameptv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="HisName"
android:textColor="@color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/onlinetv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Online"
android:textColor="@color/colorWhite"
android:textStyle="bold"/>
</LinearLayout>
<ImageView
android:id="@+id/block"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="5dp"
android:src="@drawable/ic_unblock"/>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/chatrecycle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/chatlayout"
android:layout_below="@id/toolbar"/>
<LinearLayout
android:id="@+id/chatlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/colorWhite"
android:gravity="center"
android:orientation="horizontal">
<ImageButton
android:id="@+id/attachbtn"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@null"
android:src="@drawable/ic_iattach"/>
<EditText
android:id="@+id/messaget"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="StartTyping"
android:inputType="textCapSentences|textMultiLine"
android:padding="15dp"/>
<ImageButton
android:id="@+id/sendmsg"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@null"
android:src="@drawable/send_message"/>
</LinearLayout>
</RelativeLayout>
步骤3:使用row_chatlist.xml文件
创建另一个布局资源文件,命名为row_chatlist。下面是row_chatlist.xml文件的代码。
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:contentPadding="3dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profileimage"
android:layout_width="70dp"
android:layout_height="70dp"
android:src="@drawable/profile_image"/>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/onlinestatus"
android:layout_width="25dp"
android:layout_height="25dp"/>
<TextView
android:id="@+id/nameonline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_toEndOf="@id/profileimage"
android:layout_toRightOf="@id/profileimage"
android:text="HisName"
android:textColor="@color/colorBlack"
android:textSize="18sp"/>
<TextView
android:id="@+id/lastmessge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/nameonline"
android:layout_marginStart="4dp"
android:layout_toEndOf="@id/profileimage"
android:layout_toRightOf="@id/profileimage"
android:maxLines="2"
android:text="LastMessage"
android:textColor="@color/colorBlack"/>
<ImageView
android:id="@+id/blocking"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_unblock"/>
<ImageView
android:id="@+id/seen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/blocking"
android:layout_alignParentEnd="true"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_unblock"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
步骤4:使用ModelChat.java文件
创建这个类来初始化键,以便我们以后可以检索键的值。
packagecom.example.socialmediaapp;
publicclassModelChat{
Stringmessage;
publicStringgetMessage(){
returnmessage;
}
publicvoidsetMessage(Stringmessage){
this.message=message;
}
publicStringgetReceiver(){
returnreceiver;
}
publicvoidsetReceiver(Stringreceiver){
this.receiver=receiver;
}
publicStringgetSender(){
returnsender;
}
publicvoidsetSender(Stringsender){
this.sender=sender;
}
publicStringgetTimestamp(){
returntimestamp;
}
publicvoidsetTimestamp(Stringtimestamp){
this.timestamp=timestamp;
}
publicbooleanisDilihat(){
returndilihat;
}
publicvoidsetDilihat(booleandilihat){
this.dilihat=dilihat;
}
Stringreceiver;
publicModelChat(){
}
Stringsender;
publicStringgetType(){
returntype;
}
publicvoidsetType(Stringtype){
this.type=type;
}
publicModelChat(Stringmessage,Stringreceiver,Stringsender,Stringtype,Stringtimestamp,booleandilihat){
this.message=message;
this.receiver=receiver;
this.sender=sender;
this.type=type;
this.timestamp=timestamp;
this.dilihat=dilihat;
}
Stringtype;
Stringtimestamp;
booleandilihat;
}
步骤5:使用AdpaterChat.java文件
创建一个新的java类,并将该类命名为AdpaterChat。下面是AdpaterChat.java文件的代码。
packagecom.example.socialmediaapp;
importandroid.app.AlertDialog;
importandroid.content.Context;
importandroid.content.DialogInterface;
importandroid.text.format.DateFormat;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.ImageView;
importandroid.widget.LinearLayout;
importandroid.widget.TextView;
importandroid.widget.Toast;
importandroidx.annotation.NonNull;
importandroidx.recyclerview.widget.RecyclerView;
importcom.bumptech.glide.Glide;
importcom.google.firebase.auth.FirebaseAuth;
importcom.google.firebase.auth.FirebaseUser;
importcom.google.firebase.database.DataSnapshot;
importcom.google.firebase.database.DatabaseError;
importcom.google.firebase.database.DatabaseReference;
importcom.google.firebase.database.FirebaseDatabase;
importcom.google.firebase.database.Query;
importcom.google.firebase.database.ValueEventListener;
importjava.util.Calendar;
importjava.util.List;
importjava.util.Locale;
importde.hdodenhof.circleimageview.CircleImageView;
publicclassAdapterChatextendsRecyclerView.Adapter<com.example.socialmediaapp.AdapterChat.Myholder>{
privatestaticfinalintMSG_TYPE_LEFT=0;
privatestaticfinalintMSG_TYPR_RIGHT=1;
Contextcontext;
List<ModelChat>list;
Stringimageurl;
FirebaseUserfirebaseUser;
publicAdapterChat(Contextcontext,List<ModelChat>list,Stringimageurl){
this.context=context;
this.list=list;
this.imageurl=imageurl;
}
@NonNull
@Override
publicMyholderonCreateViewHolder(@NonNullViewGroupparent,intviewType){
if(viewType==MSG_TYPE_LEFT){
Viewview=LayoutInflater.from(context)。inflate(R.layout.row_chat_left,parent,false);
returnnewMyholder(view);
}else{
Viewview=LayoutInflater.from(context)。inflate(R.layout.row_chat_right,parent,false);
returnnewMyholder(view);
}
}
@Override
publicvoidonBindViewHolder(@NonNullMyholderholder,finalintposition){
Stringmessage=list.get(position)。getMessage();
StringtimeStamp=list.get(position)。getTimestamp();
Stringtype=list.get(position)。getType();
Calendarcalendar=Calendar.getInstance(Locale.ENGLISH);
calendar.setTimeInMillis(Long.parseLong(timeStamp));
Stringtimedate=DateFormat.format("dd/MM/yyyyhh:mmaa",calendar)。toString();
holder.message.setText(message);
holder.time.setText(timedate);
try{
Glide.with(context)。load(imageurl)。into(holder.image);
}catch(Exceptione){
}
if(type.equals("text")){
holder.message.setVisibility(View.VISIBLE);
holder.mimage.setVisibility(View.GONE);
holder.message.setText(message);
}else{
holder.message.setVisibility(View.GONE);
holder.mimage.setVisibility(View.VISIBLE);
Glide.with(context)。load(message)。into(holder.mimage);
}
holder.msglayput.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
AlertDialog.Builderbuilder=newAlertDialog.Builder(context);
builder.setTitle("DeleteMessage");
builder.setMessage("AreYouSureToDeleteThisMessage");
builder.setPositiveButton("Delete",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
deleteMsg(position);
}
});
builder.setNegativeButton("Cancel",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
dialog.dismiss();
}
});
builder.create()。show();
}
});
}
privatevoiddeleteMsg(intposition){
finalStringmyuid=FirebaseAuth.getInstance()。getCurrentUser()。getUid();
Stringmsgtimestmp=list.get(position)。getTimestamp();
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference()。child("Chats");
Queryquery=dbref.orderByChild("timestamp")。equalTo(msgtimestmp);
query.addListenerForSingleValueEvent(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
for(DataSnapshotdataSnapshot1:dataSnapshot.getChildren()){
if(dataSnapshot1.child("sender")。getValue()。equals(myuid)){
//anytwoofbelowcanbeused
dataSnapshot1.getRef()。removeValue();
/HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("message","ThisMessageWasDeleted");
dataSnapshot1.getRef()。updateChildren(hashMap);
Toast.makeText(context,"MessageDeleted……",Toast.LENGTH_LONG)。show();
/
}else{
Toast.makeText(context,"youcandeletonlyyourmsg…",Toast.LENGTH_LONG)。show();
}
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
}
@Override
publicintgetItemCount(){
returnlist.size();
}
@Override
publicintgetItemViewType(intposition){
firebaseUser=FirebaseAuth.getInstance()。getCurrentUser();
if(list.get(position)。getSender()。equals(firebaseUser.getUid())){
returnMSG_TYPR_RIGHT;
}else{
returnMSG_TYPE_LEFT;
}
}
classMyholderextendsRecyclerView.ViewHolder{
CircleImageViewimage;
ImageViewmimage;
TextViewmessage,time,isSee;
LinearLayoutmsglayput;
publicMyholder(@NonNullViewitemView){
super(itemView);
image=itemView.findViewById(R.id.profilec);
message=itemView.findViewById(R.id.msgc);
time=itemView.findViewById(R.id.timetv);
isSee=itemView.findViewById(R.id.isSeen);
msglayput=itemView.findViewById(R.id.msglayout);
mimage=itemView.findViewById(R.id.images);
}
}
}
步骤6:使用ChatActivity.java文件
我们正在阅读来自Firebase中的“聊天”节点的用户消息。每次数据更改时,该数据也会相应更改
chatList=newArrayList<>();
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference()。child("Chats");
使用适配器聊天加载数据设置数据值
ModelChatmodelChat=dataSnapshot1.getValue(ModelChat.class);
if(modelChat.getSender()。equals(myuid)&&
modelChat.getReceiver()。equals(uid)||
modelChat.getReceiver()。equals(myuid)
&&modelChat.getSender()。equals(uid)){
chatList.add(modelChat);//addthechatinchatlist
}
adapterChat=newAdapterChat(ChatActivity.this,chatList,image);
adapterChat.notifyDataSetChanged();
recyclerView.setAdapter(adapterChat);
在聊天参考节点值中发送消息。下面是我们如何在Firebase实时数据库中保存数据
DatabaseReferencedatabaseReference=FirebaseDatabase.getInstance()。getReference();
Stringtimestamp=String.valueOf(System.currentTimeMillis());
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("sender",myuid);
hashMap.put("receiver",uid);
hashMap.put("message",message);
hashMap.put("timestamp",timestamp);
hashMap.put("dilihat",false);
hashMap.put("type","text");
databaseReference.child("Chats")。push()。setValue(hashMap);
下面是ChatActivity.java文件的代码。
packagecom.example.socialmediaapp;
importandroid.Manifest;
importandroid.app.AlertDialog;
importandroid.app.ProgressDialog;
importandroid.content.ContentValues;
importandroid.content.DialogInterface;
importandroid.content.Intent;
importandroid.content.pm.PackageManager;
importandroid.graphics.Bitmap;
importandroid.net.Uri;
importandroid.os.Bundle;
importandroid.provider.MediaStore;
importandroid.text.TextUtils;
importandroid.text.format.DateFormat;
importandroid.view.MenuItem;
importandroid.view.View;
importandroid.widget.EditText;
importandroid.widget.ImageButton;
importandroid.widget.ImageView;
importandroid.widget.TextView;
importandroid.widget.Toast;
importandroidx.annotation.NonNull;
importandroidx.annotation.Nullable;
importandroidx.appcompat.app.AppCompatActivity;
importandroidx.appcompat.widget.Toolbar;
importandroidx.core.content.ContextCompat;
importandroidx.recyclerview.widget.LinearLayoutManager;
importandroidx.recyclerview.widget.RecyclerView;
importcom.bumptech.glide.Glide;
importcom.google.android.gms.tasks.OnFailureListener;
importcom.google.android.gms.tasks.OnSuccessListener;
importcom.google.android.gms.tasks.Task;
importcom.google.firebase.auth.FirebaseAuth;
importcom.google.firebase.auth.FirebaseUser;
importcom.google.firebase.database.DataSnapshot;
importcom.google.firebase.database.DatabaseError;
importcom.google.firebase.database.DatabaseReference;
importcom.google.firebase.database.FirebaseDatabase;
importcom.google.firebase.database.Query;
importcom.google.firebase.database.ValueEventListener;
importcom.google.firebase.storage.FirebaseStorage;
importcom.google.firebase.storage.StorageReference;
importcom.google.firebase.storage.UploadTask;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.util.ArrayList;
importjava.util.Calendar;
importjava.util.HashMap;
importjava.util.List;
publicclassChatActivityextendsAppCompatActivity{
Toolbartoolbar;
RecyclerViewrecyclerView;
ImageViewprofile,block;
TextViewname,userstatus;
EditTextmsg;
ImageButtonsend,attach;
FirebaseAuthfirebaseAuth;
Stringuid,myuid,image;
ValueEventListenervalueEventListener;
List<ModelChat>chatList;
AdapterChatadapterChat;
privatestaticfinalintIMAGEPICK_GALLERY_REQUEST=300;
privatestaticfinalintIMAGE_PICKCAMERA_REQUEST=400;
privatestaticfinalintCAMERA_REQUEST=100;
privatestaticfinalintSTORAGE_REQUEST=200;
StringcameraPermission[];
StringstoragePermission[];
Uriimageuri=null;
FirebaseDatabasefirebaseDatabase;
DatabaseReferenceusers;
booleannotify=false;
booleanisBlocked=false;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
firebaseAuth=FirebaseAuth.getInstance();
//initialisethetextviewsandlayouts
profile=findViewById(R.id.profiletv);
name=findViewById(R.id.nameptv);
userstatus=findViewById(R.id.onlinetv);
msg=findViewById(R.id.messaget);
send=findViewById(R.id.sendmsg);
attach=findViewById(R.id.attachbtn);
block=findViewById(R.id.block);
LinearLayoutManagerlinearLayoutManager=newLinearLayoutManager(this);
linearLayoutManager.setStackFromEnd(true);
recyclerView=findViewById(R.id.chatrecycle);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(linearLayoutManager);
uid=getIntent()。getStringExtra("uid");
//gettinguidofanotheruserusingintent
firebaseDatabase=FirebaseDatabase.getInstance();
//initialisingpermissions
cameraPermission=newString[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};
storagePermission=newString[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
checkUserStatus();
users=firebaseDatabase.getReference("Users");
attach.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
showImagePicDialog();
}
});
send.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
notify=true;
Stringmessage=msg.getText()。toString()。trim();
if(TextUtils.isEmpty(message)){//ifempty
Toast.makeText(ChatActivity.this,"PleaseWriteSomethingHere",Toast.LENGTH_LONG)。show();
}else{
sendmessage(message);
}
msg.setText("");
}
});
Queryuserquery=users.orderByChild("uid")。equalTo(uid);
userquery.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
//retrieveuserdata
for(DataSnapshotdataSnapshot1:dataSnapshot.getChildren()){
Stringnameh=""+dataSnapshot1.child("name")。getValue();
image=""+dataSnapshot1.child("image")。getValue();
Stringonlinestatus=""+dataSnapshot1.child("onlineStatus")。getValue();
Stringtypingto=""+dataSnapshot1.child("typingTo")。getValue();
if(typingto.equals(myuid)){//ifuseristypingtomychat
userstatus.setText("Typing…");//typestatusastyping
}else{
if(onlinestatus.equals("online")){
userstatus.setText(onlinestatus);
}else{
Calendarcalendar=Calendar.getInstance();
calendar.setTimeInMillis(Long.parseLong(onlinestatus));
Stringtimedate=DateFormat.format("dd/MM/yyyyhh:mmaa",calendar)。toString();
userstatus.setText("LastSeen:"+timedate);
}
}
name.setText(nameh);
try{
Glide.with(ChatActivity.this)。load(image)。placeholder(R.drawable.profile_image)。into(profile);
}catch(Exceptione){
}
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
readMessages();
}
@Override
protectedvoidonPause(){
super.onPause();
Stringtimestamp=String.valueOf(System.currentTimeMillis());
checkOnlineStatus(timestamp);
checkTypingStatus("noOne");
}
@Override
protectedvoidonResume(){
checkOnlineStatus("online");
super.onResume();
}
@Override
publicbooleanonSupportNavigateUp(){
onBackPressed();
returnsuper.onSupportNavigateUp();
}
privatevoidcheckOnlineStatus(Stringstatus){
//checkonlinestatus
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference("Users")。child(myuid);
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("onlineStatus",status);
dbref.updateChildren(hashMap);
}
privatevoidcheckTypingStatus(Stringtyping){
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference("Users")。child(myuid);
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("typingTo",typing);
dbref.updateChildren(hashMap);
}
@Override
protectedvoidonStart(){
checkUserStatus();
checkOnlineStatus("online");
super.onStart();
}
privatevoidreadMessages(){
//showmessageafterretrievingdata
chatList=newArrayList<>();
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference()。child("Chats");
dbref.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
chatList.clear();
for(DataSnapshotdataSnapshot1:dataSnapshot.getChildren()){
ModelChatmodelChat=dataSnapshot1.getValue(ModelChat.class);
if(modelChat.getSender()。equals(myuid)&&
modelChat.getReceiver()。equals(uid)||
modelChat.getReceiver()。equals(myuid)
&&modelChat.getSender()。equals(uid)){
chatList.add(modelChat);//addthechatinchatlist
}
adapterChat=newAdapterChat(ChatActivity.this,chatList,image);
adapterChat.notifyDataSetChanged();
recyclerView.setAdapter(adapterChat);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
}
privatevoidshowImagePicDialog(){
Stringoptions[]={"Camera","Gallery"};
AlertDialog.Builderbuilder=newAlertDialog.Builder(ChatActivity.this);
builder.setTitle("PickImageFrom");
builder.setItems(options,newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
if(which==0){
if(!checkCameraPermission()){//ifpermissionisnotgiven
requestCameraPermission();//requestforpermission
}else{
pickFromCamera();//ifalreadyaccessgrantedthenclick
}
}elseif(which==1){
if(!checkStoragePermission()){//ifpermissionisnotgiven
requestStoragePermission();//requestforpermission
}else{
pickFromGallery();//ifalreadyaccessgrantedthenpick
}
}
}
});
builder.create()。show();
}
publicvoidonRequestPermissionsResult(intrequestCode,@NonNullString[]permissions,@NonNullint[]grantResults){
//requestforpermissionifnotgiven
switch(requestCode){
caseCAMERA_REQUEST:{
if(grantResults.length>0){
booleancamera_accepted=grantResults[0]==PackageManager.PERMISSION_GRANTED;
booleanwriteStorageaccepted=grantResults[1]==PackageManager.PERMISSION_GRANTED;
if(camera_accepted&&writeStorageaccepted){
pickFromCamera();//ifaccessgrantedthenclick
}else{
Toast.makeText(this,"PleaseEnableCameraandStoragePermissions",Toast.LENGTH_LONG)。show();
}
}
}
break;
caseSTORAGE_REQUEST:{
if(grantResults.length>0){
booleanwriteStorageaccepted=grantResults[0]==PackageManager.PERMISSION_GRANTED;
if(writeStorageaccepted){
pickFromGallery();//ifaccessgrantedthenpick
}else{
Toast.makeText(this,"PleaseEnableStoragePermissions",Toast.LENGTH_LONG)。show();
}
}
}
break;
}
}
@Override
publicvoidonActivityResult(intrequestCode,intresultCode,@NullableIntentdata){
if(resultCode==RESULT_OK){
if(requestCode==IMAGEPICK_GALLERY_REQUEST){
imageuri=data.getData();//getimagedatatoupload
try{
sendImageMessage(imageuri);
}catch(IOExceptione){
e.printStackTrace();
}
}
if(requestCode==IMAGE_PICKCAMERA_REQUEST){
try{
sendImageMessage(imageuri);
}catch(IOExceptione){
e.printStackTrace();
}
}
}
super.onActivityResult(requestCode,resultCode,data);
}
privatevoidsendImageMessage(Uriimageuri)throwsIOException{
notify=true;
finalProgressDialogdialog=newProgressDialog(this);
dialog.setMessage("SendingImage");
dialog.show();
//Ifwearesendingimageasamessage
//thenweneedtofindtheurlof
//imageafteruploadingthe
//imageinfirebasestorage
finalStringtimestamp=""+System.currentTimeMillis();
Stringfilepathandname="ChatImages/"+"post"+timestamp;//filename
Bitmapbitmap=MediaStore.Images.Media.getBitmap(this.getContentResolver(),imageuri);
ByteArrayOutputStreamarrayOutputStream=newByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG,100,arrayOutputStream);//compressingtheimageusingbitmap
finalbyte[]data=arrayOutputStream.toByteArray();
StorageReferenceref=FirebaseStorage.getInstance()。getReference()。child(filepathandname);
ref.putBytes(data)。addOnSuccessListener(newOnSuccessListener<UploadTask.TaskSnapshot>(){
@Override
publicvoidonSuccess(UploadTask.TaskSnapshottaskSnapshot){
dialog.dismiss();
Task<Uri>uriTask=taskSnapshot.getStorage()。getDownloadUrl();
while(!uriTask.isSuccessful());
StringdownloadUri=uriTask.getResult()。toString();//gettingurliftaskissuccessful
if(uriTask.isSuccessful()){
DatabaseReferencere=FirebaseDatabase.getInstance()。getReference();
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("sender",myuid);
hashMap.put("receiver",uid);
hashMap.put("message",downloadUri);
hashMap.put("timestamp",timestamp);
hashMap.put("dilihat",false);
hashMap.put("type","images");
re.child("Chats")。push()。setValue(hashMap);//pushinfirebaseusinguniqueid
finalDatabaseReferenceref1=FirebaseDatabase.getInstance()。getReference("ChatList")。child(uid)。child(myuid);
ref1.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
if(!dataSnapshot.exists()){
ref1.child("id")。setValue(myuid);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
finalDatabaseReferenceref2=FirebaseDatabase.getInstance()。getReference("ChatList")。child(myuid)。child(uid);
ref2.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
if(!dataSnapshot.exists()){
ref2.child("id")。setValue(uid);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
}
}
})。addOnFailureListener(newOnFailureListener(){
@Override
publicvoidonFailure(@NonNullExceptione){
}
});
}
privateBooleancheckCameraPermission(){
booleanresult=ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)==(PackageManager.PERMISSION_GRANTED);
booleanresult1=ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)==(PackageManager.PERMISSION_GRANTED);
returnresult&&result1;
}
privatevoidrequestCameraPermission(){
requestPermissions(cameraPermission,CAMERA_REQUEST);
}
privatevoidpickFromCamera(){
ContentValuescontentValues=newContentValues();
contentValues.put(MediaStore.Images.Media.TITLE,"Temp_pic");
contentValues.put(MediaStore.Images.Media.DESCRIPTION,"TempDescription");
imageuri=this.getContentResolver()。insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
IntentcamerIntent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
camerIntent.putExtra(MediaStore.EXTRA_OUTPUT,imageuri);
startActivityForResult(camerIntent,IMAGE_PICKCAMERA_REQUEST);
}
privatevoidpickFromGallery(){
IntentgalleryIntent=newIntent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent,IMAGEPICK_GALLERY_REQUEST);
}
privateBooleancheckStoragePermission(){
booleanresult=ContextCompat.checkSelfPermission(ChatActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)==(PackageManager.PERMISSION_GRANTED);
returnresult;
}
privatevoidrequestStoragePermission(){
requestPermissions(storagePermission,STORAGE_REQUEST);
}
privatevoidsendmessage(finalStringmessage){
//creatingareferencetostoredatainfirebase
//Wewillbestoringdatausingcurrenttimein"Chatlist"
//andwearepushingdatausinguniqueidin"Chats"
DatabaseReferencedatabaseReference=FirebaseDatabase.getInstance()。getReference();
Stringtimestamp=String.valueOf(System.currentTimeMillis());
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("sender",myuid);
hashMap.put("receiver",uid);
hashMap.put("message",message);
hashMap.put("timestamp",timestamp);
hashMap.put("dilihat",false);
hashMap.put("type","text");
databaseReference.child("Chats")。push()。setValue(hashMap);
finalDatabaseReferenceref1=FirebaseDatabase.getInstance()。getReference("ChatList")。child(uid)。child(myuid);
ref1.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
if(!dataSnapshot.exists()){
ref1.child("id")。setValue(myuid);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
finalDatabaseReferenceref2=FirebaseDatabase.getInstance()。getReference("ChatList")。child(myuid)。child(uid);
ref2.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
if(!dataSnapshot.exists()){
ref2.child("id")。setValue(uid);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
}
@Override
publicbooleanonOptionsItemSelected(@NonNullMenuItemitem){
if(item.getItemId()==R.id.logout){
firebaseAuth.signOut();
checkUserStatus();
}
returnsuper.onOptionsItemSelected(item);
}
privatevoidcheckUserStatus(){
FirebaseUseruser=firebaseAuth.getCurrentUser();
if(user!=null){
myuid=user.getUid();
}
}
}

继续阅读 »

本文将讨论实现一套即时通讯聊天系统源码并附部署教程,该im源码具有以下功能:
带app源码:im.jstxym.top
我们将创建一个聊天布局,并在聊天发送消息。
●用户可以发送消息或图像。
●用户可以使用相机或图库发送图像。
●首先,请求许可将被要求发送图像使用图库或点击图像后使用相机。
●如果允许,那么用户可以发送图像,或者它将再次请求请求许可。
分步实施
步骤1:创建两个新的布局资源文件,命名为row_chat_left和row_chat_right
使用row_chat_left.xml文件。收到的信息将在左侧。类似地,使用row_chat_right.xml文件。发送给用户的消息将在右边。下面是row_chat_left.xml文件和row_chat_right.xml文件的代码。
<LinearLayout
android:id="@+id/msglayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profilec"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/profile_image"
app:civ_border_color="@null"/>
<TextView
android:id="@+id/msgc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/bg_receiver"
android:padding="15dp"
android:text="HisMessage"
android:textColor="@color/colorBlack"
android:textSize="16sp"
android:visibility="gone"/>
<ImageView
android:id="@+id/images"
android:layout_width="200dp"
android:layout_height="200dp"
android:adjustViewBounds="true"
android:background="@drawable/bg_receiver"
android:padding="15dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_images"/>
<TextView
android:id="@+id/timetv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="02/01/199006:19PM"
android:textColor="@color/colorBlack"
android:textSize="12sp"/>
</LinearLayout>
<TextView
android:id="@+id/isSeen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Delivered"
android:textAlignment="textEnd"
android:visibility="gone"/>
</LinearLayout>
步骤2:使用activity_chat.xml文件
在RecyclerView中,我们将显示所有的消息。在TextView中,用户将键入消息,并使用发送按钮,用户将发送消息。下面是activity_chat.xml文件的代码。
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ChatActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@color/colorPrimaryDark"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profiletv"
android:layout_width="35dp"
android:layout_height="35dp"
android:scaleType="centerCrop"
android:src="@drawable/profile_image"
app:civ_circle_background_color="@color/colorPrimaryDark"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/nameptv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="HisName"
android:textColor="@color/colorWhite"
android:textSize="18sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/onlinetv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Online"
android:textColor="@color/colorWhite"
android:textStyle="bold"/>
</LinearLayout>
<ImageView
android:id="@+id/block"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="5dp"
android:src="@drawable/ic_unblock"/>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/chatrecycle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/chatlayout"
android:layout_below="@id/toolbar"/>
<LinearLayout
android:id="@+id/chatlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/colorWhite"
android:gravity="center"
android:orientation="horizontal">
<ImageButton
android:id="@+id/attachbtn"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@null"
android:src="@drawable/ic_iattach"/>
<EditText
android:id="@+id/messaget"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="StartTyping"
android:inputType="textCapSentences|textMultiLine"
android:padding="15dp"/>
<ImageButton
android:id="@+id/sendmsg"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@null"
android:src="@drawable/send_message"/>
</LinearLayout>
</RelativeLayout>
步骤3:使用row_chatlist.xml文件
创建另一个布局资源文件,命名为row_chatlist。下面是row_chatlist.xml文件的代码。
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:contentPadding="3dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/profileimage"
android:layout_width="70dp"
android:layout_height="70dp"
android:src="@drawable/profile_image"/>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/onlinestatus"
android:layout_width="25dp"
android:layout_height="25dp"/>
<TextView
android:id="@+id/nameonline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_toEndOf="@id/profileimage"
android:layout_toRightOf="@id/profileimage"
android:text="HisName"
android:textColor="@color/colorBlack"
android:textSize="18sp"/>
<TextView
android:id="@+id/lastmessge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/nameonline"
android:layout_marginStart="4dp"
android:layout_toEndOf="@id/profileimage"
android:layout_toRightOf="@id/profileimage"
android:maxLines="2"
android:text="LastMessage"
android:textColor="@color/colorBlack"/>
<ImageView
android:id="@+id/blocking"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_unblock"/>
<ImageView
android:id="@+id/seen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/blocking"
android:layout_alignParentEnd="true"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_unblock"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
步骤4:使用ModelChat.java文件
创建这个类来初始化键,以便我们以后可以检索键的值。
packagecom.example.socialmediaapp;
publicclassModelChat{
Stringmessage;
publicStringgetMessage(){
returnmessage;
}
publicvoidsetMessage(Stringmessage){
this.message=message;
}
publicStringgetReceiver(){
returnreceiver;
}
publicvoidsetReceiver(Stringreceiver){
this.receiver=receiver;
}
publicStringgetSender(){
returnsender;
}
publicvoidsetSender(Stringsender){
this.sender=sender;
}
publicStringgetTimestamp(){
returntimestamp;
}
publicvoidsetTimestamp(Stringtimestamp){
this.timestamp=timestamp;
}
publicbooleanisDilihat(){
returndilihat;
}
publicvoidsetDilihat(booleandilihat){
this.dilihat=dilihat;
}
Stringreceiver;
publicModelChat(){
}
Stringsender;
publicStringgetType(){
returntype;
}
publicvoidsetType(Stringtype){
this.type=type;
}
publicModelChat(Stringmessage,Stringreceiver,Stringsender,Stringtype,Stringtimestamp,booleandilihat){
this.message=message;
this.receiver=receiver;
this.sender=sender;
this.type=type;
this.timestamp=timestamp;
this.dilihat=dilihat;
}
Stringtype;
Stringtimestamp;
booleandilihat;
}
步骤5:使用AdpaterChat.java文件
创建一个新的java类,并将该类命名为AdpaterChat。下面是AdpaterChat.java文件的代码。
packagecom.example.socialmediaapp;
importandroid.app.AlertDialog;
importandroid.content.Context;
importandroid.content.DialogInterface;
importandroid.text.format.DateFormat;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.ImageView;
importandroid.widget.LinearLayout;
importandroid.widget.TextView;
importandroid.widget.Toast;
importandroidx.annotation.NonNull;
importandroidx.recyclerview.widget.RecyclerView;
importcom.bumptech.glide.Glide;
importcom.google.firebase.auth.FirebaseAuth;
importcom.google.firebase.auth.FirebaseUser;
importcom.google.firebase.database.DataSnapshot;
importcom.google.firebase.database.DatabaseError;
importcom.google.firebase.database.DatabaseReference;
importcom.google.firebase.database.FirebaseDatabase;
importcom.google.firebase.database.Query;
importcom.google.firebase.database.ValueEventListener;
importjava.util.Calendar;
importjava.util.List;
importjava.util.Locale;
importde.hdodenhof.circleimageview.CircleImageView;
publicclassAdapterChatextendsRecyclerView.Adapter<com.example.socialmediaapp.AdapterChat.Myholder>{
privatestaticfinalintMSG_TYPE_LEFT=0;
privatestaticfinalintMSG_TYPR_RIGHT=1;
Contextcontext;
List<ModelChat>list;
Stringimageurl;
FirebaseUserfirebaseUser;
publicAdapterChat(Contextcontext,List<ModelChat>list,Stringimageurl){
this.context=context;
this.list=list;
this.imageurl=imageurl;
}
@NonNull
@Override
publicMyholderonCreateViewHolder(@NonNullViewGroupparent,intviewType){
if(viewType==MSG_TYPE_LEFT){
Viewview=LayoutInflater.from(context)。inflate(R.layout.row_chat_left,parent,false);
returnnewMyholder(view);
}else{
Viewview=LayoutInflater.from(context)。inflate(R.layout.row_chat_right,parent,false);
returnnewMyholder(view);
}
}
@Override
publicvoidonBindViewHolder(@NonNullMyholderholder,finalintposition){
Stringmessage=list.get(position)。getMessage();
StringtimeStamp=list.get(position)。getTimestamp();
Stringtype=list.get(position)。getType();
Calendarcalendar=Calendar.getInstance(Locale.ENGLISH);
calendar.setTimeInMillis(Long.parseLong(timeStamp));
Stringtimedate=DateFormat.format("dd/MM/yyyyhh:mmaa",calendar)。toString();
holder.message.setText(message);
holder.time.setText(timedate);
try{
Glide.with(context)。load(imageurl)。into(holder.image);
}catch(Exceptione){
}
if(type.equals("text")){
holder.message.setVisibility(View.VISIBLE);
holder.mimage.setVisibility(View.GONE);
holder.message.setText(message);
}else{
holder.message.setVisibility(View.GONE);
holder.mimage.setVisibility(View.VISIBLE);
Glide.with(context)。load(message)。into(holder.mimage);
}
holder.msglayput.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
AlertDialog.Builderbuilder=newAlertDialog.Builder(context);
builder.setTitle("DeleteMessage");
builder.setMessage("AreYouSureToDeleteThisMessage");
builder.setPositiveButton("Delete",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
deleteMsg(position);
}
});
builder.setNegativeButton("Cancel",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
dialog.dismiss();
}
});
builder.create()。show();
}
});
}
privatevoiddeleteMsg(intposition){
finalStringmyuid=FirebaseAuth.getInstance()。getCurrentUser()。getUid();
Stringmsgtimestmp=list.get(position)。getTimestamp();
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference()。child("Chats");
Queryquery=dbref.orderByChild("timestamp")。equalTo(msgtimestmp);
query.addListenerForSingleValueEvent(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
for(DataSnapshotdataSnapshot1:dataSnapshot.getChildren()){
if(dataSnapshot1.child("sender")。getValue()。equals(myuid)){
//anytwoofbelowcanbeused
dataSnapshot1.getRef()。removeValue();
/HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("message","ThisMessageWasDeleted");
dataSnapshot1.getRef()。updateChildren(hashMap);
Toast.makeText(context,"MessageDeleted……",Toast.LENGTH_LONG)。show();
/
}else{
Toast.makeText(context,"youcandeletonlyyourmsg…",Toast.LENGTH_LONG)。show();
}
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
}
@Override
publicintgetItemCount(){
returnlist.size();
}
@Override
publicintgetItemViewType(intposition){
firebaseUser=FirebaseAuth.getInstance()。getCurrentUser();
if(list.get(position)。getSender()。equals(firebaseUser.getUid())){
returnMSG_TYPR_RIGHT;
}else{
returnMSG_TYPE_LEFT;
}
}
classMyholderextendsRecyclerView.ViewHolder{
CircleImageViewimage;
ImageViewmimage;
TextViewmessage,time,isSee;
LinearLayoutmsglayput;
publicMyholder(@NonNullViewitemView){
super(itemView);
image=itemView.findViewById(R.id.profilec);
message=itemView.findViewById(R.id.msgc);
time=itemView.findViewById(R.id.timetv);
isSee=itemView.findViewById(R.id.isSeen);
msglayput=itemView.findViewById(R.id.msglayout);
mimage=itemView.findViewById(R.id.images);
}
}
}
步骤6:使用ChatActivity.java文件
我们正在阅读来自Firebase中的“聊天”节点的用户消息。每次数据更改时,该数据也会相应更改
chatList=newArrayList<>();
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference()。child("Chats");
使用适配器聊天加载数据设置数据值
ModelChatmodelChat=dataSnapshot1.getValue(ModelChat.class);
if(modelChat.getSender()。equals(myuid)&&
modelChat.getReceiver()。equals(uid)||
modelChat.getReceiver()。equals(myuid)
&&modelChat.getSender()。equals(uid)){
chatList.add(modelChat);//addthechatinchatlist
}
adapterChat=newAdapterChat(ChatActivity.this,chatList,image);
adapterChat.notifyDataSetChanged();
recyclerView.setAdapter(adapterChat);
在聊天参考节点值中发送消息。下面是我们如何在Firebase实时数据库中保存数据
DatabaseReferencedatabaseReference=FirebaseDatabase.getInstance()。getReference();
Stringtimestamp=String.valueOf(System.currentTimeMillis());
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("sender",myuid);
hashMap.put("receiver",uid);
hashMap.put("message",message);
hashMap.put("timestamp",timestamp);
hashMap.put("dilihat",false);
hashMap.put("type","text");
databaseReference.child("Chats")。push()。setValue(hashMap);
下面是ChatActivity.java文件的代码。
packagecom.example.socialmediaapp;
importandroid.Manifest;
importandroid.app.AlertDialog;
importandroid.app.ProgressDialog;
importandroid.content.ContentValues;
importandroid.content.DialogInterface;
importandroid.content.Intent;
importandroid.content.pm.PackageManager;
importandroid.graphics.Bitmap;
importandroid.net.Uri;
importandroid.os.Bundle;
importandroid.provider.MediaStore;
importandroid.text.TextUtils;
importandroid.text.format.DateFormat;
importandroid.view.MenuItem;
importandroid.view.View;
importandroid.widget.EditText;
importandroid.widget.ImageButton;
importandroid.widget.ImageView;
importandroid.widget.TextView;
importandroid.widget.Toast;
importandroidx.annotation.NonNull;
importandroidx.annotation.Nullable;
importandroidx.appcompat.app.AppCompatActivity;
importandroidx.appcompat.widget.Toolbar;
importandroidx.core.content.ContextCompat;
importandroidx.recyclerview.widget.LinearLayoutManager;
importandroidx.recyclerview.widget.RecyclerView;
importcom.bumptech.glide.Glide;
importcom.google.android.gms.tasks.OnFailureListener;
importcom.google.android.gms.tasks.OnSuccessListener;
importcom.google.android.gms.tasks.Task;
importcom.google.firebase.auth.FirebaseAuth;
importcom.google.firebase.auth.FirebaseUser;
importcom.google.firebase.database.DataSnapshot;
importcom.google.firebase.database.DatabaseError;
importcom.google.firebase.database.DatabaseReference;
importcom.google.firebase.database.FirebaseDatabase;
importcom.google.firebase.database.Query;
importcom.google.firebase.database.ValueEventListener;
importcom.google.firebase.storage.FirebaseStorage;
importcom.google.firebase.storage.StorageReference;
importcom.google.firebase.storage.UploadTask;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.util.ArrayList;
importjava.util.Calendar;
importjava.util.HashMap;
importjava.util.List;
publicclassChatActivityextendsAppCompatActivity{
Toolbartoolbar;
RecyclerViewrecyclerView;
ImageViewprofile,block;
TextViewname,userstatus;
EditTextmsg;
ImageButtonsend,attach;
FirebaseAuthfirebaseAuth;
Stringuid,myuid,image;
ValueEventListenervalueEventListener;
List<ModelChat>chatList;
AdapterChatadapterChat;
privatestaticfinalintIMAGEPICK_GALLERY_REQUEST=300;
privatestaticfinalintIMAGE_PICKCAMERA_REQUEST=400;
privatestaticfinalintCAMERA_REQUEST=100;
privatestaticfinalintSTORAGE_REQUEST=200;
StringcameraPermission[];
StringstoragePermission[];
Uriimageuri=null;
FirebaseDatabasefirebaseDatabase;
DatabaseReferenceusers;
booleannotify=false;
booleanisBlocked=false;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
firebaseAuth=FirebaseAuth.getInstance();
//initialisethetextviewsandlayouts
profile=findViewById(R.id.profiletv);
name=findViewById(R.id.nameptv);
userstatus=findViewById(R.id.onlinetv);
msg=findViewById(R.id.messaget);
send=findViewById(R.id.sendmsg);
attach=findViewById(R.id.attachbtn);
block=findViewById(R.id.block);
LinearLayoutManagerlinearLayoutManager=newLinearLayoutManager(this);
linearLayoutManager.setStackFromEnd(true);
recyclerView=findViewById(R.id.chatrecycle);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(linearLayoutManager);
uid=getIntent()。getStringExtra("uid");
//gettinguidofanotheruserusingintent
firebaseDatabase=FirebaseDatabase.getInstance();
//initialisingpermissions
cameraPermission=newString[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};
storagePermission=newString[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
checkUserStatus();
users=firebaseDatabase.getReference("Users");
attach.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
showImagePicDialog();
}
});
send.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
notify=true;
Stringmessage=msg.getText()。toString()。trim();
if(TextUtils.isEmpty(message)){//ifempty
Toast.makeText(ChatActivity.this,"PleaseWriteSomethingHere",Toast.LENGTH_LONG)。show();
}else{
sendmessage(message);
}
msg.setText("");
}
});
Queryuserquery=users.orderByChild("uid")。equalTo(uid);
userquery.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
//retrieveuserdata
for(DataSnapshotdataSnapshot1:dataSnapshot.getChildren()){
Stringnameh=""+dataSnapshot1.child("name")。getValue();
image=""+dataSnapshot1.child("image")。getValue();
Stringonlinestatus=""+dataSnapshot1.child("onlineStatus")。getValue();
Stringtypingto=""+dataSnapshot1.child("typingTo")。getValue();
if(typingto.equals(myuid)){//ifuseristypingtomychat
userstatus.setText("Typing…");//typestatusastyping
}else{
if(onlinestatus.equals("online")){
userstatus.setText(onlinestatus);
}else{
Calendarcalendar=Calendar.getInstance();
calendar.setTimeInMillis(Long.parseLong(onlinestatus));
Stringtimedate=DateFormat.format("dd/MM/yyyyhh:mmaa",calendar)。toString();
userstatus.setText("LastSeen:"+timedate);
}
}
name.setText(nameh);
try{
Glide.with(ChatActivity.this)。load(image)。placeholder(R.drawable.profile_image)。into(profile);
}catch(Exceptione){
}
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
readMessages();
}
@Override
protectedvoidonPause(){
super.onPause();
Stringtimestamp=String.valueOf(System.currentTimeMillis());
checkOnlineStatus(timestamp);
checkTypingStatus("noOne");
}
@Override
protectedvoidonResume(){
checkOnlineStatus("online");
super.onResume();
}
@Override
publicbooleanonSupportNavigateUp(){
onBackPressed();
returnsuper.onSupportNavigateUp();
}
privatevoidcheckOnlineStatus(Stringstatus){
//checkonlinestatus
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference("Users")。child(myuid);
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("onlineStatus",status);
dbref.updateChildren(hashMap);
}
privatevoidcheckTypingStatus(Stringtyping){
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference("Users")。child(myuid);
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("typingTo",typing);
dbref.updateChildren(hashMap);
}
@Override
protectedvoidonStart(){
checkUserStatus();
checkOnlineStatus("online");
super.onStart();
}
privatevoidreadMessages(){
//showmessageafterretrievingdata
chatList=newArrayList<>();
DatabaseReferencedbref=FirebaseDatabase.getInstance()。getReference()。child("Chats");
dbref.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
chatList.clear();
for(DataSnapshotdataSnapshot1:dataSnapshot.getChildren()){
ModelChatmodelChat=dataSnapshot1.getValue(ModelChat.class);
if(modelChat.getSender()。equals(myuid)&&
modelChat.getReceiver()。equals(uid)||
modelChat.getReceiver()。equals(myuid)
&&modelChat.getSender()。equals(uid)){
chatList.add(modelChat);//addthechatinchatlist
}
adapterChat=newAdapterChat(ChatActivity.this,chatList,image);
adapterChat.notifyDataSetChanged();
recyclerView.setAdapter(adapterChat);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
}
privatevoidshowImagePicDialog(){
Stringoptions[]={"Camera","Gallery"};
AlertDialog.Builderbuilder=newAlertDialog.Builder(ChatActivity.this);
builder.setTitle("PickImageFrom");
builder.setItems(options,newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
if(which==0){
if(!checkCameraPermission()){//ifpermissionisnotgiven
requestCameraPermission();//requestforpermission
}else{
pickFromCamera();//ifalreadyaccessgrantedthenclick
}
}elseif(which==1){
if(!checkStoragePermission()){//ifpermissionisnotgiven
requestStoragePermission();//requestforpermission
}else{
pickFromGallery();//ifalreadyaccessgrantedthenpick
}
}
}
});
builder.create()。show();
}
publicvoidonRequestPermissionsResult(intrequestCode,@NonNullString[]permissions,@NonNullint[]grantResults){
//requestforpermissionifnotgiven
switch(requestCode){
caseCAMERA_REQUEST:{
if(grantResults.length>0){
booleancamera_accepted=grantResults[0]==PackageManager.PERMISSION_GRANTED;
booleanwriteStorageaccepted=grantResults[1]==PackageManager.PERMISSION_GRANTED;
if(camera_accepted&&writeStorageaccepted){
pickFromCamera();//ifaccessgrantedthenclick
}else{
Toast.makeText(this,"PleaseEnableCameraandStoragePermissions",Toast.LENGTH_LONG)。show();
}
}
}
break;
caseSTORAGE_REQUEST:{
if(grantResults.length>0){
booleanwriteStorageaccepted=grantResults[0]==PackageManager.PERMISSION_GRANTED;
if(writeStorageaccepted){
pickFromGallery();//ifaccessgrantedthenpick
}else{
Toast.makeText(this,"PleaseEnableStoragePermissions",Toast.LENGTH_LONG)。show();
}
}
}
break;
}
}
@Override
publicvoidonActivityResult(intrequestCode,intresultCode,@NullableIntentdata){
if(resultCode==RESULT_OK){
if(requestCode==IMAGEPICK_GALLERY_REQUEST){
imageuri=data.getData();//getimagedatatoupload
try{
sendImageMessage(imageuri);
}catch(IOExceptione){
e.printStackTrace();
}
}
if(requestCode==IMAGE_PICKCAMERA_REQUEST){
try{
sendImageMessage(imageuri);
}catch(IOExceptione){
e.printStackTrace();
}
}
}
super.onActivityResult(requestCode,resultCode,data);
}
privatevoidsendImageMessage(Uriimageuri)throwsIOException{
notify=true;
finalProgressDialogdialog=newProgressDialog(this);
dialog.setMessage("SendingImage");
dialog.show();
//Ifwearesendingimageasamessage
//thenweneedtofindtheurlof
//imageafteruploadingthe
//imageinfirebasestorage
finalStringtimestamp=""+System.currentTimeMillis();
Stringfilepathandname="ChatImages/"+"post"+timestamp;//filename
Bitmapbitmap=MediaStore.Images.Media.getBitmap(this.getContentResolver(),imageuri);
ByteArrayOutputStreamarrayOutputStream=newByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG,100,arrayOutputStream);//compressingtheimageusingbitmap
finalbyte[]data=arrayOutputStream.toByteArray();
StorageReferenceref=FirebaseStorage.getInstance()。getReference()。child(filepathandname);
ref.putBytes(data)。addOnSuccessListener(newOnSuccessListener<UploadTask.TaskSnapshot>(){
@Override
publicvoidonSuccess(UploadTask.TaskSnapshottaskSnapshot){
dialog.dismiss();
Task<Uri>uriTask=taskSnapshot.getStorage()。getDownloadUrl();
while(!uriTask.isSuccessful());
StringdownloadUri=uriTask.getResult()。toString();//gettingurliftaskissuccessful
if(uriTask.isSuccessful()){
DatabaseReferencere=FirebaseDatabase.getInstance()。getReference();
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("sender",myuid);
hashMap.put("receiver",uid);
hashMap.put("message",downloadUri);
hashMap.put("timestamp",timestamp);
hashMap.put("dilihat",false);
hashMap.put("type","images");
re.child("Chats")。push()。setValue(hashMap);//pushinfirebaseusinguniqueid
finalDatabaseReferenceref1=FirebaseDatabase.getInstance()。getReference("ChatList")。child(uid)。child(myuid);
ref1.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
if(!dataSnapshot.exists()){
ref1.child("id")。setValue(myuid);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
finalDatabaseReferenceref2=FirebaseDatabase.getInstance()。getReference("ChatList")。child(myuid)。child(uid);
ref2.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
if(!dataSnapshot.exists()){
ref2.child("id")。setValue(uid);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
}
}
})。addOnFailureListener(newOnFailureListener(){
@Override
publicvoidonFailure(@NonNullExceptione){
}
});
}
privateBooleancheckCameraPermission(){
booleanresult=ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)==(PackageManager.PERMISSION_GRANTED);
booleanresult1=ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)==(PackageManager.PERMISSION_GRANTED);
returnresult&&result1;
}
privatevoidrequestCameraPermission(){
requestPermissions(cameraPermission,CAMERA_REQUEST);
}
privatevoidpickFromCamera(){
ContentValuescontentValues=newContentValues();
contentValues.put(MediaStore.Images.Media.TITLE,"Temp_pic");
contentValues.put(MediaStore.Images.Media.DESCRIPTION,"TempDescription");
imageuri=this.getContentResolver()。insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
IntentcamerIntent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
camerIntent.putExtra(MediaStore.EXTRA_OUTPUT,imageuri);
startActivityForResult(camerIntent,IMAGE_PICKCAMERA_REQUEST);
}
privatevoidpickFromGallery(){
IntentgalleryIntent=newIntent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent,IMAGEPICK_GALLERY_REQUEST);
}
privateBooleancheckStoragePermission(){
booleanresult=ContextCompat.checkSelfPermission(ChatActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE)==(PackageManager.PERMISSION_GRANTED);
returnresult;
}
privatevoidrequestStoragePermission(){
requestPermissions(storagePermission,STORAGE_REQUEST);
}
privatevoidsendmessage(finalStringmessage){
//creatingareferencetostoredatainfirebase
//Wewillbestoringdatausingcurrenttimein"Chatlist"
//andwearepushingdatausinguniqueidin"Chats"
DatabaseReferencedatabaseReference=FirebaseDatabase.getInstance()。getReference();
Stringtimestamp=String.valueOf(System.currentTimeMillis());
HashMap<String,Object>hashMap=newHashMap<>();
hashMap.put("sender",myuid);
hashMap.put("receiver",uid);
hashMap.put("message",message);
hashMap.put("timestamp",timestamp);
hashMap.put("dilihat",false);
hashMap.put("type","text");
databaseReference.child("Chats")。push()。setValue(hashMap);
finalDatabaseReferenceref1=FirebaseDatabase.getInstance()。getReference("ChatList")。child(uid)。child(myuid);
ref1.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
if(!dataSnapshot.exists()){
ref1.child("id")。setValue(myuid);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
finalDatabaseReferenceref2=FirebaseDatabase.getInstance()。getReference("ChatList")。child(myuid)。child(uid);
ref2.addValueEventListener(newValueEventListener(){
@Override
publicvoidonDataChange(@NonNullDataSnapshotdataSnapshot){
if(!dataSnapshot.exists()){
ref2.child("id")。setValue(uid);
}
}
@Override
publicvoidonCancelled(@NonNullDatabaseErrordatabaseError){
}
});
}
@Override
publicbooleanonOptionsItemSelected(@NonNullMenuItemitem){
if(item.getItemId()==R.id.logout){
firebaseAuth.signOut();
checkUserStatus();
}
returnsuper.onOptionsItemSelected(item);
}
privatevoidcheckUserStatus(){
FirebaseUseruser=firebaseAuth.getCurrentUser();
if(user!=null){
myuid=user.getUid();
}
}
}

收起阅读 »

uapp 一个能让uniapp离线打包更简单高效的脚手架

uniapp离线打包

uapp

uapp 让uniapp离线打包更简单高效。

uniapp是一个基于Vue同构技术的多平台前端框架,对公司或创业者来说,只需要有一个会Vue的前端,就可以同时写App(android/ios),H5,快应用,微信/QQ/抖音/飞书/百度/支付宝等各家小程序,维护一套代码可以发布10多个平台。有以下几大好处:

  • 发布多个平台获取更多流量
  • 一旦熟悉,开发效率极高
  • 至少省 1 / 3 研发成本,商业试错成本更低
  • 即使当前不需要发布多平台,同样花时间写代码,为什么不选择复用价值更高的方法呢

但 uniapp 官方发布的离线包里只有 DEMO,对于一个新的项目,需要手动更改的配置较多,且调试基座和正式发版共用一个配置,维护起来也很不方便。uapp 就是我们在实践了一些产品后,积累的一些经验,分离了调试和发布的配置,也方便通过命令加入自动化集成。

为什么不使用在线打包呢?

uniapp 在线打包,一般无法满足灵活的需求,比如:

  • 没法在团队里实施自动化集成(自动构建、单元测试、发布)。
  • 有些包是冗余的,在线打包不能控制具体打入哪些包。
  • 在线打包有大小限制,超过需要单独付费,因为特别占用官方服务器资源。
  • 写uniapp插件扩展时,必须有离线工程才方便调试,且可以自己控制是否发布插件。我们也是在写 ffmpeg 扩展时,遇到些许不便。

先安装 uappsdk

1、 安装 uapp 命令

npm install -g uapp  

# 初始化或更新 uappsdk  
uapp sdk init

更多说明可以参考:

https://github.com/uappkit/cli

喜欢的小伙伴可以给个 star 关注,未来会逐步加入更多便利功能,也欢迎反馈你的需求。

继续阅读 »

uapp

uapp 让uniapp离线打包更简单高效。

uniapp是一个基于Vue同构技术的多平台前端框架,对公司或创业者来说,只需要有一个会Vue的前端,就可以同时写App(android/ios),H5,快应用,微信/QQ/抖音/飞书/百度/支付宝等各家小程序,维护一套代码可以发布10多个平台。有以下几大好处:

  • 发布多个平台获取更多流量
  • 一旦熟悉,开发效率极高
  • 至少省 1 / 3 研发成本,商业试错成本更低
  • 即使当前不需要发布多平台,同样花时间写代码,为什么不选择复用价值更高的方法呢

但 uniapp 官方发布的离线包里只有 DEMO,对于一个新的项目,需要手动更改的配置较多,且调试基座和正式发版共用一个配置,维护起来也很不方便。uapp 就是我们在实践了一些产品后,积累的一些经验,分离了调试和发布的配置,也方便通过命令加入自动化集成。

为什么不使用在线打包呢?

uniapp 在线打包,一般无法满足灵活的需求,比如:

  • 没法在团队里实施自动化集成(自动构建、单元测试、发布)。
  • 有些包是冗余的,在线打包不能控制具体打入哪些包。
  • 在线打包有大小限制,超过需要单独付费,因为特别占用官方服务器资源。
  • 写uniapp插件扩展时,必须有离线工程才方便调试,且可以自己控制是否发布插件。我们也是在写 ffmpeg 扩展时,遇到些许不便。

先安装 uappsdk

1、 安装 uapp 命令

npm install -g uapp  

# 初始化或更新 uappsdk  
uapp sdk init

更多说明可以参考:

https://github.com/uappkit/cli

喜欢的小伙伴可以给个 star 关注,未来会逐步加入更多便利功能,也欢迎反馈你的需求。

收起阅读 »

原来用UNIAPP做PWA应用这么简单,这个站,十天时间就开发了好几个

今天发现一个很有趣的网站,这个网站的名称叫做PWA导航,它居然用uniapp开发了近十款PWA应用!而且藐视有变现能力!各位开发者可以去看看!

网址:https://i.44api.com/index.html

继续阅读 »

今天发现一个很有趣的网站,这个网站的名称叫做PWA导航,它居然用uniapp开发了近十款PWA应用!而且藐视有变现能力!各位开发者可以去看看!

网址:https://i.44api.com/index.html

收起阅读 »

招外包,长期固定兼职,长期有项目,合作熟悉可全职,在家上班

招uniapp 长期兼职活外包,有稳定项目长期可做,有想长久在家稳定赚钱的,请加我V: t260852
最好是前后面一起做。

招uniapp 长期兼职活外包,有稳定项目长期可做,有想长久在家稳定赚钱的,请加我V: t260852
最好是前后面一起做。

uniapp项目打包成快手小程序的分包问题/项目体积过大问题

hbuilder的版本是最新版3.3.13.20220314。 目前uniapp的项目打包成快手小程序的时候,是把主包和分包的所有页面都放到app.json的主包里面的,分包那里是一个空的数组。这会导致项目主包过大而无法预览与上传快手小程序。希望uniapp打包尽快适配快手小程序的分包。

继续阅读 »

hbuilder的版本是最新版3.3.13.20220314。 目前uniapp的项目打包成快手小程序的时候,是把主包和分包的所有页面都放到app.json的主包里面的,分包那里是一个空的数组。这会导致项目主包过大而无法预览与上传快手小程序。希望uniapp打包尽快适配快手小程序的分包。

收起阅读 »

有一套接近完整的基于uniapp的社交软件出售

nvue

有一套接近完整的基于uniapp的社交体系出售,支持二次开发。
前端端采用nvue,渲染接近原生。

已打包安桌端+ios端
1、前端nvue
2、后端hf php框架
3、im集成hf php聊天系统
4、短信推送等集成uniapp

有需求的详聊
qq 238690

继续阅读 »

有一套接近完整的基于uniapp的社交体系出售,支持二次开发。
前端端采用nvue,渲染接近原生。

已打包安桌端+ios端
1、前端nvue
2、后端hf php框架
3、im集成hf php聊天系统
4、短信推送等集成uniapp

有需求的详聊
qq 238690

收起阅读 »

ios上传AppStore提示更新协议

iOS

当有协议更新时,所有的关联账户中都要同意,即使是不同公司的APP,但是只要你的账户关联了,所有的都要同意,你的APP才能上传。

当有协议更新时,所有的关联账户中都要同意,即使是不同公司的APP,但是只要你的账户关联了,所有的都要同意,你的APP才能上传。

关于打包64位不成功

原生插件 上架 打包

温馨提示,以后用原生插件,一定要看是否支持64位,如果作者没有在插件文档中表明,请咨询作者之后再用。
1.首先确保manifest.json -> App常用其它设置 -> 支持的CPU类型 勾选 arm64-v8a

  1. 如果勾选了64位,打包之后还是32位,那么应该就是你用的原生插件中有不支持64位的,请联系作者,或者换插件。
继续阅读 »

温馨提示,以后用原生插件,一定要看是否支持64位,如果作者没有在插件文档中表明,请咨询作者之后再用。
1.首先确保manifest.json -> App常用其它设置 -> 支持的CPU类型 勾选 arm64-v8a

  1. 如果勾选了64位,打包之后还是32位,那么应该就是你用的原生插件中有不支持64位的,请联系作者,或者换插件。
收起阅读 »

uniapp自定义调试基座打包,unipush配置了manifest,但未开通unipush服务

unipush


原因是打包的APPID与开通push服务的APPID不一致导致的


原因是打包的APPID与开通push服务的APPID不一致导致的

百度广告应用所有权验证教程

百度广告 所有权验证

申请百度广告后,开发者必须要空包签名验证应用的所有权,以下为Android和IOS的签名教程:

Android获取签名

说明

空包签名需要本地配置jdk环境

命令行方式

命令格式:

jarsigner -verbose -keystore [签名文件路径] -signedjar [签名后apk的文件路径] [未签名apk的文件路径] [证书别名]  

参数说明

  • -verbose 签名时输出详细信息,便于您查看签名结果

  • -keystore 指定签名文件的存放路径

  • -signedjar 指定签名后的apk文件的存放路径

  • [未签名apk的文件路径] 指定从百度联盟平台下载的需要您签名的apk文件的存放路径

  • [证书别名] 指定签名时使用的证书。请注意,必须与发布应用时使用的证书相同

  • Linux或Mac平台。

    • 打开 Terminal 程序
    • 切换到下载的未签名apk空包的存放目录
    • 在当前目录下执行命令完成签名

命令示例:jarsigner -verbose -keystore ~/Workspace/myKeystore.jks -signedjar ./mssp-verify-signed.apk ./mssp-verify.apk myKey

  • Windows平台。
    • 打开 命令提示符 程序
    • 切换到下载的未签名apk空包的存放目录
    • 在当前目录下执行命令完成签名

命令示例:jarsigner -verbose -keystore C:\Documents\myKeystore.jks -signedjar mssp-verify-signed.apk mssp-verify.apk myKey

HBuilder X 插件方式

插件地址:Android Apk包签名

打开上述插件地址,点击左侧“使用 HBuilderX 导入插件”,导入插件到HBuilder X中

点击HBuilder X顶部菜单【工具】,点击【Android Apk包签名】,按照说明填写即可。

IOS获取签名

  1. 进入苹果开发者主页(https://developer.apple.com)
  2. 点击菜单栏的 Account 按钮,输入开发者账号登录
  3. 进入 Certificates, Identifiers & Profiles
  4. 从左侧导航中选择 Provisioning Profiles - Distribution
  5. 在右侧选择需要认证的APP,点击APP名称展开,并点击下载即可获得一个 .mobileprovision 文件
继续阅读 »

申请百度广告后,开发者必须要空包签名验证应用的所有权,以下为Android和IOS的签名教程:

Android获取签名

说明

空包签名需要本地配置jdk环境

命令行方式

命令格式:

jarsigner -verbose -keystore [签名文件路径] -signedjar [签名后apk的文件路径] [未签名apk的文件路径] [证书别名]  

参数说明

  • -verbose 签名时输出详细信息,便于您查看签名结果

  • -keystore 指定签名文件的存放路径

  • -signedjar 指定签名后的apk文件的存放路径

  • [未签名apk的文件路径] 指定从百度联盟平台下载的需要您签名的apk文件的存放路径

  • [证书别名] 指定签名时使用的证书。请注意,必须与发布应用时使用的证书相同

  • Linux或Mac平台。

    • 打开 Terminal 程序
    • 切换到下载的未签名apk空包的存放目录
    • 在当前目录下执行命令完成签名

命令示例:jarsigner -verbose -keystore ~/Workspace/myKeystore.jks -signedjar ./mssp-verify-signed.apk ./mssp-verify.apk myKey

  • Windows平台。
    • 打开 命令提示符 程序
    • 切换到下载的未签名apk空包的存放目录
    • 在当前目录下执行命令完成签名

命令示例:jarsigner -verbose -keystore C:\Documents\myKeystore.jks -signedjar mssp-verify-signed.apk mssp-verify.apk myKey

HBuilder X 插件方式

插件地址:Android Apk包签名

打开上述插件地址,点击左侧“使用 HBuilderX 导入插件”,导入插件到HBuilder X中

点击HBuilder X顶部菜单【工具】,点击【Android Apk包签名】,按照说明填写即可。

IOS获取签名

  1. 进入苹果开发者主页(https://developer.apple.com)
  2. 点击菜单栏的 Account 按钮,输入开发者账号登录
  3. 进入 Certificates, Identifiers & Profiles
  4. 从左侧导航中选择 Provisioning Profiles - Distribution
  5. 在右侧选择需要认证的APP,点击APP名称展开,并点击下载即可获得一个 .mobileprovision 文件
收起阅读 »

无线adb调试(无offline问题)

无线调试 adb
  • 手机开启"USB调试" 和 "仅充电"允许ADB调试 并 与电脑是局域网(有公网当我没说);
  • \HBuilderX.3.3.5.20211229.full\HBuilderX\plugins\launcher\tools\adbs 目录下打开cmd;

cmd执行 :

  • "adb connect 手机IP地址" (失败往下看)
  • "adb tcpip 设置端口" (需要usb连接调试)
  • "adb connect 手机IP地址"
  • "adb devices" (查看连接)
继续阅读 »
  • 手机开启"USB调试" 和 "仅充电"允许ADB调试 并 与电脑是局域网(有公网当我没说);
  • \HBuilderX.3.3.5.20211229.full\HBuilderX\plugins\launcher\tools\adbs 目录下打开cmd;

cmd执行 :

  • "adb connect 手机IP地址" (失败往下看)
  • "adb tcpip 设置端口" (需要usb连接调试)
  • "adb connect 手机IP地址"
  • "adb devices" (查看连接)
收起阅读 »