第一步:gradle配置
项目.gradle
repositories{
jcenter()
maven {
url "http://mvn.leancloud.cn/nexus/content/repositories/releases"
}
}
app.gradle
compile ('cn.leancloud.android:avoscloud-sdk:v3.+')//基础包
compile('cn.leancloud.android:chatkit:1.0.+') //实施通讯包
compile 'cn.leancloud.android:avoscloud-statistics:v3.4.5@aar' //统计包
compile ('cn.leancloud.android:avoscloud-push:v3.+@aar'){transitive = true}//推送
第二步:minifest.xml配置
权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
保存离线报告的缓存数据。
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
这两个权限是为了获取用户手机的 IMEI 以及 WiFi 的 Mac 地址,用来唯一的标识用户。
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
android.permission.READ_LOGS
获取客户端 crash log。通过将 crash log 汇报到服务器上,你可以了解你的应用 crash 的原因以及次数。
接收推送:不使用推送可以不加
<service android:name="com.avos.avoscloud.PushService" />
<receiver android:name="com.avos.avoscloud.AVBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="com.xhl.PUSH_DEMO"/>//如果是自定义广播要自定义action
</intent-filter>
</receiver>
第三步:初始化
application
// 初始化应用信息
AVOSCloud.initialize(this, app_id, app_key);
//AVOSCloud.useAVCloudUS();// 启用北美节点,默认为中国的节点,所以不需要此行代码;
AVOSCloud.setDebugLogEnabled(true);//在应用发布之前,关闭调试日志,以免暴露敏感数据
AVAnalytics.setAnalyticsEnabled(true);//统计开关
AVAnalytics.enableCrashReport(this, true);//应用异常统计
AVAnalytics.setSessionContinueMillis(long mills);//设置自定义home间隔时间,超过返回将会认为另一个session;
第四步:使用,分四大模块
1、基础数据存储:
(1)存储:
AVObject testObject = new AVObject("TestObject");// 构建对象
testObject.put("name","content");
testObject.put("priority", 1);// 设置优先级
testObject.saveInBackground(new SaveCallback() {
@Override
public void done(AVException e) {
if(e == null){//保存成功
Log.d("name","success!");
}
}
});
(2)查询:
AVQuery<AVObject> avQuery = new AVQuery<>("TestObject");
avQuery.getInBackground("objectId", new GetCallback<AVObject>() {
@Override
public void done(AVObject avObject, AVException e) {
if(e == null){
int priority = avObject.getInt("priority");
String content = avObject.getString("content");
// 获取三个特殊属性
String objectId = avObject.getObjectId();
Date updatedAt = avObject.getUpdatedAt();
Date createdAt = avObject.getCreatedAt();
}
}
});
2、统计模块:
(1)指定发布通道
<meta-data android:name="leancloud" android:value="LeanCloud"/>
分别在onPause()和onResume();
(2)activity统计:
AVAnalytics.onPause(this);
AVAnalytics.onResume(this);
(3)fragment统计:
AVAnalytics.onFragmentEnd("myfragment");
AVAnalytics.onFragmentStart("myfragment");
(4)事件统计:
AVAnalytics.onEvent(Context context, String eventName);
AVAnalytics.onEvent(Context context, String eventName, String tag);//多标签事件统计
AVAnalytics.onEvent(Context context, String eventName, int count);//事件累计
AVAnalytics.onEvent(Context context, String eventName, String label, int count)
AVAnalytics.setOnlineConfigureListener(new AVOnlineConfigureListener() {
@Override
public void onDataReceived(JSONObject data) {
AVAnalytics.getConfigParams(getContext(), "key");
}
});
AVAnalytics.updateOnlineConfig(getContext());
3、推送模块:
PushService.setDefaultPushCallback(this, PushDemo.class);// 设置默认打开的Activity;
PushService.subscribe(this, "public", PushDemo.class);
PushService.subscribe(this, "private", Callback1.class);
PushService.subscribe(this, "protected", Callback2.class);
PushService.unsubscribe(context, "protected");//退订之后需要重新保存 Installation
这段代码应该在应用启动的时候调用一次,保证设备注册到 LeanCloud 云端。
在默认打开的actiivity里
AVInstallation.getCurrentInstallation().saveInBackground(new SaveCallback() {
public void done(AVException e) {
if (e == null) {
// 保存成功
String installationId = AVInstallation.getCurrentInstallation().getInstallationId();
// 关联 installationId 到用户表等操作……
} else {
// 保存失败,输出错误信息
}
}
});
AVAnalytics.trackAppOpened(intent);追踪推送打开的情况;
要拿到推送内容并根据推送内容跳转不同路径,需要自定义Receiver,在PushDemo里getIntent的到PendingIntent里的resultIntent;该自定义Receiver只能接受到json推送;
@Override
public void onReceive(Context context, Intent intent) {
try {
JSONObject json = new JSONObject(intent.getExtras().getString("com.avos.avoscloud.Data"));
final String message = json.getString("alert");
Intent resultIntent = new Intent(AVOSCloud.applicationContext, PushActivity.class);
resultIntent.putExtra(AVConstants.PUSH_INTENT_KEY, 1);
resultIntent.putExtra("Data", intent.getExtras().getString("com.avos.avoscloud.Data"));
PendingIntent pendingIntent =
PendingIntent.getActivity(AVOSCloud.applicationContext, 0, resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =new NotificationCompat
.Builder(AVOSCloud.applicationContext).setSmallIcon(R.mipmap.ic_launcher) .setContentTitle(AVOSCloud.applicationContext.getResources().getString(R.string.app_name))
.setContentText(message)
.setTicker(message);
mBuilder.setContentIntent(pendingIntent);
mBuilder.setAutoCancel(true);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
NotificationManager mNotifyMgr =(NotificationManager) AVOSCloud.applicationContext.getSystemService(Context.NOTIFICATION_SERVICE);
if(!TextUtils.isEmpty(message)){
mNotifyMgr.notify(0, mBuilder.build());
}
} catch (JSONException e) {
Log.d(TAG, "JSONException: " + e.getMessage());
}
}
在线推送json数据,不可少了"slient":"true","action": "自定义广播action",
4、实施通讯模块:
(1)新建AddRequest类继承AVObject,请求添加类,
@AVClassName("AddRequest")
public class AddRequest extends AVObject {
public static final int STATUS_WAIT = 0;
public static final int STATUS_DONE = 1;
public static final String FROM_USER = "fromUser";
public static final String TO_USER = "toUser";
public static final String STATUS = "status";
/**
* 标记接收方是否已读该消息
*/
public static final String IS_READ = "isRead";
public AddRequest() {
}
public LeanchatUser getFromUser() {
return getAVUser(FROM_USER, LeanchatUser.class);
}
public void setFromUser(LeanchatUser fromUser) {
put(FROM_USER, fromUser);
}
public LeanchatUser getToUser() {
return getAVUser(TO_USER, LeanchatUser.class);
}
public void setToUser(LeanchatUser toUser) {
put(TO_USER, toUser);
}
public int getStatus() {
return getInt(STATUS);
}
public void setStatus(int status) {
put(STATUS, status);
}
public boolean isRead() {
return getBoolean(IS_READ);
}
public void setIsRead(boolean isRead) {
put(IS_READ, isRead);
}
}
(2)查询好友:
AVQuery.CachePolicy policy =
(isForce ? AVQuery.CachePolicy.NETWORK_ELSE_CACHE : AVQuery.CachePolicy.CACHE_ELSE_NETWORK);
LeanchatUser.getCurrentUser().findFriendsWithCachePolicy(policy, new FindCallback<LeanchatUser>() {
@Override
public void done(List<LeanchatUser> list, AVException e) {
//设置用户列表;
}
});
(3)查询附近:
PreferenceMap preferenceMap = PreferenceMap.getCurUserPrefDao(App.ctx);
AVGeoPoint geoPoint = preferenceMap.getLocation();
if (geoPoint == null) {
LogUtils.i("geo point is null");
return;
}
AVQuery<LeanchatUser> q = LeanchatUser.getQuery(LeanchatUser.class);
LeanchatUser user = LeanchatUser.getCurrentUser();
q.whereNotEqualTo(Constants.OBJECT_ID, user.getObjectId());//除自己之外
if (orderType == Constants.ORDER_DISTANCE) {
q.whereNear(LeanchatUser.LOCATION, geoPoint);//添加一个基于距离的约束寻找附近的对象与关键值给定的点。
} else {
q.orderByDescending(Constants.UPDATED_AT);//排序列
}
q.skip(skip);//pageSize
q.limit(limit);//pageNum
q.setCachePolicy(AVQuery.CachePolicy.NETWORK_ELSE_CACHE);//改变这个查询的缓存策略
q.findInBackground(new FindCallback<LeanchatUser>() {
@Override
public void done(List<LeanchatUser> list, AVException e) {
}
(4)查询请求:
LeanchatUser user = LeanchatUser.getCurrentUser();
AVQuery<AddRequest> q = AVObject.getQuery(AddRequest.class);
q.include(AddRequest.FROM_USER);
q.skip(skip);
q.limit(limit);
q.whereEqualTo(AddRequest.TO_USER, user);
q.orderByDescending(AVObject.CREATED_AT);
q.setCachePolicy(AVQuery.CachePolicy.NETWORK_ELSE_CACHE);
q.findInBackground(new FindCallback<AddRequest>() {
@Override
public void done(List<AddRequest> list, AVException e) {
AddRequestManager.getInstance().markAddRequestsRead(list);
final List<AddRequest> filters = new ArrayList<AddRequest>();
for (AddRequest addRequest : list) {
if (addRequest.getFromUser() != null) {
filters.add(addRequest);
}
}
//设置数据源;
}
});
(5)添加好友:
new SimpleNetTask(ctx) {
@Override
protected void doInBack() throws Exception {
LeanchatUser curUser = LeanchatUser.getCurrentUser();//自己
AVQuery<AddRequest> q = AVObject.getQuery(AddRequest.class);
q.whereEqualTo(AddRequest.FROM_USER, curUser);
q.whereEqualTo(AddRequest.TO_USER, toUser);//对方
q.whereEqualTo(AddRequest.STATUS, AddRequest.STATUS_WAIT);
int count = 0;
try {
count = q.count();
} catch (AVException e) {
if (e.getCode() == AVException.OBJECT_NOT_FOUND) {
count = 0;
} else {
throw e;
}
}
if (count > 0) {
// 抛出异常,然后提示用户
throw new IllegalStateException(toast....(”已经发送请求“));
} else {
AddRequest add = new AddRequest();
add.setFromUser(curUser);
add.setToUser(toUser);
add.setStatus(AddRequest.STATUS_WAIT);
add.setIsRead(false);
add.save();//保存请求
}
}
@Override
protected void onSucceed() {
AVQuery query = AVInstallation.getQuery();
query.whereContains(“channels”, userId);//对方的userid
AVPush push = new AVPush();
push.setQuery(query);
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put(“alert”, “您有新的好友申请”);
dataMap.put(“action”, “invitation_action”);
push.setData(dataMap);
push.sendInBackground();//推送给对方
}
}.execute();
(6)同意请求:调用agreeAddRequest;
public void agreeAddRequest(final AddRequest addRequest, final SaveCallback saveCallback) {
addFriend(addRequest.getFromUser().getObjectId(), new SaveCallback() {
@Override
public void done(AVException e) {
if (e != null) {
if (e.getCode() == AVException.DUPLICATE_VALUE) {
addRequest.setStatus(AddRequest.STATUS_DONE);
addRequest.saveInBackground(saveCallback);
} else {
saveCallback.done(e);
}
} else {
addRequest.setStatus(AddRequest.STATUS_DONE);
addRequest.saveInBackground(saveCallback);
}
}
});
}
public static void addFriend(String friendId, final SaveCallback saveCallback) {
LeanchatUser user = LeanchatUser.getCurrentUser();
user.followInBackground(friendId, new FollowCallback() {
@Override
public void done(AVObject object, AVException e) {
if (saveCallback != null) {
saveCallback.done(e);
}
}
});
}
(7)拒绝请求:
直接调用AddRequest.deleteInBackground删除;
(8)创建一对一回话:
Map<String, Object> attrs = new HashMap<>();
attrs.put(”type“, 0);群聊为1;
LCChatKit.getInstance().getClient().createConversation(Arrays.asList(toUserId), "", attrs, false, true, new AVIMConversationCreatedCallback() {
@Override
public void done(AVIMConversation avimConversation, AVIMException e) {
if (e == null) {
AVIMTextMessage message = new AVIMTextMessage();
message.setText(getString(R.string.message_when_agree_request));
avimConversation.sendMessage(message, null);
}
}
});
(9)创建群聊:
LCIMProfileCache.getInstance().getCachedUsers(List<String> memberIds, new AVCallback<List<LCChatKitUser>>() {
@Override
protected void internalDone0(List<LCChatKitUser> lcimUserProfiles, AVException e) {
List<String> nameList = new ArrayList<String>();
for (LCChatKitUser userProfile : lcimUserProfiles) {
nameList.add(userProfile.getUserName());
}
Map<String, Object> attrs = new HashMap<>();
attrs.put(ConversationType.TYPE_KEY, ConversationType.Group.getValue());
attrs.put("name", TextUtils.join(",", nameList));
LCChatKit.getInstance().getClient().createConversation(memberIds, "", attrs, false, true, callback);
}
});
(10)登录
LeanchatUser.logInInBackground(name, password, new LogInCallback<LeanchatUser>() {
@Override
public void done(LeanchatUser avUser, AVException e) {
dialog.dismiss();
if (e==null)) {
登陸成功;
使用到chatkit,加上这句代码LCChatKit.getInstance().open(LeanchatUser.getCurrentUserId(), new AVIMClientCallback() {}
}
}
}, LeanchatUser.class);
(11)退出
LCChatKit.getInstance().close(new AVIMClientCallback() {
@Override
public void done(AVIMClient avimClient, AVIMException e) {
}
});
PushManager.getInstance().unsubscribeCurrentUserChannel();
LeanchatUser.logOut();