Commit 5723863a by 王文龙

first commit

parents
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
IMTeacher
\ No newline at end of file
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" alias="false" withSubpackages="false" />
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
<package name="io.ktor" alias="false" withSubpackages="true" />
</value>
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$USER_HOME$/.gradle/wrapper/dists/gradle-4.4-all/9br9xq1tocpiv8o6njlyu5op1/gradle-4.4" />
<option name="gradleJvm" value="1.8" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven3" />
<option name="name" value="maven3" />
<option name="url" value="http://maven.aliyun.com/nexus/content/repositories/releases/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://developer.huawei.com/repo/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="http://maven.base.eoffcn.com/repository/zglive/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven4" />
<option name="name" value="maven4" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
/build
\ No newline at end of file
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
apply plugin: 'org.greenrobot.greendao'
def releaseTimeFull() {
Date date = new Date();
date.hours += 8;
return date.format("MMddHHmm", TimeZone.getTimeZone("CCT"))
}
android {
compileSdkVersion 29
defaultConfig {
applicationId "com.offcn.imclient"
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
ndk {
abiFilters "armeabi-v7a"
}
}
signingConfigs {
debug {
storeFile file("../keystore/zgim.keystore")
storePassword "zgim123456"
keyAlias "zgimalias.keystore"
keyPassword "zgim123456"
}
release {
storeFile file("../keystore/zgim.keystore")
storePassword "zgim123456"
keyAlias "zgimalias.keystore"
keyPassword "zgim123456"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
build {
zipAlignEnabled true
shrinkResources false
minifyEnabled false
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "imclient_v${defaultConfig.versionName}_${releaseTimeFull()}_${buildType.name}.apk";
}
}
}
release {
zipAlignEnabled true
shrinkResources false
minifyEnabled false
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "imclient_v${defaultConfig.versionName}_${releaseTimeFull()}_${buildType.name}.apk";
}
}
}
}
greendao {
schemaVersion 1
daoPackage 'com.offcn.imclient.greendao.gen'
targetGenDir 'src/main/java'
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.android.support:multidex:1.0.3'
implementation("com.offcn.live:titleview:1.1.0-s1")
implementation("com.offcn.live:imsdk-kit:1.0.0.4")
// DB
implementation 'org.greenrobot:greendao:3.2.2'
implementation 'com.android.volley:volley:1.1.1'
}
\ No newline at end of file
{
"agcgw":{
"backurl":"connect-drcn.dbankcloud.cn",
"url":"connect-drcn.hispace.hicloud.com"
},
"client":{
"cp_id":"890086000102050749",
"product_id":"736430079244600637",
"client_id":"428619366230131712",
"client_secret":"0D095EC16F9F17A74899448A4F038C0DE64B3E04FF760788B3AD876381BB4D29",
"app_id":"102733647",
"package_name":"com.offcn.im.demo",
"api_key":"CgB6e3x929EyFzS+R9oesSLzvPTkeqrPk3dGPHkKgSm53FQVyD5S/A5bu8D+vSiFiwwSBKZdKqQTYjx1PSgpEXPE"
},
"service":{
"analytics":{
"collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
"resource_id":"p1",
"channel_id":""
},
"cloudstorage":{
"storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn"
},
"ml":{
"mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn"
}
},
"region":"CN",
"configuration_version":"1.0"
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
package com.offcn.imclient;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.offcn.imclient", appContext.getPackageName());
}
}
\ No newline at end of file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.offcn.imclient">
<application
android:name=".MyApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
<!-- 闪屏页-->
<activity
android:name=".ui.SplashActivity"
android:configChanges="keyboardHidden|screenSize|orientation"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 主页-->
<activity
android:name=".ui.MainActivity"
android:configChanges="keyboardHidden|screenSize|orientation"
android:launchMode="singleTask"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="com.offcn.imclient"
android:pathPrefix="/chatlist"
android:scheme="offcn" />
</intent-filter>
</activity>
<!-- 登录页-->
<activity
android:name=".ui.LoginActivity"
android:configChanges="keyboardHidden|screenSize|orientation"
android:screenOrientation="portrait"></activity>
<!-- 会话聊天页-->
<activity
android:name=".ui.ChatActivity"
android:configChanges="keyboardHidden|screenSize|orientation"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="com.offcn.imclient"
android:pathPrefix="/chat/"
android:scheme="offcn" />
</intent-filter>
</activity>
<!-- 中公IM平台appkey-->
<meta-data
android:name="com.offcn.live.im.appkey"
android:value="offcn_live" />
<!-- android:value="461cea0d0f9e6969b8a40eef697b0457" />-->
<!-- android:value="offcn_live" />-->
<meta-data
android:name="com.offcn.live.im.appsecret"
android:value="offcn_im" />
<!-- android:value="80b0d072d5a4" />-->
<!-- android:value="offcn_im" />-->
<!--华为推送。根目录下添加 agconnect-services.json,由华为开放平台自行获取-->
<!--小米推送。长数字解析异常,需置于 strings.xml-->
<meta-data
android:name="com.xiaomi.mipush.app_id"
android:value="@string/push_mi_appid" />
<meta-data
android:name="com.xiaomi.mipush.app_key"
android:value="@string/push_mi_appkey" />
<!--VIVO推送。长数字解析异常,需置于 strings.xml-->
<meta-data
android:name="com.vivo.push.api_key"
android:value="@string/push_vivo_appkey" />
<meta-data
android:name="com.vivo.push.app_id"
android:value="@string/push_vivo_appid" />
<!--OPPO推送。长数字解析异常,需置于 strings.xml-->
<meta-data
android:name="com.heytap.oppopush.app_key"
android:value="@string/push_oppo_appkey" />
<meta-data
android:name="com.heytap.oppopush.app_secret"
android:value="@string/push_oppo_appsecret" />
<!--begin 点击推送通知栏处理配置-->
<activity
android:name=".ui.PushTranslateActivity"
android:excludeFromRecents="true"
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|screenSize|orientation"
android:taskAffinity="com.offcn.im.demo.push.activity.PushTranslateActivity"
android:theme="@style/Activity.Translucent">
<intent-filter>
<action android:name="com.offcn.live.im.push" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!--end 点击推送通知栏处理配置-->
</application>
</manifest>
\ No newline at end of file
package com.offcn.imclient;
import android.content.Context;
import com.jyall.base.util.EventBusCenter;
import com.jyall.base.util.EventBusUtil;
import com.offcn.imclient.bean.UserBean;
import com.offcn.imclient.util.Constants;
import com.offcn.imclient.util.LoginManager;
import com.offcn.imclient.util.UserBeanDaoManager;
import com.offcn.live.im.OIMCallback;
import com.offcn.live.im.OIMSDK;
import com.offcn.live.im.bean.OIMUserInfo;
import com.offcn.live.im.util.ZGLLogUtils;
import java.util.logging.LogManager;
import androidx.multidex.MultiDex;
import androidx.multidex.MultiDexApplication;
public class MyApp extends MultiDexApplication {
private static final String TAG = MyApp.class.getSimpleName();
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
@Override
public void onCreate() {
super.onCreate();
// 初始化 OIMSDK
initOIMSDK();
}
private void initOIMSDK() {
UserBeanDaoManager.getInstance().init(this);
OIMSDK.init(this, true);
ZGLLogUtils.setLogEnabled(true);
OIMSDK.getInstance().setOnUnreadMsgCountChangedListener(new OIMCallback.OnUnreadMsgCountChangedListener() {
@Override
public void onCountChanged(int count) {
ZGLLogUtils.e(TAG, "onCountChanged " + count);
EventBusUtil.sendEvent(new EventBusCenter(Constants.EventCode.Code_Count_Changed, count));
}
});
OIMSDK.getInstance().setUserInfoProvider(new OIMCallback.OnUserInfoProvider() {
@Override
public OIMUserInfo getUserInfo(String s) {
// 当前登录用户
UserBean destUserBean;
if (s.equals(LoginManager.getUserId(getApplicationContext()))) {
destUserBean = LoginManager.getUser(getApplicationContext());
} else {
destUserBean = UserBeanDaoManager.getInstance().queryStudentByUserId(s);
}
if (destUserBean == null) {
return null;
}
OIMUserInfo userInfo = new OIMUserInfo();
userInfo.setUser_id(destUserBean.getUser_id());
userInfo.setName(destUserBean.getName());
userInfo.setAvatar(destUserBean.getAvatar());
return userInfo;
}
});
}
}
package com.offcn.imclient.adapter;
import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.jyall.base.adapter.BaseRecyclerViewAdapter;
import com.jyall.base.adapter.RecyclerViewHolderUtil;
import com.jyall.base.util.ValidateUtils;
import com.offcn.imclient.R;
import com.offcn.imclient.bean.UserBean;
import com.offcn.live.im.bean.OIMUserInfo;
import com.offcn.live.imkit.view.CircleImageView;
import java.util.List;
/**
* 最近会话列表适配器
*
* @author wangwenlong
* @date 2020/9/11
*/
public class ContactListAdapter extends BaseRecyclerViewAdapter<UserBean> {
public ContactListAdapter(Context paramContext) {
super(paramContext);
}
public ContactListAdapter(Context context, List<UserBean> list) {
super(context, list);
}
@Override
public int onCreateViewLayoutID(int i) {
return R.layout.item_contact_list;
}
@Override
public void bindItemViewHolder(RecyclerViewHolderUtil holderUtil, int position) {
CircleImageView mHeadImg = holderUtil.get(R.id.rc_img);
TextView mTvName = holderUtil.get(R.id.tv_name);
View line = holderUtil.get(R.id.view_line);
UserBean friend = getItem(position);
if (friend == null) {
return;
}
// String sectionForPosition = getSectionForPosition(position);
// if (position == getPositionForSection(sectionForPosition)) {
// mTvCategory.setVisibility(View.VISIBLE);
// mTvCategory.setText(friend.getFirst_char());
// } else {
// mTvCategory.setVisibility(View.GONE);
// mTvCategory.setText("");
// }
// if (friend.isLast()) {
// line.setVisibility(View.GONE);
// } else {
// line.setVisibility(View.VISIBLE);
// }
RequestOptions options = new RequestOptions();
options.placeholder(R.mipmap.ic_teacher).error(R.mipmap.ic_teacher);
options.diskCacheStrategy(DiskCacheStrategy.ALL);
mTvName.setText(friend.getName());
if (friend.getAvatar().startsWith("file")) {
Uri uri = Uri.parse(friend.getAvatar());
Glide.with(mContext).load(uri).apply(options).into(mHeadImg);
} else {
Glide.with(mContext).load(friend.getAvatar()).apply(options).into(mHeadImg);
}
}
// public String getSectionForPosition(int position) {
// if (!ValidateUtils.isEmpty(mList)) {
// UserBean friend = getItem(position);
// if (friend != null) {
// String firstChar = friend.getFirst_char();
// if (!TextUtils.isEmpty(firstChar)) {
// return firstChar;
// } else {
// return "";
// }
//
// } else {
// return "";
// }
// } else {
// return "";
// }
//
// }
//
// public int getPositionForSection(String section) {
// if (ValidateUtils.isEmpty(mList)) {
// return -1;
// }
// for (int i = 0; i < mList.size(); i++) {
// UserBean friend = getItem(i);
// if (friend != null) {
// String sortStr = friend.getFirst_char();
// if (!TextUtils.isEmpty(sortStr)) {
// if (sortStr.equals(section)) {
// return i;
// }
// }
// }
// }
// return -1;
// }
}
package com.offcn.imclient.adapter;
import android.content.Context;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.jyall.base.adapter.BaseRecyclerViewAdapter;
import com.jyall.base.adapter.RecyclerViewHolderUtil;
import com.offcn.imclient.R;
import com.offcn.imclient.bean.ServerContactBean;
import com.offcn.imclient.bean.UserBean;
import com.offcn.imclient.view.AnimatedExpandableListView;
import com.offcn.live.imkit.view.CircleImageView;
import java.util.ArrayList;
import java.util.List;
/**
* 最近会话列表适配器
*
* @author wangwenlong
* @date 2020/9/11
*/
public class ContactListExpandableAdapter extends AnimatedExpandableListView.AnimatedExpandableListAdapter {
private LayoutInflater inflater;
private List<ServerContactBean> items;
public ContactListExpandableAdapter(Context context,List<ServerContactBean> list) {
inflater = LayoutInflater.from(context);
items = list;
}
public void setData(List<ServerContactBean> items) {
this.items = items;
notifyDataSetChanged();
}
@Override
public UserBean getChild(int groupPosition, int childPosition) {
return items.get(groupPosition).getList().get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getRealChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
ChildHolder holder;
UserBean item = getChild(groupPosition, childPosition);
if (convertView == null) {
holder = new ChildHolder();
convertView = inflater.inflate(R.layout.item_contact_child, parent, false);
holder.title = (TextView) convertView.findViewById(R.id.tv_name);
convertView.setTag(holder);
} else {
holder = (ChildHolder) convertView.getTag();
}
holder.title.setText(item.getName());
return convertView;
}
@Override
public int getRealChildrenCount(int groupPosition) {
return items.get(groupPosition).getList().size();
}
@Override
public ServerContactBean getGroup(int groupPosition) {
return items.get(groupPosition);
}
@Override
public int getGroupCount() {
return items.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
GroupHolder holder;
ServerContactBean item = getGroup(groupPosition);
if (convertView == null) {
holder = new GroupHolder();
convertView = inflater.inflate(R.layout.item_contact_group, parent, false);
holder.title = (TextView) convertView.findViewById(R.id.tv_name);
holder.count = (TextView) convertView.findViewById(R.id.tv_count);
convertView.setTag(holder);
} else {
holder = (GroupHolder) convertView.getTag();
}
holder.title.setText(item.getKey());
return convertView;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public boolean isChildSelectable(int arg0, int arg1) {
return true;
}
private static class ChildHolder {
TextView title;
ImageView avatar;
}
private static class GroupHolder {
TextView title;
TextView count;
}
}
package com.offcn.imclient.bean;
import java.io.Serializable;
import java.util.List;
public class ServerContactBean implements Serializable {
private String group_id;
private String key;
private List<UserBean> list;
public String getGroup_id() {
return group_id;
}
public void setGroup_id(String group_id) {
this.group_id = group_id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public List<UserBean> getList() {
return list;
}
public void setList(List<UserBean> list) {
this.list = list;
}
}
package com.offcn.imclient.bean;
import java.util.List;
public class ServerContactBeanWrapper {
public List<ServerContactBean> user_list;
}
package com.offcn.imclient.bean;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import java.io.Serializable;
import org.greenrobot.greendao.annotation.Generated;
@Entity
public class UserBean implements Serializable {
private static final long serialVersionUID = 2L;
@Id(autoincrement = true)
private Long id;
private String user_id;
private String name;
private String username;
private String avatar;
private String avatar_color;
private String type;
private String token;
private String remark;
private String group_id;
private String group_name;
public UserBean() {
}
public UserBean(String user_id, String name, String avatar) {
this.user_id = user_id;
this.name = name;
this.avatar = avatar;
}
@Generated(hash = 1773158533)
public UserBean(Long id, String user_id, String name, String username,
String avatar, String avatar_color, String type, String token,
String remark, String group_id, String group_name) {
this.id = id;
this.user_id = user_id;
this.name = name;
this.username = username;
this.avatar = avatar;
this.avatar_color = avatar_color;
this.type = type;
this.token = token;
this.remark = remark;
this.group_id = group_id;
this.group_name = group_name;
}
public String getGroup_id() {
return group_id;
}
public void setGroup_id(String group_id) {
this.group_id = group_id;
}
public String getGroup_name() {
return group_name;
}
public void setGroup_name(String group_name) {
this.group_name = group_name;
}
public String getUser_id() {
return this.user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAvatar() {
return this.avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getToken() {
return this.token;
}
public void setToken(String token) {
this.token = token;
}
public String getRemark() {
return this.remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getAvatar_color() {
return this.avatar_color;
}
public void setAvatar_color(String avatar_color) {
this.avatar_color = avatar_color;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
}
package com.offcn.imclient.greendao.gen;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.util.Log;
import org.greenrobot.greendao.AbstractDaoMaster;
import org.greenrobot.greendao.database.StandardDatabase;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseOpenHelper;
import org.greenrobot.greendao.identityscope.IdentityScopeType;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* Master of DAO (schema version 1): knows all DAOs.
*/
public class DaoMaster extends AbstractDaoMaster {
public static final int SCHEMA_VERSION = 1;
/** Creates underlying database table using DAOs. */
public static void createAllTables(Database db, boolean ifNotExists) {
UserBeanDao.createTable(db, ifNotExists);
}
/** Drops underlying database table using DAOs. */
public static void dropAllTables(Database db, boolean ifExists) {
UserBeanDao.dropTable(db, ifExists);
}
/**
* WARNING: Drops all table on Upgrade! Use only during development.
* Convenience method using a {@link DevOpenHelper}.
*/
public static DaoSession newDevSession(Context context, String name) {
Database db = new DevOpenHelper(context, name).getWritableDb();
DaoMaster daoMaster = new DaoMaster(db);
return daoMaster.newSession();
}
public DaoMaster(SQLiteDatabase db) {
this(new StandardDatabase(db));
}
public DaoMaster(Database db) {
super(db, SCHEMA_VERSION);
registerDaoClass(UserBeanDao.class);
}
public DaoSession newSession() {
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}
public DaoSession newSession(IdentityScopeType type) {
return new DaoSession(db, type, daoConfigMap);
}
/**
* Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -
*/
public static abstract class OpenHelper extends DatabaseOpenHelper {
public OpenHelper(Context context, String name) {
super(context, name, SCHEMA_VERSION);
}
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
}
@Override
public void onCreate(Database db) {
Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
createAllTables(db, false);
}
}
/** WARNING: Drops all table on Upgrade! Use only during development. */
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name) {
super(context, name);
}
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
dropAllTables(db, true);
onCreate(db);
}
}
}
package com.offcn.imclient.greendao.gen;
import java.util.Map;
import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.AbstractDaoSession;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.identityscope.IdentityScopeType;
import org.greenrobot.greendao.internal.DaoConfig;
import com.offcn.imclient.bean.UserBean;
import com.offcn.imclient.greendao.gen.UserBeanDao;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* {@inheritDoc}
*
* @see org.greenrobot.greendao.AbstractDaoSession
*/
public class DaoSession extends AbstractDaoSession {
private final DaoConfig userBeanDaoConfig;
private final UserBeanDao userBeanDao;
public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
daoConfigMap) {
super(db);
userBeanDaoConfig = daoConfigMap.get(UserBeanDao.class).clone();
userBeanDaoConfig.initIdentityScope(type);
userBeanDao = new UserBeanDao(userBeanDaoConfig, this);
registerDao(UserBean.class, userBeanDao);
}
public void clear() {
userBeanDaoConfig.clearIdentityScope();
}
public UserBeanDao getUserBeanDao() {
return userBeanDao;
}
}
package com.offcn.imclient.greendao.gen;
import android.database.Cursor;
import android.database.sqlite.SQLiteStatement;
import org.greenrobot.greendao.AbstractDao;
import org.greenrobot.greendao.Property;
import org.greenrobot.greendao.internal.DaoConfig;
import org.greenrobot.greendao.database.Database;
import org.greenrobot.greendao.database.DatabaseStatement;
import com.offcn.imclient.bean.UserBean;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* DAO for table "USER_BEAN".
*/
public class UserBeanDao extends AbstractDao<UserBean, Long> {
public static final String TABLENAME = "USER_BEAN";
/**
* Properties of entity UserBean.<br/>
* Can be used for QueryBuilder and for referencing column names.
*/
public static class Properties {
public final static Property Id = new Property(0, Long.class, "id", true, "_id");
public final static Property User_id = new Property(1, String.class, "user_id", false, "USER_ID");
public final static Property Name = new Property(2, String.class, "name", false, "NAME");
public final static Property Username = new Property(3, String.class, "username", false, "USERNAME");
public final static Property Avatar = new Property(4, String.class, "avatar", false, "AVATAR");
public final static Property Avatar_color = new Property(5, String.class, "avatar_color", false, "AVATAR_COLOR");
public final static Property Type = new Property(6, String.class, "type", false, "TYPE");
public final static Property Token = new Property(7, String.class, "token", false, "TOKEN");
public final static Property Remark = new Property(8, String.class, "remark", false, "REMARK");
public final static Property Group_id = new Property(9, String.class, "group_id", false, "GROUP_ID");
public final static Property Group_name = new Property(10, String.class, "group_name", false, "GROUP_NAME");
}
public UserBeanDao(DaoConfig config) {
super(config);
}
public UserBeanDao(DaoConfig config, DaoSession daoSession) {
super(config, daoSession);
}
/** Creates the underlying database table. */
public static void createTable(Database db, boolean ifNotExists) {
String constraint = ifNotExists? "IF NOT EXISTS ": "";
db.execSQL("CREATE TABLE " + constraint + "\"USER_BEAN\" (" + //
"\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
"\"USER_ID\" TEXT," + // 1: user_id
"\"NAME\" TEXT," + // 2: name
"\"USERNAME\" TEXT," + // 3: username
"\"AVATAR\" TEXT," + // 4: avatar
"\"AVATAR_COLOR\" TEXT," + // 5: avatar_color
"\"TYPE\" TEXT," + // 6: type
"\"TOKEN\" TEXT," + // 7: token
"\"REMARK\" TEXT," + // 8: remark
"\"GROUP_ID\" TEXT," + // 9: group_id
"\"GROUP_NAME\" TEXT);"); // 10: group_name
}
/** Drops the underlying database table. */
public static void dropTable(Database db, boolean ifExists) {
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"USER_BEAN\"";
db.execSQL(sql);
}
@Override
protected final void bindValues(DatabaseStatement stmt, UserBean entity) {
stmt.clearBindings();
Long id = entity.getId();
if (id != null) {
stmt.bindLong(1, id);
}
String user_id = entity.getUser_id();
if (user_id != null) {
stmt.bindString(2, user_id);
}
String name = entity.getName();
if (name != null) {
stmt.bindString(3, name);
}
String username = entity.getUsername();
if (username != null) {
stmt.bindString(4, username);
}
String avatar = entity.getAvatar();
if (avatar != null) {
stmt.bindString(5, avatar);
}
String avatar_color = entity.getAvatar_color();
if (avatar_color != null) {
stmt.bindString(6, avatar_color);
}
String type = entity.getType();
if (type != null) {
stmt.bindString(7, type);
}
String token = entity.getToken();
if (token != null) {
stmt.bindString(8, token);
}
String remark = entity.getRemark();
if (remark != null) {
stmt.bindString(9, remark);
}
String group_id = entity.getGroup_id();
if (group_id != null) {
stmt.bindString(10, group_id);
}
String group_name = entity.getGroup_name();
if (group_name != null) {
stmt.bindString(11, group_name);
}
}
@Override
protected final void bindValues(SQLiteStatement stmt, UserBean entity) {
stmt.clearBindings();
Long id = entity.getId();
if (id != null) {
stmt.bindLong(1, id);
}
String user_id = entity.getUser_id();
if (user_id != null) {
stmt.bindString(2, user_id);
}
String name = entity.getName();
if (name != null) {
stmt.bindString(3, name);
}
String username = entity.getUsername();
if (username != null) {
stmt.bindString(4, username);
}
String avatar = entity.getAvatar();
if (avatar != null) {
stmt.bindString(5, avatar);
}
String avatar_color = entity.getAvatar_color();
if (avatar_color != null) {
stmt.bindString(6, avatar_color);
}
String type = entity.getType();
if (type != null) {
stmt.bindString(7, type);
}
String token = entity.getToken();
if (token != null) {
stmt.bindString(8, token);
}
String remark = entity.getRemark();
if (remark != null) {
stmt.bindString(9, remark);
}
String group_id = entity.getGroup_id();
if (group_id != null) {
stmt.bindString(10, group_id);
}
String group_name = entity.getGroup_name();
if (group_name != null) {
stmt.bindString(11, group_name);
}
}
@Override
public Long readKey(Cursor cursor, int offset) {
return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
}
@Override
public UserBean readEntity(Cursor cursor, int offset) {
UserBean entity = new UserBean( //
cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // user_id
cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // name
cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // username
cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // avatar
cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5), // avatar_color
cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6), // type
cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7), // token
cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8), // remark
cursor.isNull(offset + 9) ? null : cursor.getString(offset + 9), // group_id
cursor.isNull(offset + 10) ? null : cursor.getString(offset + 10) // group_name
);
return entity;
}
@Override
public void readEntity(Cursor cursor, UserBean entity, int offset) {
entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
entity.setUser_id(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
entity.setName(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
entity.setUsername(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
entity.setAvatar(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
entity.setAvatar_color(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5));
entity.setType(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6));
entity.setToken(cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7));
entity.setRemark(cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8));
entity.setGroup_id(cursor.isNull(offset + 9) ? null : cursor.getString(offset + 9));
entity.setGroup_name(cursor.isNull(offset + 10) ? null : cursor.getString(offset + 10));
}
@Override
protected final Long updateKeyAfterInsert(UserBean entity, long rowId) {
entity.setId(rowId);
return rowId;
}
@Override
public Long getKey(UserBean entity) {
if(entity != null) {
return entity.getId();
} else {
return null;
}
}
@Override
public boolean hasKey(UserBean entity) {
return entity.getId() != null;
}
@Override
protected final boolean isEntityUpdateable() {
return true;
}
}
package com.offcn.imclient.ui;
import android.net.Uri;
import android.text.TextUtils;
import com.jyall.base.base.BaseActivity;
import com.jyall.titleview.TitleView;
import com.jyall.titleview.TitleViewCompatible;
import com.offcn.imclient.R;
import com.offcn.live.imkit.ui.ChatFragment;
/**
* 聊天页面示例
*
* @author wangwenlong
* @date 2020/12/7
*/
public class ChatActivity extends BaseActivity {
private static final String TAG = ChatActivity.class.getSimpleName();
TitleView mTitleView;
ChatFragment mChatFragment;
@Override
protected int getContentViewLayoutId() {
return R.layout.activity_chat;
}
@Override
protected void initViewsAndEvents() {
Uri intentUri = getIntent().getData();
if (intentUri == null) {
finish();
return;
}
String title = intentUri.getQueryParameter("title");
String targetId = intentUri.getQueryParameter("targetId");
long lastSeq = Long.parseLong(intentUri.getQueryParameter("lastSeq"));
mTitleView = findViewById(R.id.title_view);
mTitleView.setTitleText(TextUtils.isEmpty(title) ? "会话详情" : title);
mChatFragment = (ChatFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_chat);
mChatFragment.setUri(intentUri);
}
@Override
protected void loadData() {
}
@Override
public void onBackPressed() {
if (mChatFragment != null && mChatFragment.hookOnBackPressed()) {
return;
}
super.onBackPressed();
}
}
package com.offcn.imclient.ui;
import android.content.Intent;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.RelativeLayout;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.jyall.base.base.BaseFragment;
import com.jyall.base.util.CommonUtils;
import com.jyall.base.util.ValidateUtils;
import com.offcn.imclient.R;
import com.offcn.imclient.adapter.ContactListExpandableAdapter;
import com.offcn.imclient.bean.ServerContactBean;
import com.offcn.imclient.bean.ServerContactBeanWrapper;
import com.offcn.imclient.bean.UserBean;
import com.offcn.imclient.util.LoginManager;
import com.offcn.imclient.util.UserBeanDaoManager;
import com.offcn.imclient.util.Utils;
import com.offcn.imclient.view.AnimatedExpandableListView;
import com.offcn.live.im.OIMSDK;
import com.offcn.live.im.util.ZGLLogUtils;
import com.offcn.live.im.util.ZGLParseUtils;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
/**
* 通讯录页
*
* @author wangwenlong
* @date 2020/12/9
*/
public class ContactListFragment extends BaseFragment {
private static final String TAG = ContactListFragment.class.getSimpleName();
private RelativeLayout mContainerContact;
private AnimatedExpandableListView mRecyclerView;
private List<ServerContactBean> friends = new ArrayList<>();
private ContactListExpandableAdapter mAdapter;
@Override
protected int getContentViewId() {
return R.layout.fragment_contact_list;
}
@Override
protected void init(View view) {
mContainerContact = view.findViewById(R.id.container_list);
mRecyclerView = view.findViewById(R.id.recycler_view);
mAdapter = new ContactListExpandableAdapter(getContext(), friends);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
UserBean userBean = friends.get(groupPosition).getList().get(childPosition);
if (userBean != null) {
OIMSDK.getInstance().startChat(getActivity(), userBean.getUser_id(), userBean.getName(), 0);
}
return true;
}
});
mRecyclerView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if (mRecyclerView.isGroupExpanded(groupPosition)) {
mRecyclerView.collapseGroupWithAnimation(groupPosition);
} else {
mRecyclerView.expandGroupWithAnimation(groupPosition);
}
return true;
}
});
getContactList();
}
@Override
protected boolean setLoadAlways() {
return false;
}
@Override
protected View isNeedEmpty() {
return mContainerContact;
}
@Override
protected void initEmptyResource() {
setEmptyRes("暂无联系人", R.mipmap.ic_empty_contact);
setErrorRes("联系人获取失败", 0);
setErrorClickListner(new View.OnClickListener() {
@Override
public void onClick(View v) {
getContactList();
}
});
}
private void getContactList() {
if (!CommonUtils.isNetConnected(getActivity())) {
showNoNetView();
return;
}
showLoading();
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("im_token", LoginManager.getToken(getActivity()));
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, "http://api.study.t.eoffcn.com/web/v2/im/userlist", jsonObject,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
ZGLLogUtils.e(TAG, "contact success " + response.toString());
dismissLoading();
try {
int rtnCode = response.getInt("code");
if (rtnCode == 0) {
ServerContactBeanWrapper beanWrapper = ZGLParseUtils.parseObjectByGson(response.getJSONObject("data").toString(), ServerContactBeanWrapper.class);
if (beanWrapper != null && !ValidateUtils.isEmpty(beanWrapper.user_list)) {
friends = beanWrapper.user_list;
exeContactList();
} else {
// 数据为空
friends.clear();
showEmptyView();
}
} else if (rtnCode == 1) {
// {"code":1,"msg":"登陆过期,请重新登陆","params":{"im_token":"0XR5YOS6dg7x2lirfeX3CbjRLqPWmesaFbdsr\/M4IRZS4mYYyZILI82FT8dgqybCA4W+MxfjJDY=@ip6c.cn.rongnav.com;ip6c.cn.rongcfg.com"}}
// TODO: 2020/12/11
Utils.logout(getActivity());
startActivity(new Intent(getActivity(), LoginActivity.class));
getActivity().finish();
CommonUtils.showToast(getActivity(), response.getString("msg"));
} else {
showErrorView();
CommonUtils.showToast(getActivity(), response.getString("msg"));
}
} catch (Exception e) {
showErrorView();
CommonUtils.showToast(getActivity(), "联系人获取失败");
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
ZGLLogUtils.e(TAG, "contact error " + error.toString());
dismissLoading();
CommonUtils.showToast(getActivity(), error.toString());
}
}
);
requestQueue.add(jsonObjectRequest);
} catch (Exception e) {
dismissLoading();
}
}
private void exeContactList() {
if (!ValidateUtils.isEmpty(friends)) {
showNormalContent();
mAdapter.setData(friends);
List<UserBean> userBeanList = new ArrayList<>();
for (ServerContactBean contactBean : friends) {
userBeanList.addAll(contactBean.getList());
}
UserBeanDaoManager.getInstance().insertMulti(userBeanList);
} else {
showEmptyView();
UserBeanDaoManager.getInstance().deleteAll();
}
}
}
package com.offcn.imclient.ui;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.jyall.base.base.BaseActivity;
import com.jyall.base.util.CommonUtils;
import com.offcn.imclient.R;
import com.offcn.imclient.bean.UserBean;
import com.offcn.imclient.util.LoginManager;
import com.offcn.live.im.util.ZGLLogUtils;
import com.offcn.live.im.util.ZGLParseUtils;
import org.json.JSONObject;
/**
* 登录页
*
* @author wangwenlong
* @date 2020/12/10
*/
public class LoginActivity extends BaseActivity {
private static final String TAG = LoginActivity.class.getSimpleName();
EditText mEtName, mEtPwd;
TextView mTvLogin;
@Override
protected int getContentViewLayoutId() {
return R.layout.activity_login;
}
@Override
protected void initViewsAndEvents() {
mEtName = findViewById(R.id.et_name);
mEtPwd = findViewById(R.id.et_pwd);
mTvLogin = findViewById(R.id.tv_login);
mTvLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
login();
}
});
}
@Override
protected void loadData() {
}
private void login() {
String name = mEtName.getText().toString().trim();
String pwd = mEtPwd.getText().toString().trim();
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("username", "lqy62094");
jsonObject.put("password", "lqy62094");
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, "http://api.study.t.eoffcn.com/web/v2/im/login", jsonObject,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.e(TAG, "login success " + response.toString());
try {
if (response.getInt("code") == 0) {
if (response.getJSONObject("data") == null || response.getJSONObject("data").getJSONObject("user_info") == null) {
CommonUtils.showToast(LoginActivity.this, "用户信息获取失败");
return;
}
UserBean userBean = ZGLParseUtils.parseObjectByGson(response.getJSONObject("data").getJSONObject("user_info").toString(), UserBean.class);
if (userBean != null) {
ZGLLogUtils.e(TAG, userBean.toString());
LoginManager.login(LoginActivity.this, userBean);
startActivity(new Intent(LoginActivity.this, MainActivity.class));
} else {
CommonUtils.showToast(LoginActivity.this, "用户信息获取失败");
}
} else {
CommonUtils.showToast(LoginActivity.this, response.getString("msg"));
}
} catch (Exception e) {
CommonUtils.showToast(LoginActivity.this, "用户信息解析失败");
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "login error " + error.toString());
CommonUtils.showToast(LoginActivity.this, error.toString());
}
}
);
requestQueue.add(jsonObjectRequest);
} catch (Exception e) {
}
}
}
package com.offcn.imclient.ui;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Handler;
import com.google.android.material.tabs.TabLayout;
import com.jyall.base.adapter.BaseVPAdapter;
import com.jyall.base.base.BaseActivity;
import com.jyall.base.util.CommonUtils;
import com.offcn.imclient.R;
import com.offcn.imclient.bean.UserBean;
import com.offcn.imclient.util.LoginManager;
import com.offcn.imclient.util.UserBeanDaoManager;
import com.offcn.live.im.OIMCallback;
import com.offcn.live.im.OIMSDK;
import com.offcn.live.im.bean.OIMCode;
import com.offcn.live.im.util.ZGLCommonUtils;
import com.offcn.live.im.util.ZGLLogUtils;
import com.offcn.live.imkit.ui.ChatListFragment;
import java.util.ArrayList;
import java.util.List;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
/**
* tab主页。由最近会话和好友列表组成
*/
public class MainActivity extends BaseActivity {
private static final String TAG = MainActivity.class.getSimpleName();
TabLayout mTabLayout;
ViewPager mViewPager;
String[] titles = new String[]{"聊天", "通讯录", "我的"};
private UserBean mUserBean;
@Override
protected int getContentViewLayoutId() {
return R.layout.activity_main;
}
@Override
protected void initViewsAndEvents() {
mTabLayout = findViewById(R.id.tab_layout);
mViewPager = findViewById(R.id.view_pager);
mUserBean = LoginManager.getUser(this);
if (mUserBean == null) {
CommonUtils.showToast(this, "用户信息获取失败");
finish();
return;
}
OIMSDK.getInstance().connect(mUserBean.getUser_id(), mUserBean.getToken(), new OIMCallback.OnConnectListener() {
@Override
public void onStateConnected() {
ZGLLogUtils.e(TAG, "IM连接成功");
ZGLCommonUtils.showToast(MainActivity.this, "IM连接成功");
}
@Override
public void onStateDisconnected(int code, String error) {
ZGLLogUtils.e(TAG, "IM连接失败 " + code + " " + error);
ZGLCommonUtils.showToast(MainActivity.this, "IM连接失败 " + code + " " + error);
// 连接失败超时,和部分情况作特殊处理如退出页面:token失效、被踢
if (code == OIMCode.Code_IM_Connect_Fail
|| code == OIMCode.Code_IM_Connect_Timeout
|| code == OIMCode.Code_IM_Error_TokenInvalid
|| code == OIMCode.Code_IM_Disconnect_Kick
|| code == OIMCode.Code_IM_Error_NoExist) {
// 此处注释。内部已调用 destroy() 方法。
// OIMSDK.getInstance(DemoMainActivity.this).destroy();
// 注销登录信息
LoginManager.logout(MainActivity.this);
UserBeanDaoManager.getInstance().deleteAll();
AlertDialog dialog = new AlertDialog.Builder(MainActivity.this)
.setTitle("IM连接失败")
.setMessage(code + "," + error)
.setPositiveButton("退出", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(MainActivity.this, LoginActivity.class));
finish();
}
})
.setCancelable(false)
.create();
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
}
@Override
public void onStateReconnecting() {
ZGLLogUtils.e(TAG, "IM重连");
}
});
List<Fragment> fragmentList = new ArrayList<>();
fragmentList.add(new ChatListFragment());
fragmentList.add(new ContactListFragment());
fragmentList.add(new MeFragment());
for (int i = 0; i < titles.length; i++) {
mTabLayout.addTab(mTabLayout.newTab());
}
BaseVPAdapter adapter = new BaseVPAdapter(getSupportFragmentManager(), fragmentList);
mViewPager.setOffscreenPageLimit(fragmentList.size());
mViewPager.setAdapter(adapter);
mTabLayout.setupWithViewPager(mViewPager, false);
for (int i = 0; i < titles.length; i++) {
mTabLayout.getTabAt(i).setText(titles[i]);
}
}
@Override
protected void loadData() {
}
@Override
protected void onResume() {
super.onResume();
// 清除通知栏消息
OIMSDK.getInstance().clearNotification();
}
}
package com.offcn.imclient.ui;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.offcn.imclient.R;
import com.offcn.imclient.util.LoginManager;
import com.offcn.imclient.util.Utils;
import com.offcn.live.imkit.view.CircleImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
/**
* 我
*/
public class MeFragment extends Fragment implements View.OnClickListener {
TextView mTvLogout;
TextView mTvName;
CircleImageView mImageView;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_me, null);
mTvLogout = view.findViewById(R.id.btn_logout);
mTvName = view.findViewById(R.id.name);
mImageView = view.findViewById(R.id.avatar);
mTvName.setText(LoginManager.getUserName(getActivity()));
mTvLogout.setOnClickListener(this);
Glide.with(getActivity()).load(LoginManager.getUserAvatar(getActivity()))
.placeholder(R.mipmap.ic_teacher).into(mImageView);
return view;
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_logout:
Utils.logout(getActivity());
startActivity(new Intent(getActivity(), LoginActivity.class));
getActivity().finish();
break;
}
}
}
package com.offcn.imclient.ui;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import com.offcn.live.im.bean.OIMMsg;
import com.offcn.live.im.bean.OIMMsgBody;
import com.offcn.live.im.util.ZGLLogUtils;
import com.offcn.live.im.util.ZGLParseUtils;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
/**
* 华为推送,通知栏点击处理类
*/
public class PushTranslateActivity extends AppCompatActivity {
private static final String TAG = PushTranslateActivity.class.getSimpleName();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String content = null;
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
content = bundle.getString("content");
}
if (!TextUtils.isEmpty(content)) {
// 跳转到页面需要保证 OIMSDK 连接成功,所以建议先跳转到应用首页进行全局初始化操作,若跳转到聊天页需要先连接 OIMSDK 初始化
ZGLLogUtils.e(TAG, "push : " + content);
OIMMsg oimMsg = ZGLParseUtils.parseObjectByGson(content, OIMMsg.class);
if(oimMsg != null) {
OIMMsgBody msgBody = oimMsg.getBody();
if (msgBody != null) {
// DemoChatActivity.newInstance(this, msgBody.getMsg_to(), msgBody.getMsg_from(), msgBody.getMsg_seq());
startActivity(new Intent(this, SplashActivity.class));
}
}
}
finish();
overridePendingTransition(0, 0);
}
}
package com.offcn.imclient.ui;
import android.content.Intent;
import android.os.Handler;
import com.jyall.base.base.BaseActivity;
import com.offcn.imclient.R;
import com.offcn.imclient.util.LoginManager;
/**
* 闪屏页
*
* @author wangwenlong
* @date 2020/12/10
*/
public class SplashActivity extends BaseActivity {
private static final String TAG = SplashActivity.class.getSimpleName();
@Override
protected int getContentViewLayoutId() {
return R.layout.activity_splash;
}
@Override
protected void initViewsAndEvents() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
exeLogin();
}
}, 1000 * 2);
}
@Override
protected void loadData() {
}
private void exeLogin() {
if (LoginManager.isLogin(this)) {
startActivity(new Intent(this, MainActivity.class));
} else {
startActivity(new Intent(this, LoginActivity.class));
}
finish();
}
}
package com.offcn.imclient.util;
public class Constants {
public static class EventCode{
public static final int Code_Count_Changed = 1;
}
}
package com.offcn.imclient.util;
import android.content.Context;
import com.offcn.imclient.greendao.gen.DaoMaster;
import com.offcn.imclient.greendao.gen.DaoSession;
import com.offcn.live.im.util.ZGLDaoManager;
import com.offcn.live.im.util.ZGLGreenDaoUpgradeHelper;
import org.greenrobot.greendao.query.QueryBuilder;
public class DaoManager {
private static final String DB_NAME = "im-client.db";//数据库名称
private volatile static DaoManager mDaoManager;//多线程访问
private static DaoUpgradeHelper mHelper;
private static DaoMaster mDaoMaster;
private static DaoSession mDaoSession;
private Context context;
public Context getContext() {
return context;
}
private DaoManager(){
}
/**
* 使用单例模式获得操作数据库的对象
*/
public static DaoManager getInstance() {
if (mDaoManager == null) {
synchronized (ZGLDaoManager.class) {
if (mDaoManager == null) {
mDaoManager = new DaoManager();
}
}
}
return mDaoManager;
}
/**
* 初始化Context对象
*/
public void init(Context context) {
this.context = context;
}
/**
* 判断数据库是否存在,如果不存在则创建
*/
public DaoMaster getDaoMaster() {
if (null == mDaoMaster) {
mHelper = new DaoUpgradeHelper(context, DB_NAME, null);
mDaoMaster = new DaoMaster(mHelper.getWritableDatabase());
}
return mDaoMaster;
}
/**
* 完成对数据库的增删查找
*/
public DaoSession getDaoSession() {
if (null == mDaoSession) {
if (null == mDaoMaster) {
mDaoMaster = getDaoMaster();
}
mDaoSession = mDaoMaster.newSession();
}
return mDaoSession;
}
/**
* 设置debug模式开启或关闭,默认关闭
*/
public void setDebug(boolean flag) {
QueryBuilder.LOG_SQL = flag;
QueryBuilder.LOG_VALUES = flag;
}
/**
* 关闭数据库
*/
public void closeDataBase() {
closeHelper();
closeDaoSession();
}
public void closeDaoSession() {
if (null != mDaoSession) {
mDaoSession.clear();
mDaoSession = null;
}
}
public void closeHelper() {
if (mHelper != null) {
mHelper.close();
mHelper = null;
}
}
}
package com.offcn.imclient.util;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import com.offcn.imclient.greendao.gen.UserBeanDao;
import com.offcn.live.im.greendao.gen.DaoMaster;
import com.offcn.live.im.greendao.gen.MsgTableDao;
import com.offcn.live.im.greendao.gen.OIMMsgContentDao;
import com.offcn.live.im.greendao.gen.OIMUserBeanDao;
import com.offcn.live.im.util.ZGLMigrationHelper;
public class DaoUpgradeHelper extends DaoMaster.DevOpenHelper {
public DaoUpgradeHelper(Context context, String name) {
super(context, name);
}
public DaoUpgradeHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
ZGLMigrationHelper.migrate(db, UserBeanDao.class);
}
}
package com.offcn.imclient.util;
import android.content.Context;
import android.text.TextUtils;
import com.jyall.base.util.SharedPrefUtils;
import com.offcn.imclient.bean.UserBean;
import com.offcn.live.im.util.ZGLParseUtils;
/**
* 登录工具类
*/
public class LoginManager {
private static final String KEY_USER = "login_user";
public static boolean isLogin(Context context) {
return getUser(context) != null;
}
public static void login(Context context, UserBean userBean) {
SharedPrefUtils.setParam(context, KEY_USER, ZGLParseUtils.parseToJson(userBean));
}
public static String getUserId(Context context) {
if(getUser(context) == null){
return null;
}
return getUser(context).getUser_id();
}
public static String getUserName(Context context) {
if(getUser(context) == null){
return null;
}
return getUser(context).getName();
}
public static String getUserAvatar(Context context) {
if(getUser(context) == null){
return null;
}
return getUser(context).getAvatar();
}
public static String getToken(Context context) {
if(getUser(context) == null){
return null;
}
return getUser(context).getToken();
}
public static UserBean getUser(Context context) {
String userJson = String.valueOf(SharedPrefUtils.getParam(context, KEY_USER, ""));
if(TextUtils.isEmpty(userJson)){
return null;
}
return ZGLParseUtils.parseObjectByGson(userJson, UserBean.class);
}
public static void logout(Context context) {
SharedPrefUtils.clear(context);
}
}
package com.offcn.imclient.util;
import android.content.Context;
import com.jyall.base.util.SharedPrefUtils;
import com.jyall.base.util.ValidateUtils;
import com.offcn.imclient.bean.UserBean;
import com.offcn.imclient.greendao.gen.DaoSession;
import com.offcn.imclient.greendao.gen.UserBeanDao;
import com.offcn.live.im.util.ZGLParseUtils;
import org.greenrobot.greendao.query.QueryBuilder;
import java.util.List;
public class UserBeanDaoManager {
private static final boolean DUBUG = true;
private DaoManager manager;
private UserBeanDao studentDao;
private DaoSession daoSession;
private Context mContext;
private UserBeanDaoManager() {
}
private static UserBeanDaoManager INSTANCE = new UserBeanDaoManager();
public static UserBeanDaoManager getInstance() {
return INSTANCE;
}
public void init(Context context) {
mContext = context;
manager = DaoManager.getInstance();
manager.init(context);
daoSession = manager.getDaoSession();
manager.setDebug(DUBUG);
UserBeanDao.createTable(daoSession.getDatabase(), true);
}
/**
* 添加数据,如果有重复则覆盖
*/
public void insert(UserBean student) {
manager.getDaoSession().insertOrReplace(student);
}
/**
* 添加多条数据,需要开辟新的线程
*/
public void insertMulti(final List<UserBean> students) {
manager.getDaoSession().runInTx(new Runnable() {
@Override
public void run() {
for (UserBean student : students) {
manager.getDaoSession().insertOrReplace(student);
}
}
});
}
/**
* 删除数据
*/
public void deleteStudent(UserBean student) {
manager.getDaoSession().delete(student);
}
/**
* 删除全部数据
*/
public void deleteAll() {
manager.getDaoSession().deleteAll(UserBean.class);
}
/**
* 更新数据
*/
public void updateStudent(UserBean student) {
manager.getDaoSession().update(student);
}
/**
* 按照主键返回单条数据
*/
public UserBean listOneStudent(long key) {
return manager.getDaoSession().load(UserBean.class, key);
}
/**
* 根据指定条件查询数据
*/
public List<UserBean> queryStudent() {
//查询构建器
QueryBuilder<UserBean> builder = manager.getDaoSession().queryBuilder(UserBean.class);
List<UserBean> list = builder.where(UserBeanDao.Properties.User_id.ge(1)).where(UserBeanDao.Properties.Name.like("王小二")).list();
return list;
}
/**
* 根据指定条件查询数据
*/
public UserBean queryStudentByUserId(String userId) {
//查询构建器
try {
QueryBuilder<UserBean> builder = manager.getDaoSession().queryBuilder(UserBean.class);
UserBean userBean = builder.where(UserBeanDao.Properties.User_id.eq(userId)).limit(1).unique();
return userBean;
}catch (Exception e){
return null;
}
}
/**
* 查询全部数据
*/
public List<UserBean> queryAll() {
return manager.getDaoSession().loadAll(UserBean.class);
}
}
package com.offcn.imclient.util;
import android.content.Context;
import com.offcn.imclient.bean.UserBean;
import com.offcn.live.im.OIMSDK;
public class Utils {
public static void logout(Context context){
OIMSDK.getInstance().destroy();
LoginManager.logout(context);
UserBeanDaoManager.getInstance().deleteAll();
}
}
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true"
tools:ignore="MissingDefaultResource">
<com.jyall.titleview.TitleView
android:id="@+id/title_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<fragment
android:id="@+id/fragment_chat"
android:name="com.offcn.live.imkit.ui.ChatFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_margin="30dp"
android:focusableInTouchMode="true"
android:focusable="true"
android:layout_height="match_parent">
<com.jyall.base.view.ClearEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et_name"
android:singleLine="true"
android:hint="请输入用户名"/>
<com.jyall.base.view.ClearEditText
android:layout_width="match_parent"
android:layout_marginTop="20dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:id="@+id/et_pwd"
android:hint="请输入密码"/>
<TextView
android:layout_width="match_parent"
android:layout_marginTop="50dp"
android:text="登录"
android:textSize="16sp"
android:gravity="center"
android:textColor="@android:color/white"
android:layout_height="50dp"
android:id="@+id/tv_login"
android:background="@color/colorPrimary"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="50dp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:id="@+id/view_line"
android:layout_above="@+id/tab_layout"
android:background="@android:color/darker_gray"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_above="@+id/view_line"
android:layout_height="match_parent" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="闪屏页"/>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/container_list"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.offcn.imclient.view.AnimatedExpandableListView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.offcn.live.imkit.view.CircleImageView
android:id="@+id/avatar"
android:layout_marginTop="50dp"
android:layout_width="50dp"
android:layout_height="50dp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
tools:text="我是名字" />
<TextView
android:id="@+id/btn_logout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="20dp"
android:background="@android:color/darker_gray"
android:gravity="center"
android:padding="10dp"
android:text="退出登录"
android:textSize="16sp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:paddingLeft="50dp"
android:gravity="center_vertical">
<ImageView
android:id="@+id/iv_avatar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_teacher" />
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:paddingLeft="40dp"
android:gravity="center_vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp" />
<TextView
android:id="@+id/tv_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.offcn.live.imkit.view.CircleImageView
android:id="@+id/rc_img"
android:layout_width="38dp"
android:layout_height="38dp"
android:layout_alignParentStart="true"
android:layout_marginLeft="16dp"
android:layout_marginTop="9dp"
android:layout_marginBottom="9dp"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="13dp"
android:layout_marginRight="16dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:singleLine="true"
android:textColor="@color/color_333333"
android:textSize="15dp" />
</LinearLayout>
<View
android:id="@+id/view_line"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginStart="65dp"
android:background="@color/color_e5e5e5" />
</LinearLayout>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_top"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#e9ebec" />
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#e64444</color>
<color name="colorPrimaryDark">#e60012</color>
<color name="colorAccent">#03DAC5</color>
<color name="color_333333">#333333</color>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">中公云信教师版</string>
<string name="push_mi_appid">2882303761518588294</string>
<string name="push_mi_appkey">5761858881294</string>
<string name="push_vivo_appid">104300660</string>
<string name="push_vivo_appkey">5920cbae23f22a915ecabf26554b644e</string>
<string name="push_oppo_appkey">aa5d4f8306b04b7c820019b906e2ce92</string>
<string name="push_oppo_appsecret">365b1426c0a14519b3f96092f0a729a9</string>
</resources>
\ No newline at end of file
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="windowNoTitle">true</item>
</style>
<style name="MyTablayoutstyle" parent="Base.Widget.Design.TabLayout">
<item name="tabBackground">@android:color/white</item>
<item name="tabIndicatorHeight">0dp</item>
<item name="tabSelectedTextColor">@color/colorPrimary</item>
<item name="android:textSize">15sp</item>
<item name="android:textColor">@android:color/darker_gray</item>
</style>
</resources>
\ No newline at end of file
package com.offcn.imclient;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
maven {
url 'http://maven.base.eoffcn.com/repository/zglive/'
credentials {
username = "zglive"
password = "zglive"
}
}
maven {url 'https://developer.huawei.com/repo/'}
maven {
url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
}
mavenCentral()
maven {
url "https://jitpack.io"
}
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
classpath 'com.huawei.agconnect:agcp:1.3.1.300'
classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven {
url 'http://maven.base.eoffcn.com/repository/zglive/'
credentials {
username = "zglive"
password = "zglive"
}
}
maven {url 'https://developer.huawei.com/repo/'}
maven {
url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
}
mavenCentral()
maven {
url "https://jitpack.io"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
\ No newline at end of file
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
\ No newline at end of file
#Thu Dec 10 10:42:23 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
该项目为 IM 客户端
集成IMKIT
\ No newline at end of file
include ':app'
rootProject.name = "IMTeacher"
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment