master
李富 9 years ago
commit bcb1bd5dff

17
.gitattributes vendored

@ -0,0 +1,17 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

7
.gitignore vendored

@ -0,0 +1,7 @@
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures

@ -0,0 +1 @@
NewIM

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="myModules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" 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>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/NewIM.iml" filepath="$PROJECT_DIR$/NewIM.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>
</project>

@ -0,0 +1,12 @@
<?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>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="NewIM" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

1
app/.gitignore vendored

@ -0,0 +1 @@
/build

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="NewIM" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":app" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/cn.bmob.android/bmob-im/2.0.5/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/cn.bmob.android/bmob-sdk/3.4.7-aar/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.2.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/22.2.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.orhanobut/logger/1.4/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="butterknife-7.0.1" level="project" />
<orderEntry type="library" exported="" name="baidumapapi_v3_5_0" level="project" />
<orderEntry type="library" exported="" name="recyclerview-v7-22.2.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-22.2.0" level="project" />
<orderEntry type="library" exported="" name="support-v4-22.2.0" level="project" />
<orderEntry type="library" exported="" name="universal-image-loader-1.9.5" level="project" />
<orderEntry type="library" exported="" name="logger-1.4" level="project" />
<orderEntry type="library" exported="" name="eventbus-3.0.0" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-22.2.0" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="hamcrest-core-1.3" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="junit-4.12" level="project" />
<orderEntry type="library" exported="" name="bmob-sdk-3.4.7-aar" level="project" />
<orderEntry type="library" exported="" name="bmob-im-2.0.5" level="project" />
<orderEntry type="library" exported="" name="locSDK_6.23" level="project" />
</component>
</module>

@ -0,0 +1,61 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
aaptOptions.cruncherEnabled = false
aaptOptions.useNewCruncher = false
defaultConfig {
applicationId "cn.bmob.imdemo"
minSdkVersion 14
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// unaligned .apks
applicationVariants.all { variant ->
variant.assemble.doLast {
variant.outputs.each { output ->
File unaligned = output.packageApplication.outputFile;
File aligned = output.outputFile
if (!unaligned.getName().equalsIgnoreCase(aligned.getName())) {
println "deleting " + unaligned.getName()
unaligned.delete()
}
}
}
}
}
}
dexOptions{
incremental false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile('com.android.support:appcompat-v7:22.2.0') {
exclude module: 'support-annotations'
}
compile 'com.android.support:recyclerview-v7:22.2.0'
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.orhanobut:logger:1.4'
compile 'org.greenrobot:eventbus:3.0.0'
//bmob-im:2.0.5aarBmobNewIM_xxxx.jarandroidasync_2.1.6.jarbmob_im_notification_strings.xml
compile 'cn.bmob.android:bmob-im:2.0.5@aar'
//bmob-sdk:3.4.7
compile 'cn.bmob.android:bmob-sdk:3.4.7-aar'
compile files('libs/baidumapapi_v3_5_0.jar')
compile files('libs/locSDK_6.23.jar')
}

Binary file not shown.

Binary file not shown.

@ -0,0 +1,13 @@
package cn.bmob.imdemo;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.bmob.imdemo">
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- 监听网络的变化 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 设备休眠 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- sd卡存储 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 摄像头 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 录音 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 通知震动 -->
<uses-permission android:name="android.permission.VIBRATE" />
<!-- 百度地图的权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
android:name=".BmobIMApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".ui.SplashActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.LoginActivity" />
<activity android:name=".ui.MainActivity" />
<activity android:name=".ui.RegisterActivity" />
<activity android:name=".ui.SearchUserActivity" />
<activity android:name=".ui.UserInfoActivity"/>
<activity android:name=".ui.NewFriendActivity"/>
<activity
android:name=".ui.ChatActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
<!-- bmobim start -->
<receiver android:name="cn.bmob.newim.core.ConnectChangeReceiver">
<intent-filter>
<action android:name="cn.bmob.action.RECONNECT" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<service
android:name="cn.bmob.newim.core.service.BmobIMService"
android:process=":bmobcore" />
<service
android:name="cn.bmob.newim.core.service.NotifyService"
android:process=":bmobcore" />
<service android:name="cn.bmob.newim.core.service.ReConnectService" />
<service android:name="cn.bmob.newim.core.service.HeartBeatService" />
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote">
</service>
<!-- 设置bmob appkey -->
<meta-data
android:name="Bmob_APP_KEY"
android:value="44d76c5b8464f93f380b1083f049bb36" />
<!-- bmobim end -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="tqoNSeUugf6ZBvfKPAv7Rpc40IV3bA8K" />
</application>
</manifest>

@ -0,0 +1,65 @@
package cn.bmob.imdemo;
import android.app.Application;
import com.orhanobut.logger.Logger;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import cn.bmob.imdemo.base.UniversalImageLoader;
import cn.bmob.newim.BmobIM;
/**
* @author :smile
* @project:BmobIMApplication
* @date :2016-01-13-10:19
*/
public class BmobIMApplication extends Application{
private static BmobIMApplication INSTANCE;
public static BmobIMApplication INSTANCE(){
return INSTANCE;
}
private void setInstance(BmobIMApplication app) {
setBmobIMApplication(app);
}
private static void setBmobIMApplication(BmobIMApplication a) {
BmobIMApplication.INSTANCE = a;
}
@Override
public void onCreate() {
super.onCreate();
setInstance(this);
//初始化
Logger.init("smile");
//只有主进程运行的时候才需要初始化
if (getApplicationInfo().packageName.equals(getMyProcessName())){
//im初始化
BmobIM.init(this);
//注册消息接收器
BmobIM.registerDefaultMessageHandler(new DemoMessageHandler(this));
}
//uil初始化
UniversalImageLoader.initImageLoader(this);
}
/**
*
* @return
*/
public static String getMyProcessName() {
try {
File file = new File("/proc/" + android.os.Process.myPid() + "/" + "cmdline");
BufferedReader mBufferedReader = new BufferedReader(new FileReader(file));
String processName = mBufferedReader.readLine().trim();
mBufferedReader.close();
return processName;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

@ -0,0 +1,27 @@
package cn.bmob.imdemo;
/**
* @author :smile
* @project:Config
* @date :2016-01-15-18:23
*/
public class Config {
/**
* Bmobkey
*/
// public static final String DEFAULT_APPKEY="d6f44e8f1ba9d3dcf4fab7a487fa97dd";//内
public static final String DEFAULT_APPKEY="87ab0f9bee41bce86dfadd69af692873";//外
//是否是debug模式
public static final boolean DEBUG=true;
//好友请求:未读-未添加->接收到别人发给我的好友添加请求,初始状态
public static final int STATUS_VERIFY_NONE=0;
//好友请求:已读-未添加->点击查看了新朋友,则都变成已读状态
public static final int STATUS_VERIFY_READED=2;
//好友请求:已添加
public static final int STATUS_VERIFIED=1;
//好友请求:拒绝
public static final int STATUS_VERIFY_REFUSE=3;
//好友请求:我发出的好友请求-暂未存储到本地数据库中
public static final int STATUS_VERIFY_ME_SEND=4;
}

@ -0,0 +1,176 @@
package cn.bmob.imdemo;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.Toast;
import com.orhanobut.logger.Logger;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
import java.util.Map;
import cn.bmob.imdemo.bean.AddFriendMessage;
import cn.bmob.imdemo.bean.AgreeAddFriendMessage;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.db.NewFriend;
import cn.bmob.imdemo.db.NewFriendManager;
import cn.bmob.imdemo.event.RefreshEvent;
import cn.bmob.imdemo.model.UserModel;
import cn.bmob.imdemo.model.i.UpdateCacheListener;
import cn.bmob.imdemo.ui.MainActivity;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMMessageType;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.event.MessageEvent;
import cn.bmob.newim.event.OfflineMessageEvent;
import cn.bmob.newim.listener.BmobIMMessageHandler;
import cn.bmob.newim.notification.BmobNotificationManager;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;
/**
* @author smile
* @project DemoMessageHandler
* @date 2016-03-08-17:37
*/
public class DemoMessageHandler extends BmobIMMessageHandler{
private Context context;
public DemoMessageHandler(Context context) {
this.context = context;
}
@Override
public void onMessageReceive(final MessageEvent event) {
//当接收到服务器发来的消息时,此方法被调用
Logger.i(event.getConversation().getConversationTitle() + "," + event.getMessage().getMsgType() + "," + event.getMessage().getContent());
excuteMessage(event);
}
@Override
public void onOfflineReceive(final OfflineMessageEvent event) {
//每次调用connect方法时会查询一次离线消息如果有此方法会被调用
Map<String,List<MessageEvent>> map =event.getEventMap();
Logger.i("离线消息属于" + map.size() + "个用户");
//挨个检测下离线消息所属的用户的信息是否需要更新
for (Map.Entry<String, List<MessageEvent>> entry : map.entrySet()) {
List<MessageEvent> list =entry.getValue();
int size = list.size();
for(int i=0;i<size;i++){
excuteMessage(list.get(i));
}
}
}
/**
*
* @param event
*/
private void excuteMessage(final MessageEvent event){
//检测用户信息是否需要更新
UserModel.getInstance().updateUserInfo(event, new UpdateCacheListener() {
@Override
public void done(BmobException e) {
BmobIMMessage msg = event.getMessage();
if (BmobIMMessageType.getMessageTypeValue(msg.getMsgType()) == 0) {//用户自定义的消息类型其类型值均为0
processCustomMessage(msg, event.getFromUserInfo());
} else {//SDK内部内部支持的消息类型
if (BmobNotificationManager.getInstance(context).isShowNotification()) {//如果需要显示通知栏SDK提供以下两种显示方式
Intent pendingIntent = new Intent(context, MainActivity.class);
pendingIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
//1、多个用户的多条消息合并成一条通知有XX个联系人发来了XX条消息
BmobNotificationManager.getInstance(context).showNotification(event, pendingIntent);
//2、自定义通知消息始终只有一条通知新消息覆盖旧消息
// BmobIMUserInfo info =event.getFromUserInfo();
// //这里可以是应用图标也可以将聊天头像转成bitmap
// Bitmap largetIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
// BmobNotificationManager.getInstance(context).showNotification(largetIcon,
// info.getName(),msg.getContent(),"您有一条新消息",pendingIntent);
} else {//直接发送消息事件
Logger.i("当前处于应用内发送event");
EventBus.getDefault().post(event);
}
}
}
});
}
/**
*
* @param msg
*/
private void processCustomMessage(BmobIMMessage msg,BmobIMUserInfo info){
//自行处理自定义消息类型
Logger.i(msg.getMsgType() + "," + msg.getContent() + "," + msg.getExtra());
String type =msg.getMsgType();
//发送页面刷新的广播
EventBus.getDefault().post(new RefreshEvent());
//处理消息
if(type.equals("add")){//接收到的添加好友的请求
NewFriend friend = AddFriendMessage.convert(msg);
//本地好友请求表做下校验,本地没有的才允许显示通知栏--有可能离线消息会有些重复
long id = NewFriendManager.getInstance(context).insertOrUpdateNewFriend(friend);
if(id>0){
showAddNotify(friend);
}
}else if(type.equals("agree")){//接收到的对方同意添加自己为好友,此时需要做的事情1、添加对方为好友2、显示通知
AgreeAddFriendMessage agree = AgreeAddFriendMessage.convert(msg);
addFriend(agree.getFromId());//添加消息的发送方为好友
//这里应该也需要做下校验--来检测下是否已经同意过该好友请求,我这里省略了
showAgreeNotify(info,agree);
}else{
Toast.makeText(context,"接收到的自定义消息:"+msg.getMsgType() + "," + msg.getContent() + "," + msg.getExtra(),Toast.LENGTH_SHORT).show();
}
}
/**
*
* @param friend
*/
private void showAddNotify(NewFriend friend){
Intent pendingIntent = new Intent(context, MainActivity.class);
pendingIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
//这里可以是应用图标也可以将聊天头像转成bitmap
Bitmap largetIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
BmobNotificationManager.getInstance(context).showNotification(largetIcon,
friend.getName(), friend.getMsg(), friend.getName() + "请求添加你为朋友", pendingIntent);
}
/**
*
* @param info
* @param agree
*/
private void showAgreeNotify(BmobIMUserInfo info,AgreeAddFriendMessage agree){
Intent pendingIntent = new Intent(context, MainActivity.class);
pendingIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
Bitmap largetIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
BmobNotificationManager.getInstance(context).showNotification(largetIcon,info.getName(),agree.getMsg(),agree.getMsg(),pendingIntent);
}
/**
*
* @param uid
*/
private void addFriend(String uid){
User user =new User();
user.setObjectId(uid);
UserModel.getInstance().agreeAddFriend(user, new SaveListener() {
@Override
public void onSuccess() {
Log.i("bmob", "onSuccess");
}
@Override
public void onFailure(int i, String s) {
Log.i("bmob", "onFailure:"+s+"-"+i);
}
});
}
}

@ -0,0 +1,43 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.newim.bean.BmobIMMessage;
/**
* agree
*/
public class AgreeHolder extends BaseViewHolder implements View.OnClickListener,View.OnLongClickListener {
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.tv_message)
protected TextView tv_message;
public AgreeHolder(Context context, ViewGroup root, OnRecyclerViewListener listener) {
super(context, root, R.layout.item_chat_agree, listener);
}
@Override
public void bindData(Object o) {
final BmobIMMessage message = (BmobIMMessage)o;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time = dateFormat.format(message.getCreateTime());
String content = message.getContent();
tv_message.setText(content);
tv_time.setText(time);
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,219 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMMessageType;
import cn.bmob.v3.BmobUser;
/**
* @author :smile
* @project:ChatAdapter
* @date :2016-01-22-14:18
*/
public class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
//文本
private final int TYPE_RECEIVER_TXT = 0;
private final int TYPE_SEND_TXT = 1;
//图片
private final int TYPE_SEND_IMAGE = 2;
private final int TYPE_RECEIVER_IMAGE = 3;
//位置
private final int TYPE_SEND_LOCATION = 4;
private final int TYPE_RECEIVER_LOCATION = 5;
//语音
private final int TYPE_SEND_VOICE =6;
private final int TYPE_RECEIVER_VOICE = 7;
//视频
private final int TYPE_SEND_VIDEO =8;
private final int TYPE_RECEIVER_VIDEO = 9;
//同意添加好友成功后的样式
private final int TYPE_AGREE = 10;
/**
* :10
*/
private final long TIME_INTERVAL = 10 * 60 * 1000;
private List<BmobIMMessage> msgs = new ArrayList<>();
private String currentUid="";
BmobIMConversation c;
public ChatAdapter(Context context,BmobIMConversation c) {
try {
currentUid = BmobUser.getCurrentUser(context).getObjectId();
} catch (Exception e) {
e.printStackTrace();
}
this.c =c;
}
public int findPosition(BmobIMMessage message) {
int index = this.getCount();
int position = -1;
while(index-- > 0) {
if(message.equals(this.getItem(index))) {
position = index;
break;
}
}
return position;
}
public int findPosition(long id) {
int index = this.getCount();
int position = -1;
while(index-- > 0) {
if(this.getItemId(index) == id) {
position = index;
break;
}
}
return position;
}
public int getCount() {
return this.msgs == null?0:this.msgs.size();
}
public void addMessages(List<BmobIMMessage> messages) {
msgs.addAll(0, messages);
notifyDataSetChanged();
}
public void addMessage(BmobIMMessage message) {
msgs.addAll(Arrays.asList(message));
notifyDataSetChanged();
}
/**
* @param position
* @return
*/
public BmobIMMessage getItem(int position){
return this.msgs == null?null:(position >= this.msgs.size()?null:this.msgs.get(position));
}
/**
* @param position
*/
public void remove(int position){
msgs.remove(position);
notifyDataSetChanged();
}
public BmobIMMessage getFirstMessage() {
if (null != msgs && msgs.size() > 0) {
return msgs.get(0);
} else {
return null;
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_SEND_TXT) {
return new SendTextHolder(parent.getContext(), parent,c,onRecyclerViewListener);
} else if (viewType == TYPE_SEND_IMAGE) {
return new SendImageHolder(parent.getContext(), parent,c,onRecyclerViewListener);
} else if (viewType == TYPE_SEND_LOCATION) {
return new SendLocationHolder(parent.getContext(), parent,c,onRecyclerViewListener);
} else if (viewType == TYPE_SEND_VOICE) {
return new SendVoiceHolder(parent.getContext(), parent,c,onRecyclerViewListener);
} else if (viewType == TYPE_RECEIVER_TXT) {
return new ReceiveTextHolder(parent.getContext(), parent,onRecyclerViewListener);
} else if (viewType == TYPE_RECEIVER_IMAGE) {
return new ReceiveImageHolder(parent.getContext(), parent,onRecyclerViewListener);
} else if (viewType == TYPE_RECEIVER_LOCATION) {
return new ReceiveLocationHolder(parent.getContext(), parent,onRecyclerViewListener);
} else if (viewType == TYPE_RECEIVER_VOICE) {
return new ReceiveVoiceHolder(parent.getContext(), parent,onRecyclerViewListener);
} else if (viewType == TYPE_SEND_VIDEO) {
return new SendVideoHolder(parent.getContext(), parent,c,onRecyclerViewListener);
} else if (viewType == TYPE_RECEIVER_VIDEO) {
return new ReceiveVideoHolder(parent.getContext(), parent,onRecyclerViewListener);
}else if(viewType ==TYPE_AGREE) {
return new AgreeHolder(parent.getContext(),parent,onRecyclerViewListener);
}else{//开发者自定义的其他类型,可自行处理
return null;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((BaseViewHolder)holder).bindData(msgs.get(position));
if (holder instanceof ReceiveTextHolder) {
((ReceiveTextHolder)holder).showTime(shouldShowTime(position));
} else if (holder instanceof ReceiveImageHolder) {
((ReceiveImageHolder)holder).showTime(shouldShowTime(position));
}else if (holder instanceof ReceiveLocationHolder) {
((ReceiveLocationHolder)holder).showTime(shouldShowTime(position));
}else if (holder instanceof ReceiveVoiceHolder) {
((ReceiveVoiceHolder)holder).showTime(shouldShowTime(position));
}else if (holder instanceof SendTextHolder) {
((SendTextHolder)holder).showTime(shouldShowTime(position));
}else if (holder instanceof SendImageHolder) {
((SendImageHolder)holder).showTime(shouldShowTime(position));
}else if (holder instanceof SendLocationHolder) {
((SendLocationHolder)holder).showTime(shouldShowTime(position));
}else if (holder instanceof SendVoiceHolder) {
((SendVoiceHolder)holder).showTime(shouldShowTime(position));
}else if (holder instanceof SendVideoHolder) {//随便模拟的视频类型
((SendVideoHolder)holder).showTime(shouldShowTime(position));
}else if (holder instanceof ReceiveVideoHolder) {
((ReceiveVideoHolder)holder).showTime(shouldShowTime(position));
}else if (holder instanceof AgreeHolder) {//同意添加好友成功后的消息
((AgreeHolder)holder).showTime(shouldShowTime(position));
}
}
@Override
public int getItemViewType(int position) {
BmobIMMessage message = msgs.get(position);
if(message.getMsgType().equals(BmobIMMessageType.IMAGE.getType())){
return message.getFromId().equals(currentUid) ? TYPE_SEND_IMAGE: TYPE_RECEIVER_IMAGE;
}else if(message.getMsgType().equals(BmobIMMessageType.LOCATION.getType())){
return message.getFromId().equals(currentUid) ? TYPE_SEND_LOCATION: TYPE_RECEIVER_LOCATION;
}else if(message.getMsgType().equals(BmobIMMessageType.VOICE.getType())){
return message.getFromId().equals(currentUid) ? TYPE_SEND_VOICE: TYPE_RECEIVER_VOICE;
}else if(message.getMsgType().equals(BmobIMMessageType.TEXT.getType())){
return message.getFromId().equals(currentUid) ? TYPE_SEND_TXT: TYPE_RECEIVER_TXT;
}else if(message.getMsgType().equals(BmobIMMessageType.VIDEO.getType())){
return message.getFromId().equals(currentUid) ? TYPE_SEND_VIDEO: TYPE_RECEIVER_VIDEO;
}else if(message.getMsgType().equals("agree")) {//显示欢迎
return TYPE_AGREE;
}else{
return -1;
}
}
@Override
public int getItemCount() {
return msgs.size();
}
private OnRecyclerViewListener onRecyclerViewListener;
public void setOnRecyclerViewListener(OnRecyclerViewListener onRecyclerViewListener) {
this.onRecyclerViewListener = onRecyclerViewListener;
}
private boolean shouldShowTime(int position) {
if (position == 0) {
return true;
}
long lastTime = msgs.get(position - 1).getCreateTime();
long curTime = msgs.get(position).getCreateTime();
return curTime - lastTime > TIME_INTERVAL;
}
}

@ -0,0 +1,48 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import java.util.Collection;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseRecyclerAdapter;
import cn.bmob.imdemo.adapter.base.BaseRecyclerHolder;
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
import cn.bmob.imdemo.bean.Friend;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.db.NewFriendManager;
/**
* AdapterItemrecycleViewViewHolder
* @author :smile
* @project:ContactNewAdapter
* @date :2016-04-27-14:18
*/
public class ContactAdapter extends BaseRecyclerAdapter<Friend> {
public static final int TYPE_NEW_FRIEND = 0;
public static final int TYPE_ITEM = 1;
public ContactAdapter(Context context, IMutlipleItem<Friend> items, Collection<Friend> datas) {
super(context,items,datas);
}
@Override
public void bindView(BaseRecyclerHolder holder, Friend friend, int position) {
if(holder.layoutId==R.layout.item_contact){
User user =friend.getFriendUser();
//好友头像
holder.setImageView(user == null ? null : user.getAvatar(), R.mipmap.head, R.id.iv_recent_avatar);
//好友名称
holder.setText(R.id.tv_recent_name,user==null?"未知":user.getUsername());
}else if(holder.layoutId==R.layout.header_new_friend){
if(NewFriendManager.getInstance(context).hasNewFriendInvitation()){
holder.setVisible(R.id.iv_msg_tips,View.VISIBLE);
}else{
holder.setVisible(R.id.iv_msg_tips, View.GONE);
}
}
}
}

@ -0,0 +1,54 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import java.util.Collection;
import java.util.List;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseRecyclerAdapter;
import cn.bmob.imdemo.adapter.base.BaseRecyclerHolder;
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
import cn.bmob.imdemo.bean.Conversation;
import cn.bmob.imdemo.util.TimeUtil;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMMessageType;
/**
* 使Conversation,
* @author smile
*/
public class ConversationAdapter extends BaseRecyclerAdapter<Conversation> {
public ConversationAdapter(Context context, IMutlipleItem<Conversation> items, Collection<Conversation> datas) {
super(context,items,datas);
}
@Override
public void bindView(BaseRecyclerHolder holder, Conversation conversation, int position) {
holder.setText(R.id.tv_recent_msg,conversation.getLastMessageContent());
holder.setText(R.id.tv_recent_time,TimeUtil.getChatTime(false,conversation.getLastMessageTime()));
//会话图标
Object obj = conversation.getAvatar();
if(obj instanceof String){
String avatar=(String)obj;
holder.setImageView(avatar, R.mipmap.head, R.id.iv_recent_avatar);
}else{
int defaultRes = (int)obj;
holder.setImageView(null, defaultRes, R.id.iv_recent_avatar);
}
//会话标题
holder.setText(R.id.tv_recent_name, conversation.getcName());
//查询指定未读消息数
long unread = conversation.getUnReadCount();
if(unread>0){
holder.setVisible(R.id.tv_recent_unread, View.VISIBLE);
holder.setText(R.id.tv_recent_unread, String.valueOf(unread));
}else{
holder.setVisible(R.id.tv_recent_unread, View.GONE);
}
}
}

@ -0,0 +1,137 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.bmob.imdemo.Config;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseRecyclerAdapter;
import cn.bmob.imdemo.adapter.base.BaseRecyclerHolder;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.imdemo.bean.AgreeAddFriendMessage;
import cn.bmob.imdemo.bean.Friend;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.db.NewFriend;
import cn.bmob.imdemo.db.NewFriendManager;
import cn.bmob.imdemo.model.UserModel;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.core.BmobIMClient;
import cn.bmob.newim.listener.MessageSendListener;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;
/**
* @author :smile
* @project:NewFriendAdapter
* @date :2016-04-27-14:18
*/
public class NewFriendAdapter extends BaseRecyclerAdapter<NewFriend>{
public NewFriendAdapter(Context context, IMutlipleItem<NewFriend> items, Collection<NewFriend> datas) {
super(context,items,datas);
}
@Override
public void bindView(final BaseRecyclerHolder holder, final NewFriend add, int position) {
holder.setImageView(add == null ? null : add.getAvatar(), R.mipmap.head, R.id.iv_recent_avatar);
holder.setText(R.id.tv_recent_name,add==null?"未知":add.getName());
holder.setText(R.id.tv_recent_msg,add==null?"未知":add.getMsg());
Integer status =add.getStatus();
Logger.i("bindData:"+status+","+add.getUid()+","+add.getTime());
if(status==null || status== Config.STATUS_VERIFY_NONE||status ==Config.STATUS_VERIFY_READED){//未添加/已读未添加
holder.setText(R.id.btn_aggree,"接受");
holder.setEnabled(R.id.btn_aggree,true);
holder.setOnClickListener(R.id.btn_aggree,new View.OnClickListener() {
@Override
public void onClick(View v) {//发送消息
agreeAdd(add, new SaveListener() {
@Override
public void onSuccess() {
holder.setText(R.id.btn_aggree,"已添加");
holder.setEnabled(R.id.btn_aggree,false);
}
@Override
public void onFailure(int i, String s) {
holder.setEnabled(R.id.btn_aggree,true);
toast("添加好友失败:" + s);
}
});
}
});
}else{
holder.setText(R.id.btn_aggree,"已添加");
holder.setEnabled(R.id.btn_aggree,false);
}
}
/**
* ...
* @param add
* @param listener
*/
private void agreeAdd(final NewFriend add, final SaveListener listener){
User user =new User();
user.setObjectId(add.getUid());
UserModel.getInstance().agreeAddFriend(user, new SaveListener() {
@Override
public void onSuccess() {
sendAgreeAddFriendMessage(add, listener);
}
@Override
public void onFailure(int i, String s) {
listener.onFailure(i, s);
}
});
}
/**
*
*/
private void sendAgreeAddFriendMessage(final NewFriend add,final SaveListener listener){
BmobIMUserInfo info = new BmobIMUserInfo(add.getUid(), add.getName(), add.getAvatar());
//如果为true,则表明为暂态会话,也就是说该会话仅执行发送消息的操作,不会保存会话和消息到本地数据库中
BmobIMConversation c = BmobIM.getInstance().startPrivateConversation(info,true,null);
//这个obtain方法才是真正创建一个管理消息发送的会话
BmobIMConversation conversation = BmobIMConversation.obtain(BmobIMClient.getInstance(),c);
//而AgreeAddFriendMessage的isTransient设置为false表明我希望在对方的会话数据库中保存该类型的消息
AgreeAddFriendMessage msg =new AgreeAddFriendMessage();
User currentUser = BmobUser.getCurrentUser(context, User.class);
msg.setContent("我通过了你的好友验证请求,我们可以开始聊天了!");//---这句话是直接存储到对方的消息表中的
Map<String,Object> map =new HashMap<>();
map.put("msg",currentUser.getUsername()+"同意添加你为好友");//显示在通知栏上面的内容
map.put("uid",add.getUid());//发送者的uid-方便请求添加的发送方找到该条添加好友的请求
map.put("time", add.getTime());//添加好友的请求时间
msg.setExtraMap(map);
conversation.sendMessage(msg, new MessageSendListener() {
@Override
public void done(BmobIMMessage msg, BmobException e){
if (e == null) {//发送成功
//修改本地的好友请求记录
NewFriendManager.getInstance(context).updateNewFriend(add,Config.STATUS_VERIFIED);
listener.onSuccess();
} else {//发送失败
listener.onFailure(e.getErrorCode(),e.getMessage());
}
}
});
}
}

@ -0,0 +1,144 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.view.View;
import android.widget.ImageView;
import java.io.File;
import java.io.FileInputStream;
import cn.bmob.imdemo.R;
import cn.bmob.newim.bean.BmobIMAudioMessage;
import cn.bmob.newim.core.BmobDownloadManager;
import cn.bmob.v3.BmobUser;
public class NewRecordPlayClickListener implements View.OnClickListener {
BmobIMAudioMessage message;
ImageView iv_voice;
private AnimationDrawable anim = null;
Context mContext;
String currentObjectId = "";
MediaPlayer mediaPlayer = null;
public static boolean isPlaying = false;
public static NewRecordPlayClickListener currentPlayListener = null;
static BmobIMAudioMessage currentMsg = null;
public NewRecordPlayClickListener(Context context, BmobIMAudioMessage msg,ImageView voice) {
this.iv_voice = voice;
this.message = msg;
this.mContext = context.getApplicationContext();
currentMsg = msg;
currentPlayListener = this;
try {
currentObjectId = BmobUser.getCurrentUser(mContext).getObjectId();
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("resource")
public void startPlayRecord(String filePath, boolean isUseSpeaker) {
if (!(new File(filePath).exists())) {
return;
}
AudioManager audioManager = (AudioManager) mContext
.getSystemService(Context.AUDIO_SERVICE);
mediaPlayer = new MediaPlayer();
if (isUseSpeaker) {
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setSpeakerphoneOn(true);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
} else {
audioManager.setSpeakerphoneOn(false);
audioManager.setMode(AudioManager.MODE_IN_CALL);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
}
try {
mediaPlayer.reset();
// 单独使用此方法会报错播放错误:setDataSourceFD failed.: status=0x80000000
// mediaPlayer.setDataSource(filePath);
// 因此采用此方式会避免这种错误
FileInputStream fis = new FileInputStream(new File(filePath));
mediaPlayer.setDataSource(fis.getFD());
mediaPlayer.prepare();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer arg0) {
isPlaying = true;
currentMsg = message;
arg0.start();
startRecordAnimation();
}
});
mediaPlayer
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
stopPlayRecord();
}
});
currentPlayListener = this;
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopPlayRecord() {
stopRecordAnimation();
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
}
isPlaying = false;
}
private void startRecordAnimation() {
if (message.getFromId().equals(currentObjectId)) {
iv_voice.setImageResource(R.drawable.anim_chat_voice_right);
} else {
iv_voice.setImageResource(R.drawable.anim_chat_voice_left);
}
anim = (AnimationDrawable) iv_voice.getDrawable();
anim.start();
}
private void stopRecordAnimation() {
if (message.getFromId().equals(currentObjectId)) {
iv_voice.setImageResource(R.mipmap.voice_left3);
} else {
iv_voice.setImageResource(R.mipmap.voice_right3);
}
if (anim != null) {
anim.stop();
}
}
@Override
public void onClick(View arg0) {
if (isPlaying) {
currentPlayListener.stopPlayRecord();
if (currentMsg != null
&& currentMsg.hashCode() == message.hashCode()) {
currentMsg = null;
return;
}
}
if (message.getFromId().equals(currentObjectId)) {// 如果是自己发送的语音消息,则播放本地地址
String localPath = message.getContent().split("&")[0];
startPlayRecord(localPath, true);
} else {// 如果是收到的消息,则需要先下载后播放
String localPath = BmobDownloadManager.getDownLoadFilePath(message);
startPlayRecord(localPath, true);
}
}
}

@ -0,0 +1,11 @@
package cn.bmob.imdemo.adapter;
/**RecycleView
* @author smile
* @project OnRecyclerViewListener
* @date 2016-03-03-16:39
*/
public interface OnRecyclerViewListener {
void onItemClick(int position);
boolean onItemLongClick(int position);
}

@ -0,0 +1,111 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMImageMessage;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMUserInfo;
/**
*
*/
public class ReceiveImageHolder extends BaseViewHolder {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.iv_picture)
protected ImageView iv_picture;
@Bind(R.id.progress_load)
protected ProgressBar progress_load;
public ReceiveImageHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
super(context, root, R.layout.item_chat_received_image,onRecyclerViewListener);
}
@Override
public void bindData(Object o) {
BmobIMMessage msg = (BmobIMMessage)o;
//用户信息的获取必须在buildFromDB之前否则会报错'Entity is detached from DAO context'
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
String time = dateFormat.format(msg.getCreateTime());
tv_time.setText(time);
//可使用buildFromDB方法转化为指定类型的消息
final BmobIMImageMessage message = BmobIMImageMessage.buildFromDB(false,msg);
//显示图片
ImageLoaderFactory.getLoader().load(iv_picture,message.getRemoteUrl(), R.mipmap.ic_launcher,new ImageLoadingListener(){;
@Override
public void onLoadingStarted(String s, View view) {
progress_load.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingComplete(String s, View view, Bitmap bitmap) {
progress_load.setVisibility(View.INVISIBLE);
}
@Override
public void onLoadingCancelled(String s, View view) {
progress_load.setVisibility(View.INVISIBLE);
}
@Override
public void onLoadingFailed(String s, View view, FailReason failReason) {
progress_load.setVisibility(View.INVISIBLE);
}
});
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击" + info.getName() + "的头像");
}
});
iv_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击图片:"+message.getRemoteUrl()+"");
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemClick(getAdapterPosition());
}
}
});
iv_picture.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,81 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMLocationMessage;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMUserInfo;
/**
*
*/
public class ReceiveLocationHolder extends BaseViewHolder {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.tv_location)
protected TextView tv_location;
public ReceiveLocationHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
super(context, root, R.layout.item_chat_received_location,onRecyclerViewListener);
}
@Override
public void bindData(Object o) {
BmobIMMessage msg = (BmobIMMessage)o;
//用户信息的获取必须在buildFromDB之前否则会报错'Entity is detached from DAO context'
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
//加载头像
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
String time = dateFormat.format(msg.getCreateTime());
tv_time.setText(time);
//
final BmobIMLocationMessage message = BmobIMLocationMessage.buildFromDB(msg);
tv_location.setText(message.getAddress());
//
tv_location.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("经度:" + message.getLongitude() + ",维度:" + message.getLatitude());
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemClick(getAdapterPosition());
}
}
});
tv_location.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击"+info.getName()+"头像");
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,82 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import butterknife.OnClick;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMUserInfo;
/**
*
*/
public class ReceiveTextHolder extends BaseViewHolder {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.tv_message)
protected TextView tv_message;
public ReceiveTextHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
super(context, root, R.layout.item_chat_received_message,onRecyclerViewListener);
}
@OnClick({R.id.iv_avatar})
public void onAvatarClick(View view) {
}
@Override
public void bindData(Object o) {
final BmobIMMessage message = (BmobIMMessage)o;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
String time = dateFormat.format(message.getCreateTime());
tv_time.setText(time);
final BmobIMUserInfo info = message.getBmobIMUserInfo();
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
String content = message.getContent();
tv_message.setText(content);
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击" + info.getName() + "的头像");
}
});
tv_message.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击"+message.getContent());
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemClick(getAdapterPosition());
}
}
});
tv_message.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,83 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import butterknife.OnClick;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMUserInfo;
/**
* --
*/
public class ReceiveVideoHolder extends BaseViewHolder {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.tv_message)
protected TextView tv_message;
public ReceiveVideoHolder(Context context, ViewGroup root, OnRecyclerViewListener onRecyclerViewListener) {
super(context, root, R.layout.item_chat_received_message,onRecyclerViewListener);
}
@OnClick({R.id.iv_avatar})
public void onAvatarClick(View view) {
}
@Override
public void bindData(Object o) {
final BmobIMMessage message = (BmobIMMessage)o;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
String time = dateFormat.format(message.getCreateTime());
tv_time.setText(time);
final BmobIMUserInfo info = message.getBmobIMUserInfo();
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
String content = message.getContent();
tv_message.setText("接收到的视频文件:"+content);
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击" + info.getName() + "的头像");
}
});
tv_message.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击"+message.getContent());
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemClick(getAdapterPosition());
}
}
});
tv_message.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,118 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMAudioMessage;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.core.BmobDownloadManager;
import cn.bmob.newim.listener.FileDownloadListener;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
/**
*
*/
public class ReceiveVoiceHolder extends BaseViewHolder {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.tv_voice_length)
protected TextView tv_voice_length;
@Bind(R.id.iv_voice)
protected ImageView iv_voice;
@Bind(R.id.progress_load)
protected ProgressBar progress_load;
private String currentUid="";
public ReceiveVoiceHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
super(context, root, R.layout.item_chat_received_voice,onRecyclerViewListener);
try {
currentUid = BmobUser.getCurrentUser(context).getObjectId();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void bindData(Object o) {
BmobIMMessage msg = (BmobIMMessage)o;
//用户信息的获取必须在buildFromDB之前否则会报错'Entity is detached from DAO context'
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
String time = dateFormat.format(msg.getCreateTime());
tv_time.setText(time);
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击" + info.getName() + "的头像");
}
});
//显示特有属性
final BmobIMAudioMessage message = BmobIMAudioMessage.buildFromDB(false, msg);
boolean isExists = BmobDownloadManager.isAudioExist(currentUid, message);
if(!isExists){//若指定格式的录音文件不存在,则需要下载,因为其文件比较小,故放在此下载
BmobDownloadManager downloadTask = new BmobDownloadManager(getContext(),msg,new FileDownloadListener() {
@Override
public void onStart() {
progress_load.setVisibility(View.VISIBLE);
tv_voice_length.setVisibility(View.GONE);
iv_voice.setVisibility(View.INVISIBLE);//只有下载完成才显示播放的按钮
}
@Override
public void done(BmobException e) {
if(e==null){
progress_load.setVisibility(View.GONE);
tv_voice_length.setVisibility(View.VISIBLE);
tv_voice_length.setText(message.getDuration()+"\''");
iv_voice.setVisibility(View.VISIBLE);
}else{
progress_load.setVisibility(View.GONE);
tv_voice_length.setVisibility(View.GONE);
iv_voice.setVisibility(View.INVISIBLE);
}
}
});
downloadTask.execute(message.getContent());
}else{
tv_voice_length.setVisibility(View.VISIBLE);
tv_voice_length.setText(message.getDuration() + "\''");
}
iv_voice.setOnClickListener(new NewRecordPlayClickListener(getContext(), message, iv_voice));
iv_voice.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,64 @@
package cn.bmob.imdemo.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.bean.User;
/**
* @author :smile
* @project:SearchUserAdapter
* @date :2016-01-22-14:18
*/
public class SearchUserAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private List<User> users = new ArrayList<>();
public SearchUserAdapter() {
}
public void setDatas(List<User> list) {
users.clear();
if (null != list) {
users.addAll(list);
}
}
/**
* @param position
* @return
*/
public User getItem(int position){
return users.get(position);
}
private OnRecyclerViewListener onRecyclerViewListener;
public void setOnRecyclerViewListener(OnRecyclerViewListener onRecyclerViewListener) {
this.onRecyclerViewListener = onRecyclerViewListener;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new SearchUserHolder(parent.getContext(), parent, onRecyclerViewListener);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((BaseViewHolder)holder).bindData(users.get(position));
}
@Override
public int getItemViewType(int position) {
return 1;
}
@Override
public int getItemCount() {
return users.size();
}
}

@ -0,0 +1,45 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.ui.UserInfoActivity;
public class SearchUserHolder extends BaseViewHolder {
@Bind(R.id.avatar)
public ImageView avatar;
@Bind(R.id.name)
public TextView name;
@Bind(R.id.btn_add)
public Button btn_add;
public SearchUserHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
super(context, root, R.layout.item_search_user,onRecyclerViewListener);
}
@Override
public void bindData(Object o) {
final User user =(User)o;
ImageLoaderFactory.getLoader().loadAvator(avatar,user.getAvatar(), R.mipmap.head);
name.setText(user.getUsername());
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {//查看个人详情
Bundle bundle = new Bundle();
bundle.putSerializable("u", user);
startActivity(UserInfoActivity.class,bundle);
}
});
}
}

@ -0,0 +1,144 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMImageMessage;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMSendStatus;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.listener.MessageSendListener;
import cn.bmob.v3.exception.BmobException;
/**
*
*/
public class SendImageHolder extends BaseViewHolder {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.iv_fail_resend)
protected ImageView iv_fail_resend;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.iv_picture)
protected ImageView iv_picture;
@Bind(R.id.tv_send_status)
protected TextView tv_send_status;
@Bind(R.id.progress_load)
protected ProgressBar progress_load;
BmobIMConversation c;
public SendImageHolder(Context context, ViewGroup root,BmobIMConversation c,OnRecyclerViewListener onRecyclerViewListener) {
super(context, root, R.layout.item_chat_sent_image,onRecyclerViewListener);
this.c =c;
}
@Override
public void bindData(Object o) {
BmobIMMessage msg = (BmobIMMessage)o;
//用户信息的获取必须在buildFromDB之前否则会报错'Entity is detached from DAO context'
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null,R.mipmap.head);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
String time = dateFormat.format(msg.getCreateTime());
tv_time.setText(time);
//
final BmobIMImageMessage message = BmobIMImageMessage.buildFromDB(true, msg);
int status =message.getSendStatus();
if (status == BmobIMSendStatus.SENDFAILED.getStatus() ||status == BmobIMSendStatus.UPLOADAILED.getStatus()) {
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
progress_load.setVisibility(View.VISIBLE);
iv_fail_resend.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
} else {
tv_send_status.setVisibility(View.VISIBLE);
tv_send_status.setText("已发送");
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
}
//发送的不是远程图片地址,则取本地地址
ImageLoaderFactory.getLoader().load(iv_picture,TextUtils.isEmpty(message.getRemoteUrl()) ? message.getLocalPath():message.getRemoteUrl(),R.mipmap.ic_launcher,null);
// ViewUtil.setPicture(TextUtils.isEmpty(message.getRemoteUrl()) ? message.getLocalPath():message.getRemoteUrl(), R.mipmap.ic_launcher, iv_picture,null);
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击" + info.getName() + "的头像");
}
});
iv_picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击图片:"+(TextUtils.isEmpty(message.getRemoteUrl()) ? message.getLocalPath():message.getRemoteUrl())+"");
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemClick(getAdapterPosition());
}
}
});
iv_picture.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
//重发
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
c.resendMessage(message, new MessageSendListener() {
@Override
public void onStart(BmobIMMessage msg) {
progress_load.setVisibility(View.VISIBLE);
iv_fail_resend.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
@Override
public void done(BmobIMMessage msg, BmobException e) {
if (e == null) {
tv_send_status.setVisibility(View.VISIBLE);
tv_send_status.setText("已发送");
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
} else {
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
}
});
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,137 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMLocationMessage;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMSendStatus;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.listener.MessageSendListener;
import cn.bmob.v3.exception.BmobException;
/**
*
*/
public class SendLocationHolder extends BaseViewHolder {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.iv_fail_resend)
protected ImageView iv_fail_resend;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.layout_location)
protected LinearLayout layout_location;
@Bind(R.id.tv_location)
protected TextView tv_location;
@Bind(R.id.tv_send_status)
protected TextView tv_send_status;
@Bind(R.id.progress_load)
protected ProgressBar progress_load;
BmobIMConversation c;
public SendLocationHolder(Context context, ViewGroup root,BmobIMConversation c,OnRecyclerViewListener onRecyclerViewListener) {
super(context, root, R.layout.item_chat_sent_location,onRecyclerViewListener);
this.c = c;
}
@Override
public void bindData(Object o) {
BmobIMMessage msg = (BmobIMMessage)o;
//用户信息的获取必须在buildFromDB之前否则会报错'Entity is detached from DAO context'
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
String time = dateFormat.format(msg.getCreateTime());
tv_time.setText(time);
final BmobIMLocationMessage message = BmobIMLocationMessage.buildFromDB(msg);
tv_location.setText(message.getAddress());
int status =message.getSendStatus();
if (status == BmobIMSendStatus.SENDFAILED.getStatus()) {
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.VISIBLE);
} else {
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
}
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击" + info.getName() + "的头像");
}
});
tv_location.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("经度:" + message.getLongitude() + ",维度:" + message.getLatitude());
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemClick(getAdapterPosition());
}
}
});
tv_location.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
//重发
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
c.resendMessage(message, new MessageSendListener() {
@Override
public void onStart(BmobIMMessage msg) {
progress_load.setVisibility(View.VISIBLE);
iv_fail_resend.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
@Override
public void done(BmobIMMessage msg, BmobException e) {
if (e == null) {
tv_send_status.setVisibility(View.VISIBLE);
tv_send_status.setText("已发送");
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
} else {
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
}
});
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,135 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMSendStatus;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.listener.MessageSendListener;
import cn.bmob.v3.exception.BmobException;
/**
*
*/
public class SendTextHolder extends BaseViewHolder implements View.OnClickListener,View.OnLongClickListener {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.iv_fail_resend)
protected ImageView iv_fail_resend;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.tv_message)
protected TextView tv_message;
@Bind(R.id.tv_send_status)
protected TextView tv_send_status;
@Bind(R.id.progress_load)
protected ProgressBar progress_load;
BmobIMConversation c;
public SendTextHolder(Context context, ViewGroup root,BmobIMConversation c,OnRecyclerViewListener listener) {
super(context, root, R.layout.item_chat_sent_message, listener);
this.c =c;
}
@Override
public void bindData(Object o) {
final BmobIMMessage message = (BmobIMMessage)o;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
final BmobIMUserInfo info = message.getBmobIMUserInfo();
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
String time = dateFormat.format(message.getCreateTime());
String content = message.getContent();
tv_message.setText(content);
tv_time.setText(time);
int status =message.getSendStatus();
if (status == BmobIMSendStatus.SENDFAILED.getStatus()) {
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.VISIBLE);
} else {
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
}
tv_message.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击"+message.getContent());
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemClick(getAdapterPosition());
}
}
});
tv_message.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击" + info.getName() + "的头像");
}
});
//重发
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
c.resendMessage(message, new MessageSendListener() {
@Override
public void onStart(BmobIMMessage msg) {
progress_load.setVisibility(View.VISIBLE);
iv_fail_resend.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
@Override
public void done(BmobIMMessage msg, BmobException e) {
if(e==null){
tv_send_status.setVisibility(View.VISIBLE);
tv_send_status.setText("已发送");
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
}else{
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
}
});
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,136 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMSendStatus;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.listener.MessageSendListener;
import cn.bmob.v3.exception.BmobException;
/**
* ---
*/
public class SendVideoHolder extends BaseViewHolder implements View.OnClickListener,View.OnLongClickListener {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.iv_fail_resend)
protected ImageView iv_fail_resend;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.tv_message)
protected TextView tv_message;
@Bind(R.id.tv_send_status)
protected TextView tv_send_status;
@Bind(R.id.progress_load)
protected ProgressBar progress_load;
BmobIMConversation c;
public SendVideoHolder(Context context, ViewGroup root, BmobIMConversation c, OnRecyclerViewListener listener) {
super(context, root, R.layout.item_chat_sent_message, listener);
this.c =c;
}
@Override
public void bindData(Object o) {
final BmobIMMessage message = (BmobIMMessage)o;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
final BmobIMUserInfo info = message.getBmobIMUserInfo();
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
String time = dateFormat.format(message.getCreateTime());
String content = message.getContent();
tv_message.setText("发送的视频文件:"+content);
tv_time.setText(time);
int status =message.getSendStatus();
if (status == BmobIMSendStatus.SENDFAILED.getStatus()) {
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.VISIBLE);
} else {
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
}
tv_message.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击"+message.getContent());
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemClick(getAdapterPosition());
}
}
});
tv_message.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击" + info.getName() + "的头像");
}
});
//重发
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
c.resendMessage(message, new MessageSendListener() {
@Override
public void onStart(BmobIMMessage msg) {
progress_load.setVisibility(View.VISIBLE);
iv_fail_resend.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
@Override
public void done(BmobIMMessage msg, BmobException e) {
if(e==null){
tv_send_status.setVisibility(View.VISIBLE);
tv_send_status.setText("已发送");
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
}else{
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
}
});
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,137 @@
package cn.bmob.imdemo.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.newim.bean.BmobIMAudioMessage;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMSendStatus;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.listener.MessageSendListener;
import cn.bmob.v3.exception.BmobException;
/**
*
*/
public class SendVoiceHolder extends BaseViewHolder {
@Bind(R.id.iv_avatar)
protected ImageView iv_avatar;
@Bind(R.id.iv_fail_resend)
protected ImageView iv_fail_resend;
@Bind(R.id.tv_time)
protected TextView tv_time;
@Bind(R.id.tv_voice_length)
protected TextView tv_voice_length;
@Bind(R.id.iv_voice)
protected ImageView iv_voice;
@Bind(R.id.tv_send_status)
protected TextView tv_send_status;
@Bind(R.id.progress_load)
protected ProgressBar progress_load;
BmobIMConversation c;
public SendVoiceHolder(Context context, ViewGroup root,BmobIMConversation c,OnRecyclerViewListener onRecyclerViewListener) {
super(context, root, R.layout.item_chat_sent_voice,onRecyclerViewListener);
this.c =c;
}
@Override
public void bindData(Object o) {
BmobIMMessage msg = (BmobIMMessage)o;
//用户信息的获取必须在buildFromDB之前否则会报错'Entity is detached from DAO context'
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
String time = dateFormat.format(msg.getCreateTime());
tv_time.setText(time);
//使用buildFromDB方法转化成指定类型的消息
final BmobIMAudioMessage message = BmobIMAudioMessage.buildFromDB(true,msg);
tv_voice_length.setText(message.getDuration()+"\''");
int status =message.getSendStatus();
if (status == BmobIMSendStatus.SENDFAILED.getStatus()||status == BmobIMSendStatus.UPLOADAILED.getStatus()) {//发送失败/上传失败
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
tv_voice_length.setVisibility(View.INVISIBLE);
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
progress_load.setVisibility(View.VISIBLE);
iv_fail_resend.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
tv_voice_length.setVisibility(View.INVISIBLE);
} else {//发送成功
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
tv_send_status.setVisibility(View.GONE);
tv_voice_length.setVisibility(View.VISIBLE);
}
iv_voice.setOnClickListener(new NewRecordPlayClickListener(getContext(),message,iv_voice));
iv_voice.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (onRecyclerViewListener != null) {
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
});
iv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toast("点击" + info.getName() + "的头像");
}
});
//重发
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
c.resendMessage(message, new MessageSendListener() {
@Override
public void onStart(BmobIMMessage msg) {
progress_load.setVisibility(View.VISIBLE);
iv_fail_resend.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
@Override
public void done(BmobIMMessage msg, BmobException e) {
if(e==null){
tv_send_status.setVisibility(View.VISIBLE);
tv_send_status.setText("已发送");
iv_fail_resend.setVisibility(View.GONE);
progress_load.setVisibility(View.GONE);
}else{
iv_fail_resend.setVisibility(View.VISIBLE);
progress_load.setVisibility(View.GONE);
tv_send_status.setVisibility(View.INVISIBLE);
}
}
});
}
});
}
public void showTime(boolean isShow) {
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
}
}

@ -0,0 +1,221 @@
package cn.bmob.imdemo.adapter.base;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
import cn.bmob.imdemo.base.BaseActivity;
/**
*
* item
* recycleview/
* @param <T>
* @author smile
* @link https://github.com/bodismile/BaseRecyclerAdapter
*/
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseRecyclerHolder> {
/**
*
*/
private final int TYPE_DEFAULT = 0;
/**
* list
*/
private final int TYPE_HEADER = 1;
/**
*
*/
private final int TYPE_MUTIPLE = 2;
/**
* header
*/
private final int TYPE_MUTIPLE_HEADER = 3;
protected final Context context;
protected List<T> lists;
protected IMutlipleItem<T> items;
protected OnRecyclerViewListener listener;
/**
* Item
*
* @param context
* @param items
* @param datas
*/
public BaseRecyclerAdapter(Context context, IMutlipleItem<T> items, Collection<T> datas) {
this.context = context;
this.items = items;
this.lists = datas == null ? new ArrayList<T>() : new ArrayList<T>(datas);
}
/**
*
* @param datas
* @return
*/
public BaseRecyclerAdapter<T> bindDatas(Collection<T> datas) {
this.lists = datas == null ? new ArrayList<T>() : new ArrayList<T>(datas);
notifyDataSetChanged();
return this;
}
/**
*
* @param position
*/
public void remove(int position) {
int more = getItemCount() - lists.size();
lists.remove(position - more);
notifyDataSetChanged();
}
/**
* positionItem
* @param position
* @return
*/
public T getItem(int position) {
int more = getItemCount() - lists.size();
return lists.get(position - more);
}
@Override
public BaseRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layoutId = items.getItemLayoutId(viewType);
LayoutInflater inflater = LayoutInflater.from(context);
View root = inflater.inflate(layoutId, parent, false);
return new BaseRecyclerHolder(layoutId, root);
}
@Override
public void onBindViewHolder(BaseRecyclerHolder holder, int position) {
int type = getViewTypeByPosition(position);
if(type==TYPE_HEADER){
bindView(holder, null, position);
}else if(type==TYPE_MUTIPLE){
bindView(holder, lists.get(position), position);
}else if(type==TYPE_MUTIPLE_HEADER){
int headerCount = getItemCount() - lists.size();
bindView(holder, lists.get(position - headerCount), position);
}else{
bindView(holder, null, position);
}
holder.itemView.setOnClickListener(getOnClickListener(position));
holder.itemView.setOnLongClickListener(getOnLongClickListener(position));
}
@Override
public int getItemCount() {
if (items != null) {//当有多重布局的时候,则采用多重布局
return items.getItemCount(lists);
}
return lists.size();
}
@Override
public int getItemViewType(int position) {
int type = getViewTypeByPosition(position);
if(type==TYPE_HEADER){
return items.getItemViewType(position, null);
}else if(type==TYPE_MUTIPLE){
return items.getItemViewType(position, lists.get(position));
}else if(type==TYPE_MUTIPLE_HEADER){
int headerCount = getItemCount() - lists.size();
return items.getItemViewType(position, lists.get(position - headerCount));
}else{
return 0;
}
}
/**position
* @param position
*/
private int getViewTypeByPosition(int position) {
if (items == null) {//默认布局
return TYPE_DEFAULT;
} else {//多布局
if (lists != null && lists.size() > 0) {//list有值的时候
if (getItemCount() > lists.size()) {//是否有自定义的Header
int headerCount = getItemCount() - lists.size();
if (position >= headerCount) {//当前位置大于header个数
return TYPE_MUTIPLE_HEADER;
} else {//当前点击的是header
return TYPE_HEADER;
}
} else {
return TYPE_MUTIPLE;
}
} else {//list还没有值的时候
return TYPE_HEADER;
}
}
}
/**
* /
* @param onRecyclerViewListener
*/
public void setOnRecyclerViewListener(OnRecyclerViewListener onRecyclerViewListener) {
this.listener = onRecyclerViewListener;
}
public View.OnClickListener getOnClickListener(final int position) {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null && v != null) {
listener.onItemClick(position);
}
}
};
}
public View.OnLongClickListener getOnLongClickListener(final int position) {
return new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (listener != null && v != null) {
listener.onItemLongClick(position);
}
return true;
}
};
}
/**
*
* @param holder
* @param item
*/
public abstract void bindView(BaseRecyclerHolder holder, T item, int position);
private Toast toast;
public void toast(final Object obj) {
try {
((BaseActivity)context).runOnUiThread(new Runnable() {
@Override
public void run() {
if (toast == null)
toast = Toast.makeText(context,"", Toast.LENGTH_SHORT);
toast.setText(obj.toString());
toast.show();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}

@ -0,0 +1,123 @@
package cn.bmob.imdemo.adapter.base;
import android.graphics.Bitmap;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import cn.bmob.imdemo.base.ImageLoaderFactory;
/**
* BaseRecyclerAdapter使
*
*/
public class BaseRecyclerHolder extends RecyclerView.ViewHolder {
private final SparseArray<View> mViews;
public int layoutId;
public BaseRecyclerHolder(int layoutId,View itemView) {
super(itemView);
this.layoutId =layoutId;
this.mViews = new SparseArray<>(8);
}
public SparseArray<View> getAllView() {
return mViews;
}
/**
* @param viewId
* @return
*/
protected <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = itemView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
/**
* @param viewId
* @param text
* @return
*/
public BaseRecyclerHolder setText(int viewId, String text) {
TextView view = getView(viewId);
view.setText(text);
return this;
}
/**
* Enabled
* @param viewId
* @param enable
* @return
*/
public BaseRecyclerHolder setEnabled(int viewId,boolean enable){
View v = getView(viewId);
v.setEnabled(enable);
return this;
}
/**
*
* @param viewId
* @param listener
* @return
*/
public BaseRecyclerHolder setOnClickListener(int viewId, View.OnClickListener listener){
View v = getView(viewId);
v.setOnClickListener(listener);
return this;
}
/**
* @param viewId
* @param visibility
* @return
*/
public BaseRecyclerHolder setVisible(int viewId,int visibility) {
View view = getView(viewId);
view.setVisibility(visibility);
return this;
}
/**
* @param viewId
* @param drawableId
* @return
*/
public BaseRecyclerHolder setImageResource(int viewId, int drawableId) {
ImageView view = getView(viewId);
view.setImageResource(drawableId);
return this;
}
/**
* @param viewId
* @param bm
* @return
*/
public BaseRecyclerHolder setImageBitmap(int viewId, Bitmap bm) {
ImageView view = getView(viewId);
view.setImageBitmap(bm);
return this;
}
/**
* @param avatar
* @param defaultRes
* @param viewId
* @return
*/
public BaseRecyclerHolder setImageView(String avatar, int defaultRes, int viewId) {
ImageView iv = getView(viewId);
ImageLoaderFactory.getLoader().loadAvator(iv,avatar, defaultRes);
return this;
}
}

@ -0,0 +1,86 @@
package cn.bmob.imdemo.adapter.base;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import butterknife.ButterKnife;
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
import cn.bmob.imdemo.base.BaseActivity;
/**
* 使BaseRecyclerAdapter
* @param <T>
*/
public abstract class BaseViewHolder<T> extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener {
public OnRecyclerViewListener onRecyclerViewListener;
protected Context context;
public BaseViewHolder(Context context, ViewGroup root, int layoutRes,OnRecyclerViewListener listener) {
super(LayoutInflater.from(context).inflate(layoutRes, root, false));
this.context=context;
ButterKnife.bind(this, itemView);
this.onRecyclerViewListener =listener;
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
public Context getContext() {
return itemView.getContext();
}
public abstract void bindData(T t);
private Toast toast;
public void toast(final Object obj) {
try {
((BaseActivity)context).runOnUiThread(new Runnable() {
@Override
public void run() {
if (toast == null)
toast = Toast.makeText(context,"", Toast.LENGTH_SHORT);
toast.setText(obj.toString());
toast.show();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onClick(View v) {
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemClick(getAdapterPosition());
}
}
@Override
public boolean onLongClick(View v) {
if(onRecyclerViewListener!=null){
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
}
return true;
}
/**Activity
* @param target
* @param bundle
*/
public void startActivity(Class<? extends Activity> target, Bundle bundle) {
Intent intent = new Intent();
intent.setClass(getContext(), target);
if (bundle != null)
intent.putExtra(getContext().getPackageName(), bundle);
getContext().startActivity(intent);
}
}

@ -0,0 +1,31 @@
package cn.bmob.imdemo.adapter.base;
import java.util.List;
/**
* Created by Administrator on 2016/5/6.
*/
public interface IMutlipleItem<T> {
/**
* layout
* @param viewtype
* @return
*/
int getItemLayoutId(int viewtype);
/**
*
* @param postion
* @param t
* @return
*/
int getItemViewType(int postion, T t);
/**
*
* @param list
* @return
*/
int getItemCount(List<T> list);
}

@ -0,0 +1,139 @@
package cn.bmob.imdemo.base;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import com.orhanobut.logger.Logger;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import butterknife.ButterKnife;
import cn.bmob.imdemo.Config;
/**
* @author :smile
* @project:BaseActivity
* @date :2016-01-15-18:23
*/
public class BaseActivity extends FragmentActivity {
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
@Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
ButterKnife.bind(this);
initView();
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
super.setContentView(view, params);
ButterKnife.bind(this);
initView();
}
@Override
protected void onDestroy() {
super.onDestroy();
ButterKnife.unbind(this);
}
@Subscribe
public void onEvent(Boolean empty){
}
protected void initView() {}
protected void runOnMain(Runnable runnable) {
runOnUiThread(runnable);
}
protected final static String NULL = "";
private Toast toast;
public void toast(final Object obj) {
try {
runOnMain(new Runnable() {
@Override
public void run() {
if (toast == null)
toast = Toast.makeText(BaseActivity.this, NULL,Toast.LENGTH_SHORT);
toast.setText(obj.toString());
toast.show();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public void startActivity(Class<? extends Activity> target, Bundle bundle,boolean finish) {
Intent intent = new Intent();
intent.setClass(this, target);
if (bundle != null)
intent.putExtra(getPackageName(), bundle);
startActivity(intent);
if (finish)
finish();
}
public Bundle getBundle() {
if (getIntent() != null && getIntent().hasExtra(getPackageName()))
return getIntent().getBundleExtra(getPackageName());
else
return null;
}
/**
*
*/
public void hideSoftInputView() {
InputMethodManager manager = ((InputMethodManager) this.getSystemService(Activity.INPUT_METHOD_SERVICE));
if (getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
if (getCurrentFocus() != null)
manager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
/**-EditText.getWindowToken()
* @param token
*/
public void hideSoftInput(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token,InputMethodManager.HIDE_NOT_ALWAYS);
}
}
/**Log
* @param msg
*/
public void log(String msg){
if(Config.DEBUG){
Logger.i(msg);
}
}
}

@ -0,0 +1,74 @@
package cn.bmob.imdemo.base;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.Fragment;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import com.orhanobut.logger.Logger;
import cn.bmob.imdemo.Config;
/**
* @author :smile
* @project:BaseActivity
* @date :2016-01-15-18:23
*/
public class BaseFragment extends Fragment {
protected void runOnMain(Runnable runnable) {
getActivity().runOnUiThread(runnable);
}
protected final static String NULL = "";
private Toast toast;
public void toast(final Object obj) {
try {
runOnMain(new Runnable() {
@Override
public void run() {
if (toast == null)
toast = Toast.makeText(getActivity(), NULL,Toast.LENGTH_SHORT);
toast.setText(obj.toString());
toast.show();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public void hideSoftInput(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token,InputMethodManager.HIDE_NOT_ALWAYS);
}
}
/**Activity
* @param target
* @param bundle
*/
public void startActivity(Class<? extends Activity> target, Bundle bundle) {
Intent intent = new Intent();
intent.setClass(getActivity(), target);
if (bundle != null)
intent.putExtra(getActivity().getPackageName(), bundle);
getActivity().startActivity(intent);
}
/**Log
* @param msg
*/
public void log(String msg){
if(Config.DEBUG){
Logger.i(msg);
}
}
}

@ -0,0 +1,30 @@
package cn.bmob.imdemo.base;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
/**
*
* @author smile
*/
public interface ILoader {
/**
*
* @param iv
* @param url
* @param defaultRes
*/
void loadAvator(ImageView iv, String url, int defaultRes);
/**
*
* @param iv
* @param url
* @param defaultRes
* @param listener
*/
void load(ImageView iv,String url,int defaultRes,ImageLoadingListener listener);
}

@ -0,0 +1,22 @@
package cn.bmob.imdemo.base;
/**
* Created by Administrator on 2016/5/24.
*/
public class ImageLoaderFactory {
private static volatile ILoader sInstance;
private ImageLoaderFactory() {}
public static ILoader getLoader() {
if (sInstance == null) {
synchronized (ImageLoaderFactory.class) {
if (sInstance == null) {
sInstance = new UniversalImageLoader();
}
}
}
return sInstance;
}
}

@ -0,0 +1,161 @@
package cn.bmob.imdemo.base;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.bean.User;
import cn.bmob.v3.BmobUser;
/**
* @author :smile
* @project:ParentWithNaviActivity
* @date :2015-08-18-11:29
*/
public abstract class ParentWithNaviActivity extends BaseActivity {
public ToolBarListener listener;
public TextView tv_title;
public ImageView tv_left;
public TextView tv_right;
/**:
* @return
*/
protected abstract String title();
/**stringid,
* @return
*/
public Object left(){return null;}
/**stringid,
* @return
*/
public Object right(){return null;}
/**,
* @return
*/
public ToolBarListener setToolBarListener(){return null;}
/**
*
*/
public void initNaviView(){
tv_title = getView(R.id.tv_title);
tv_right = getView(R.id.tv_right);
tv_left = getView(R.id.tv_left);
setNaviListener(setToolBarListener());
tv_left.setOnClickListener(clickListener);
tv_right.setOnClickListener(clickListener);
tv_title.setText(title());
refreshTop();
}
View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_left:
if (listener == null)
finish();
else{
listener.clickLeft();
}
break;
case R.id.tv_right:
if (listener != null)
listener.clickRight();
break;
default:
break;
}
}
};
protected void refreshTop() {
setLeftView(left()==null ? R.drawable.base_action_bar_back_bg_selector: left());
setValue(R.id.tv_right, right());
this.tv_title.setText(title());
}
private void setLeftView(Object obj){
if(obj !=null && !obj.equals("")){
tv_left.setVisibility(View.VISIBLE);
if(obj instanceof Integer){
tv_left.setImageResource(Integer.parseInt(obj.toString()));
}else{
tv_left.setImageResource(R.drawable.base_action_bar_back_bg_selector);
}
}else{
tv_left.setVisibility(View.INVISIBLE);
}
}
protected void setValue(int id,Object obj){
if (obj != null && !obj.equals("")) {
((TextView) getView(id)).setText("");
getView(id).setBackgroundDrawable(new BitmapDrawable());
if (obj instanceof String) {
((TextView) getView(id)).setText(obj.toString());
} else if (obj instanceof Integer) {
getView(id).setBackgroundResource(Integer.parseInt(obj.toString()));
}
} else {
((TextView) getView(id)).setText("");
getView(id).setBackgroundDrawable(new BitmapDrawable());
}
}
protected void setNaviListener(ToolBarListener listener) {
this.listener = listener;
}
@SuppressWarnings("unchecked")
protected <T extends View> T getView(int id) {
return (T) findViewById(id);
}
public boolean handleBackPressed(){
return false;
}
/**Drawable
* @param id
* @return
*/
public Drawable getDrawableResources(int id){
return getResources().getDrawable(id);
}
public interface ToolBarListener {
void clickLeft();
void clickRight();
}
/**Activity
* @param target
* @param bundle
*/
public void startActivity(Class<? extends Activity> target, Bundle bundle) {
Intent intent = new Intent();
intent.setClass(this, target);
if (bundle != null)
intent.putExtra(this.getPackageName(), bundle);
startActivity(intent);
}
public String getCurrentUid(){
return BmobUser.getCurrentUser(this,User.class).getObjectId();
}
}

@ -0,0 +1,139 @@
package cn.bmob.imdemo.base;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.base.ParentWithNaviActivity.ToolBarListener;
/**Fragment
* @author :smile
* @project:ParentWithNaviFragment
* @date :2015-08-18-14:19
*/
public abstract class ParentWithNaviFragment extends BaseFragment {
protected View rootView = null;
private ToolBarListener listener;
private TextView tv_title;
public TextView tv_right;
public ImageView tv_left;
public LinearLayout ll_navi;
/**
*
*/
public void initNaviView(){
tv_title = getView(R.id.tv_title);
tv_right = getView(R.id.tv_right);
tv_left = getView(R.id.tv_left);
setListener(setToolBarListener());
tv_left.setOnClickListener(clickListener);
tv_right.setOnClickListener(clickListener);
tv_title.setText(title());
refreshTop();
}
View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_left:
if (listener != null){
listener.clickLeft();
}
break;
case R.id.tv_right:
if (listener != null)
listener.clickRight();
break;
default:
break;
}
}
};
private void refreshTop() {
setLeftView(left());
setValue(R.id.tv_right, right());
this.tv_title.setText(title());
}
private void setLeftView(Object obj){
if(obj !=null && !obj.equals("")){
tv_left.setVisibility(View.VISIBLE);
if(obj instanceof Integer){
tv_left.setImageResource(Integer.parseInt(obj.toString()));
}else{
tv_left.setImageResource(R.drawable.base_action_bar_back_bg_selector);
}
}else{
tv_left.setVisibility(View.INVISIBLE);
}
}
private void setValue(int id,Object obj){
if (obj != null && !obj.equals("")) {
((TextView) getView(id)).setText("");
getView(id).setBackgroundDrawable(new BitmapDrawable());
if (obj instanceof String) {
((TextView) getView(id)).setText(obj.toString());
} else if (obj instanceof Integer) {
getView(id).setBackgroundResource(Integer.parseInt(obj.toString()));
}
} else {
((TextView) getView(id)).setText("");
getView(id).setBackgroundDrawable(new BitmapDrawable());
}
}
private void setListener(ToolBarListener listener) {
this.listener = listener;
}
/**
* @return
*/
protected abstract String title();
/**stringid
* @return
*/
public Object right(){
return null;
}
/**
* @return
*/
public Object left(){return null;}
/**
* @param color
*/
public void setNavBackground(int color){
ll_navi.setBackgroundColor(color);
}
/**
* @param dimenId
*/
public void setRightTextSize(float dimenId){
tv_right.setTextSize(dimenId);
}
/**
* @return
*/
public ToolBarListener setToolBarListener(){return null;}
protected <T extends View> T getView(int id) {
return (T) rootView.findViewById(id);
}
}

@ -0,0 +1,80 @@
package cn.bmob.imdemo.base;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.download.ImageDownloader;
import com.nostra13.universalimageloader.core.imageaware.ImageAware;
import com.nostra13.universalimageloader.core.imageaware.ImageViewAware;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.orhanobut.logger.Logger;
import cn.bmob.imdemo.util.DisplayConfig;
/**
* 使UIL便glidefresco
* Created by Administrator on 2016/5/24.
*/
public class UniversalImageLoader implements ILoader{
public UniversalImageLoader(){}
@Override
public void loadAvator(ImageView iv, String url, int defaultRes) {
if(!TextUtils.isEmpty(url)){
display(iv,url,true,defaultRes,null);
} else {
iv.setImageResource(defaultRes);
}
}
@Override
public void load(ImageView iv, String url, int defaultRes,ImageLoadingListener listener) {
if(!TextUtils.isEmpty(url)){
display(iv,url.trim(),false,defaultRes,listener);
} else {
iv.setImageResource(defaultRes);
}
}
/**
*
* @param iv
* @param url
* @param defaultRes
* @param listener
*/
private void display(ImageView iv,String url,boolean isCircle,int defaultRes,ImageLoadingListener listener){
if(!url.equals(iv.getTag())){//增加tag标记减少UIL的display次数
iv.setTag(url);
//不直接display imageview改为ImageAware解决ListView滚动时重复加载图片
ImageAware imageAware = new ImageViewAware(iv, false);
ImageLoader.getInstance().displayImage(url, imageAware, DisplayConfig.getDefaultOptions(isCircle,defaultRes),listener);
}
}
/**
* ImageLoader
* @param context
*/
public static void initImageLoader(Context context) {
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
config.threadPoolSize(3);
config.memoryCache(new WeakMemoryCache());
config.threadPriority(Thread.NORM_PRIORITY - 2);
config.denyCacheImageMultipleSizesInMemory();
config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
config.tasksProcessingOrder(QueueProcessingType.LIFO);
// config.writeDebugLogs(); // Remove for release app
// Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(config.build());
}
}

@ -0,0 +1,63 @@
package cn.bmob.imdemo.bean;
import android.text.TextUtils;
import org.json.JSONObject;
import cn.bmob.imdemo.Config;
import cn.bmob.imdemo.db.NewFriend;
import cn.bmob.newim.bean.BmobIMExtraMessage;
import cn.bmob.newim.bean.BmobIMMessage;
import com.orhanobut.logger.Logger;
/**
* @author :smile
* @project:AddFriendMessage
* @date :2016-01-30-17:28
*/
public class AddFriendMessage extends BmobIMExtraMessage{
public AddFriendMessage(){}
/**BmobIMMessageNewFriend
* @param msg
* @return
*/
public static NewFriend convert(BmobIMMessage msg){
NewFriend add =new NewFriend();
String content = msg.getContent();
add.setMsg(content);
add.setTime(msg.getCreateTime());
add.setStatus(Config.STATUS_VERIFY_NONE);
try {
String extra = msg.getExtra();
if(!TextUtils.isEmpty(extra)){
JSONObject json =new JSONObject(extra);
String name = json.getString("name");
add.setName(name);
String avatar = json.getString("avatar");
add.setAvatar(avatar);
add.setUid(json.getString("uid"));
}else{
Logger.i("AddFriendMessage的extra为空");
}
} catch (Exception e) {
e.printStackTrace();
}
return add;
}
@Override
public String getMsgType() {
return "add";
}
@Override
public boolean isTransient() {
//设置为true,表明为暂态消息那么这条消息并不会保存到本地db中SDK只负责发送出去
//设置为false,则会保存到指定会话的数据库中
return true;
}
}

@ -0,0 +1,95 @@
package cn.bmob.imdemo.bean;
import android.text.TextUtils;
import com.orhanobut.logger.Logger;
import org.json.JSONObject;
import cn.bmob.newim.bean.BmobIMExtraMessage;
import cn.bmob.newim.bean.BmobIMMessage;
/**-
* @author smile
* @project AgreeAddFriendMessage
* @date 2016-03-04-10:41
* 1isTransientfalse,2
*/
public class AgreeAddFriendMessage extends BmobIMExtraMessage{
//以下均是从extra里面抽离出来的字段方便获取
private String uid;//最初的发送方
private Long time;
private String msg;//用于通知栏显示的内容
@Override
public String getMsgType() {
return "agree";
}
@Override
public boolean isTransient() {
//如果需要在对方的会话表中新增一条该类型的消息则设置为false表明是非暂态会话
//此处将同意添加好友的请求设置为false为了演示怎样向会话表和消息表中新增一个类型
return false;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public AgreeAddFriendMessage(){}
/**
* BmobIMMessage
* @param msg
*/
private AgreeAddFriendMessage(BmobIMMessage msg){
super.parse(msg);
}
/**BmobIMMessageAgreeAddFriendMessage
* @param msg
* @return
*/
public static AgreeAddFriendMessage convert(BmobIMMessage msg){
AgreeAddFriendMessage agree =new AgreeAddFriendMessage(msg);
try {
String extra = msg.getExtra();
if(!TextUtils.isEmpty(extra)){
JSONObject json =new JSONObject(extra);
Long time = json.getLong("time");
String uid =json.getString("uid");
String m =json.getString("msg");
agree.setMsg(m);
agree.setUid(uid);
agree.setTime(time);
}else{
Logger.i("AgreeAddFriendMessage的extra为空");
}
} catch (Exception e) {
e.printStackTrace();
}
return agree;
}
}

@ -0,0 +1,106 @@
package cn.bmob.imdemo.bean;
import android.content.Context;
import java.io.Serializable;
import cn.bmob.newim.bean.BmobIMConversationType;
/**
* BmobIMConveration,便
* @author smile
* @date 2016-05-25
*/
public abstract class Conversation implements Serializable,Comparable{
/**
* id
*/
protected String cId;
/**
*
*/
protected BmobIMConversationType cType;
/**
*
*/
protected String cName;
/**
* -
*/
abstract public Object getAvatar();
/**
*
*/
abstract public long getLastMessageTime();
/**
*
* @return
*/
abstract public String getLastMessageContent();
/**
*
* @return
*/
abstract public int getUnReadCount();
/**
*
*/
abstract public void readAllMessages();
/**
*
* @param context
*/
abstract public void onClick(Context context);
/**
*
* @param context
*/
abstract public void onLongClick(Context context);
public String getcName() {
return cName;
}
public String getcId(){
return cId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Conversation that = (Conversation) o;
if (!cId.equals(that.cId)) return false;
return cType == that.cType;
}
@Override
public int hashCode() {
int result = cId.hashCode();
result = 31 * result + cType.hashCode();
return result;
}
@Override
public int compareTo(Object another) {
if (another instanceof Conversation){
Conversation anotherConversation = (Conversation) another;
long timeGap = anotherConversation.getLastMessageTime() - getLastMessageTime();
if (timeGap > 0) return 1;
else if (timeGap < 0) return -1;
return 0;
}else{
throw new ClassCastException();
}
}
}

@ -0,0 +1,41 @@
package cn.bmob.imdemo.bean;
import cn.bmob.v3.BmobObject;
/**
* @author smile
* @project Friend
* @date 2016-04-26
*/
public class Friend extends BmobObject{
private User user;
private User friendUser;
//拼音
private transient String pinyin;
public String getPinyin() {
return pinyin;
}
public void setPinyin(String pinyin) {
this.pinyin = pinyin;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public User getFriendUser() {
return friendUser;
}
public void setFriendUser(User friendUser) {
this.friendUser = friendUser;
}
}

@ -0,0 +1,83 @@
package cn.bmob.imdemo.bean;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import cn.bmob.imdemo.BmobIMApplication;
import cn.bmob.imdemo.Config;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.db.NewFriend;
import cn.bmob.imdemo.db.NewFriendManager;
import cn.bmob.imdemo.ui.NewFriendActivity;
import cn.bmob.imdemo.util.TimeUtil;
/**
*
* Created by Administrator on 2016/5/25.
*/
public class NewFriendConversation extends Conversation{
NewFriend lastFriend;
public NewFriendConversation(NewFriend friend){
this.lastFriend=friend;
this.cName="新朋友";
}
@Override
public String getLastMessageContent() {
if(lastFriend!=null){
Integer status =lastFriend.getStatus();
String name = lastFriend.getName();
if(TextUtils.isEmpty(name)){
name = lastFriend.getUid();
}
//目前的好友请求都是别人发给我的
if(status==null || status== Config.STATUS_VERIFY_NONE||status ==Config.STATUS_VERIFY_READED){
return name+"请求添加好友";
}else{
return "我已添加"+name;
}
}else{
return "";
}
}
@Override
public long getLastMessageTime() {
if(lastFriend!=null){
return lastFriend.getTime();
}else{
return 0;
}
}
@Override
public Object getAvatar() {
return R.mipmap.new_friends_icon;
}
@Override
public int getUnReadCount() {
return NewFriendManager.getInstance(BmobIMApplication.INSTANCE()).getNewInvitationCount();
}
@Override
public void readAllMessages() {
//批量更新未读未认证的消息为已读状态
NewFriendManager.getInstance(BmobIMApplication.INSTANCE()).updateBatchStatus();
}
@Override
public void onClick(Context context) {
Intent intent = new Intent();
intent.setClass(context, NewFriendActivity.class);
context.startActivity(intent);
}
@Override
public void onLongClick(Context context) {
NewFriendManager.getInstance(context).deleteNewFriend(lastFriend);
}
}

@ -0,0 +1,117 @@
package cn.bmob.imdemo.bean;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import java.util.List;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.ui.ChatActivity;
import cn.bmob.imdemo.util.TimeUtil;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMConversationType;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMMessageType;
/**
*
* Created by Administrator on 2016/5/25.
*/
public class PrivateConversation extends Conversation{
private BmobIMConversation conversation;
private BmobIMMessage lastMsg;
public PrivateConversation(BmobIMConversation conversation){
this.conversation = conversation;
cType = BmobIMConversationType.setValue(conversation.getConversationType());
cId = conversation.getConversationId();
if (cType == BmobIMConversationType.PRIVATE){
cName=conversation.getConversationTitle();
if (TextUtils.isEmpty(cName)) cName = cId;
}else{
cName="未知会话";
}
List<BmobIMMessage> msgs =conversation.getMessages();
if(msgs!=null && msgs.size()>0){
lastMsg =msgs.get(0);
}
}
@Override
public void readAllMessages() {
conversation.updateLocalCache();
}
@Override
public Object getAvatar() {
if (cType == BmobIMConversationType.PRIVATE){
String avatar = conversation.getConversationIcon();
if (TextUtils.isEmpty(avatar)){//头像为空,使用默认头像
return R.mipmap.head;
}else{
return avatar;
}
}else{
return R.mipmap.head;
}
}
@Override
public String getLastMessageContent() {
if(lastMsg!=null){
String content =lastMsg.getContent();
if(lastMsg.getMsgType().equals(BmobIMMessageType.TEXT.getType()) || lastMsg.getMsgType().equals("agree")){
return content;
}else if(lastMsg.getMsgType().equals(BmobIMMessageType.IMAGE.getType())){
return "[图片]";
}else if(lastMsg.getMsgType().equals(BmobIMMessageType.VOICE.getType())){
return "[语音]";
}else if(lastMsg.getMsgType().equals(BmobIMMessageType.LOCATION.getType())){
return"[位置]";
}else if(lastMsg.getMsgType().equals(BmobIMMessageType.VIDEO.getType())){
return "[视频]";
}else{//开发者自定义的消息类型,需要自行处理
return "[未知]";
}
}else{//防止消息错乱
return "";
}
}
@Override
public long getLastMessageTime() {
if(lastMsg!=null) {
return lastMsg.getCreateTime();
}else{
return 0;
}
}
@Override
public int getUnReadCount() {
return (int)BmobIM.getInstance().getUnReadCount(conversation.getConversationId());
}
@Override
public void onClick(Context context) {
Intent intent = new Intent();
intent.setClass(context, ChatActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("c", conversation);
if (bundle != null) {
intent.putExtra(context.getPackageName(), bundle);
}
context.startActivity(intent);
}
@Override
public void onLongClick(Context context) {
//以下两种方式均可以删除会话
// BmobIM.getInstance().deleteConversation(conversation.getConversationId());
BmobIM.getInstance().deleteConversation(conversation);
}
}

@ -0,0 +1,30 @@
package cn.bmob.imdemo.bean;
import cn.bmob.imdemo.db.NewFriend;
import cn.bmob.v3.BmobUser;
/**
* @author :smile
* @project:User
* @date :2016-01-22-18:11
*/
public class User extends BmobUser {
private String avatar;
public User(){}
public User(NewFriend friend){
setObjectId(friend.getUid());
setUsername(friend.getName());
setAvatar(friend.getAvatar());
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
}

@ -0,0 +1,99 @@
package cn.bmob.imdemo.db;
// THIS CODE IS GENERATED BY greenDAO, EDIT ONLY INSIDE THE "KEEP"-SECTIONS
// KEEP INCLUDES - put your custom includes here
// KEEP INCLUDES END
/**
* Entity mapped to table "newfriend".
*/
public class NewFriend implements java.io.Serializable {
private Long id;
private String uid;
private String msg;
private String name;
private String avatar;
private Integer status;
private Long time;
// KEEP FIELDS - put your custom fields here
// KEEP FIELDS END
public NewFriend() {
}
public NewFriend(Long id) {
this.id = id;
}
public NewFriend(Long id, String uid, String msg, String name, String avatar, Integer status, Long time) {
this.id = id;
this.uid = uid;
this.msg = msg;
this.name = name;
this.avatar = avatar;
this.status = status;
this.time = time;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
// KEEP METHODS - put your custom methods here
// KEEP METHODS END
}

@ -0,0 +1,213 @@
package cn.bmob.imdemo.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.Log;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import cn.bmob.imdemo.Config;
import cn.bmob.imdemo.bean.AgreeAddFriendMessage;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.db.dao.DaoMaster;
import cn.bmob.imdemo.db.dao.DaoSession;
import cn.bmob.imdemo.db.dao.NewFriendDao;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMReceiveStatus;
import cn.bmob.newim.db.dao.MessageDao;
import cn.bmob.v3.BmobUser;
/**
* Created by Administrator on 2016/4/27.
*/
public class NewFriendManager {
private DaoMaster.DevOpenHelper openHelper;
Context mContecxt;
String uid=null;
private static HashMap<String, NewFriendManager> daoMap = new HashMap<>();
/**DB
* @param context
* @return
*/
public static NewFriendManager getInstance(Context context) {
User user = BmobUser.getCurrentUser(context, User.class);
String loginId=user.getObjectId();
if(TextUtils.isEmpty(loginId)){
throw new RuntimeException("you must login.");
}
NewFriendManager dao = daoMap.get(loginId);
if (dao == null) {
dao = new NewFriendManager(context,loginId);
daoMap.put(loginId, dao);
}
return dao;
}
private NewFriendManager(Context context, String uId){
clear();
this.mContecxt =context.getApplicationContext();
this.uid=uId;
String DBName = uId+".demodb";
this.openHelper = new DaoMaster.DevOpenHelper(mContecxt, DBName, null);
}
/**
*
*/
public void clear() {
if(openHelper !=null) {
openHelper.close();
openHelper = null;
mContecxt=null;
uid =null;
}
}
private DaoSession openReadableDb() {
checkInit();
SQLiteDatabase db = openHelper.getReadableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
DaoSession daoSession = daoMaster.newSession();
return daoSession;
}
private DaoSession openWritableDb(){
checkInit();
SQLiteDatabase db = openHelper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
DaoSession daoSession = daoMaster.newSession();
return daoSession;
}
private void checkInit(){
if(openHelper ==null){
throw new RuntimeException("请初始化db");
}
}
//-------------------------------------------------------------
/**
* @return
*/
public List<NewFriend> getAllNewFriend(){
NewFriendDao dao =openReadableDb().getNewFriendDao();
return dao.queryBuilder().orderDesc(NewFriendDao.Properties.Time).list();
}
/**
* @param info
* @return long:id
*/
public long insertOrUpdateNewFriend(NewFriend info){
NewFriendDao dao = openWritableDb().getNewFriendDao();
NewFriend local = getNewFriend(info.getUid(), info.getTime());
if(local==null){
return dao.insertOrReplace(info);
}else{
return -1;
}
}
/**
*
* @param uid
* @param time
* @return
*/
private NewFriend getNewFriend(String uid,Long time){
NewFriendDao dao = openReadableDb().getNewFriendDao();
return dao.queryBuilder().where(NewFriendDao.Properties.Uid.eq(uid))
.where(NewFriendDao.Properties.Time.eq(time)).build().unique();
}
/**
*
* @return
*/
public boolean hasNewFriendInvitation(){
List<NewFriend> infos =getNoVerifyNewFriend();
if(infos!=null && infos.size()>0){
return true;
}else{
return false;
}
}
/**
*
* @return
*/
public int getNewInvitationCount(){
List<NewFriend> infos =getNoVerifyNewFriend();
if(infos!=null && infos.size()>0){
return infos.size();
}else{
return 0;
}
}
/**
*
* @return
*/
private List<NewFriend> getNoVerifyNewFriend(){
NewFriendDao dao = openReadableDb().getNewFriendDao();
return dao.queryBuilder().where(NewFriendDao.Properties.Status.eq(Config.STATUS_VERIFY_NONE))
.build().list();
}
/**
*
*/
public void updateBatchStatus(){
List<NewFriend> infos =getNoVerifyNewFriend();
if(infos!=null && infos.size()>0){
int size =infos.size();
List<NewFriend> all =new ArrayList<>();
for (int i = 0; i < size; i++) {
NewFriend msg =infos.get(i);
msg.setStatus(Config.STATUS_VERIFY_READED);
all.add(msg);
}
insertBatchMessages(infos);
}
}
/**
* @param msgs
*/
public void insertBatchMessages(List<NewFriend> msgs){
NewFriendDao dao =openWritableDb().getNewFriendDao();
dao.insertOrReplaceInTx(msgs);
}
/**
*
* @param friend
* @param status
* @return
*/
public long updateNewFriend(NewFriend friend,int status){
NewFriendDao dao = openWritableDb().getNewFriendDao();
friend.setStatus(status);
return dao.insertOrReplace(friend);
}
/**
*
* @param friend
*/
public void deleteNewFriend(NewFriend friend){
NewFriendDao dao =openWritableDb().getNewFriendDao();
dao.delete(friend);
}
}

@ -0,0 +1,70 @@
package cn.bmob.imdemo.db.dao;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import de.greenrobot.dao.AbstractDaoMaster;
import de.greenrobot.dao.identityscope.IdentityScopeType;
import cn.bmob.imdemo.db.dao.NewFriendDao;
// 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(SQLiteDatabase db, boolean ifNotExists) {
NewFriendDao.createTable(db, ifNotExists);
}
/** Drops underlying database table using DAOs. */
public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
NewFriendDao.dropTable(db, ifExists);
}
public static abstract class OpenHelper extends SQLiteOpenHelper {
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
}
@Override
public void onCreate(SQLiteDatabase 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, CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
dropAllTables(db, true);
onCreate(db);
}
}
public DaoMaster(SQLiteDatabase db) {
super(db, SCHEMA_VERSION);
registerDaoClass(NewFriendDao.class);
}
public DaoSession newSession() {
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}
public DaoSession newSession(IdentityScopeType type) {
return new DaoSession(db, type, daoConfigMap);
}
}

@ -0,0 +1,49 @@
package cn.bmob.imdemo.db.dao;
import android.database.sqlite.SQLiteDatabase;
import java.util.Map;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.AbstractDaoSession;
import de.greenrobot.dao.identityscope.IdentityScopeType;
import de.greenrobot.dao.internal.DaoConfig;
import cn.bmob.imdemo.db.NewFriend;
import cn.bmob.imdemo.db.dao.NewFriendDao;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* {@inheritDoc}
*
* @see de.greenrobot.dao.AbstractDaoSession
*/
public class DaoSession extends AbstractDaoSession {
private final DaoConfig newFriendDaoConfig;
private final NewFriendDao newFriendDao;
public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
daoConfigMap) {
super(db);
newFriendDaoConfig = daoConfigMap.get(NewFriendDao.class).clone();
newFriendDaoConfig.initIdentityScope(type);
newFriendDao = new NewFriendDao(newFriendDaoConfig, this);
registerDao(NewFriend.class, newFriendDao);
}
public void clear() {
newFriendDaoConfig.getIdentityScope().clear();
}
public NewFriendDao getNewFriendDao() {
return newFriendDao;
}
}

@ -0,0 +1,160 @@
package cn.bmob.imdemo.db.dao;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.Property;
import de.greenrobot.dao.internal.DaoConfig;
import cn.bmob.imdemo.db.NewFriend;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* DAO for table "newfriend".
*/
public class NewFriendDao extends AbstractDao<NewFriend, Long> {
public static final String TABLENAME = "newfriend";
/**
* Properties of entity NewFriend.<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 Uid = new Property(1, String.class, "uid", false, "UID");
public final static Property Msg = new Property(2, String.class, "msg", false, "MSG");
public final static Property Name = new Property(3, String.class, "name", false, "NAME");
public final static Property Avatar = new Property(4, String.class, "avatar", false, "AVATAR");
public final static Property Status = new Property(5, Integer.class, "status", false, "STATUS");
public final static Property Time = new Property(6, Long.class, "time", false, "TIME");
};
public NewFriendDao(DaoConfig config) {
super(config);
}
public NewFriendDao(DaoConfig config, DaoSession daoSession) {
super(config, daoSession);
}
/** Creates the underlying database table. */
public static void createTable(SQLiteDatabase db, boolean ifNotExists) {
String constraint = ifNotExists? "IF NOT EXISTS ": "";
db.execSQL("CREATE TABLE " + constraint + "\"newfriend\" (" + //
"\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
"\"UID\" TEXT," + // 1: uid
"\"MSG\" TEXT," + // 2: msg
"\"NAME\" TEXT," + // 3: name
"\"AVATAR\" TEXT," + // 4: avatar
"\"STATUS\" INTEGER," + // 5: status
"\"TIME\" INTEGER);"); // 6: time
}
/** Drops the underlying database table. */
public static void dropTable(SQLiteDatabase db, boolean ifExists) {
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"newfriend\"";
db.execSQL(sql);
}
/** @inheritdoc */
@Override
protected void bindValues(SQLiteStatement stmt, NewFriend entity) {
stmt.clearBindings();
Long id = entity.getId();
if (id != null) {
stmt.bindLong(1, id);
}
String uid = entity.getUid();
if (uid != null) {
stmt.bindString(2, uid);
}
String msg = entity.getMsg();
if (msg != null) {
stmt.bindString(3, msg);
}
String name = entity.getName();
if (name != null) {
stmt.bindString(4, name);
}
String avatar = entity.getAvatar();
if (avatar != null) {
stmt.bindString(5, avatar);
}
Integer status = entity.getStatus();
if (status != null) {
stmt.bindLong(6, status);
}
Long time = entity.getTime();
if (time != null) {
stmt.bindLong(7, time);
}
}
/** @inheritdoc */
@Override
public Long readKey(Cursor cursor, int offset) {
return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
}
/** @inheritdoc */
@Override
public NewFriend readEntity(Cursor cursor, int offset) {
NewFriend entity = new NewFriend( //
cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // uid
cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // msg
cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // name
cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // avatar
cursor.isNull(offset + 5) ? null : cursor.getInt(offset + 5), // status
cursor.isNull(offset + 6) ? null : cursor.getLong(offset + 6) // time
);
return entity;
}
/** @inheritdoc */
@Override
public void readEntity(Cursor cursor, NewFriend entity, int offset) {
entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
entity.setUid(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
entity.setMsg(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
entity.setName(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
entity.setAvatar(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
entity.setStatus(cursor.isNull(offset + 5) ? null : cursor.getInt(offset + 5));
entity.setTime(cursor.isNull(offset + 6) ? null : cursor.getLong(offset + 6));
}
/** @inheritdoc */
@Override
protected Long updateKeyAfterInsert(NewFriend entity, long rowId) {
entity.setId(rowId);
return rowId;
}
/** @inheritdoc */
@Override
public Long getKey(NewFriend entity) {
if(entity != null) {
return entity.getId();
} else {
return null;
}
}
/** @inheritdoc */
@Override
protected boolean isEntityUpdateable() {
return true;
}
}

@ -0,0 +1,11 @@
package cn.bmob.imdemo.event;
/**
* @author :smile
* @project:FinishEvent
* @date :2016-01-25-15:25
*/
public class FinishEvent {
public FinishEvent(){}
}

@ -0,0 +1,8 @@
package cn.bmob.imdemo.event;
/**
* Created by Administrator on 2016/4/28.
*/
public class RefreshEvent {
public RefreshEvent(){}
}

@ -0,0 +1,22 @@
package cn.bmob.imdemo.model;
import android.content.Context;
import cn.bmob.imdemo.BmobIMApplication;
/**
* @author :smile
* @project:BaseModel
* @date :2016-01-23-10:37
*/
public abstract class BaseModel {
public int CODE_NULL=1000;
public static int CODE_NOT_EQUAL=1001;
public static final int DEFAULT_LIMIT=20;
public Context getContext(){
return BmobIMApplication.INSTANCE();
}
}

@ -0,0 +1,268 @@
package cn.bmob.imdemo.model;
import android.text.TextUtils;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
import java.util.List;
import cn.bmob.imdemo.bean.Friend;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.db.NewFriend;
import cn.bmob.imdemo.model.i.QueryUserListener;
import cn.bmob.imdemo.model.i.UpdateCacheListener;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.event.MessageEvent;
import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.DeleteListener;
import cn.bmob.v3.listener.FindListener;
import cn.bmob.v3.listener.LogInListener;
import cn.bmob.v3.listener.SaveListener;
/**
* @author :smile
* @project:UserModel
* @date :2016-01-22-18:09
*/
public class UserModel extends BaseModel {
private static UserModel ourInstance = new UserModel();
public static UserModel getInstance() {
return ourInstance;
}
private UserModel() {}
/**
* @param username
* @param password
* @param listener
*/
public void login(String username, String password, final LogInListener listener) {
if(TextUtils.isEmpty(username)){
listener.internalDone(new BmobException(CODE_NULL, "请填写用户名"));
return;
}
if(TextUtils.isEmpty(password)){
listener.internalDone(new BmobException(CODE_NULL, "请填写密码"));
return;
}
final User user =new User();
user.setUsername(username);
user.setPassword(password);
user.login(getContext(), new SaveListener() {
@Override
public void onSuccess() {
listener.done(getCurrentUser(), null);
}
@Override
public void onFailure(int i, String s) {
listener.done(user, new BmobException(i, s));
}
});
}
/**
* 退
*/
public void logout(){
BmobUser.logOut(getContext());
}
public User getCurrentUser(){
return BmobUser.getCurrentUser(getContext(), User.class);
}
/**
* @param username
* @param password
* @param pwdagain
* @param listener
*/
public void register(String username,String password, String pwdagain, final LogInListener listener) {
if(TextUtils.isEmpty(username)){
listener.internalDone(new BmobException(CODE_NULL, "请填写用户名"));
return;
}
if(TextUtils.isEmpty(password)){
listener.internalDone(new BmobException(CODE_NULL, "请填写密码"));
return;
}
if(TextUtils.isEmpty(pwdagain)){
listener.internalDone(new BmobException(CODE_NULL, "请填写确认密码"));
return;
}
if(!password.equals(pwdagain)){
listener.internalDone(new BmobException(CODE_NOT_EQUAL, "两次输入的密码不一致,请重新输入"));
return;
}
final User user = new User();
user.setUsername(username);
user.setPassword(password);
user.signUp(getContext(), new SaveListener() {
@Override
public void onSuccess() {
listener.done(null, null);
}
@Override
public void onFailure(int i, String s) {
listener.done(null, new BmobException(i, s));
}
});
}
/**
* @param username
* @param limit
* @param listener
*/
public void queryUsers(String username,int limit,final FindListener<User> listener){
BmobQuery<User> query = new BmobQuery<>();
//去掉当前用户
try {
BmobUser user = BmobUser.getCurrentUser(getContext());
query.addWhereNotEqualTo("username",user.getUsername());
} catch (Exception e) {
e.printStackTrace();
}
query.addWhereContains("username", username);
query.setLimit(limit);
query.order("-createdAt");
query.findObjects(getContext(), new FindListener<User>() {
@Override
public void onSuccess(List<User> list) {
if (list != null && list.size() > 0) {
listener.onSuccess(list);
} else {
listener.onError(CODE_NULL, "查无此人");
}
}
@Override
public void onError(int i, String s) {
listener.onError(i, s);
}
});
}
/**
* @param objectId
* @param listener
*/
public void queryUserInfo(String objectId, final QueryUserListener listener){
BmobQuery<User> query = new BmobQuery<>();
query.addWhereEqualTo("objectId", objectId);
query.findObjects(getContext(), new FindListener<User>() {
@Override
public void onSuccess(List<User> list) {
if(list!=null && list.size()>0){
listener.internalDone(list.get(0), null);
}else{
listener.internalDone(new BmobException(000, "查无此人"));
}
}
@Override
public void onError(int i, String s) {
listener.internalDone(new BmobException(i, s));
}
});
}
/**
* @param event
* @param listener
*/
public void updateUserInfo(MessageEvent event,final UpdateCacheListener listener){
final BmobIMConversation conversation=event.getConversation();
final BmobIMUserInfo info =event.getFromUserInfo();
final BmobIMMessage msg =event.getMessage();
String username =info.getName();
String title =conversation.getConversationTitle();
Logger.i("" + username + "," + title);
//sdk内部将新会话的会话标题用objectId表示因此需要比对用户名和会话标题--单聊,后续会根据会话类型进行判断
if(!username.equals(title)) {
UserModel.getInstance().queryUserInfo(info.getUserId(), new QueryUserListener() {
@Override
public void done(User s, BmobException e) {
if(e==null){
String name =s.getUsername();
String avatar = s.getAvatar();
Logger.i("query success"+name+","+avatar);
conversation.setConversationIcon(avatar);
conversation.setConversationTitle(name);
info.setName(name);
info.setAvatar(avatar);
//更新用户资料
BmobIM.getInstance().updateUserInfo(info);
//更新会话资料-如果消息是暂态消息,则不更新会话资料
if(!msg.isTransient()){
BmobIM.getInstance().updateConversation(conversation);
}
}else{
Logger.e(e);
}
listener.done(null);
}
});
}else{
listener.internalDone(null);
}
}
/**
* 12
*/
public void agreeAddFriend(User friend,SaveListener listener){
Friend f = new Friend();
User user =BmobUser.getCurrentUser(getContext(), User.class);
f.setUser(user);
f.setFriendUser(friend);
f.save(getContext(),listener);
}
/**
*
* @param listener
*/
public void queryFriends(final FindListener<Friend> listener){
BmobQuery<Friend> query = new BmobQuery<>();
User user =BmobUser.getCurrentUser(getContext(), User.class);
query.addWhereEqualTo("user", user);
query.include("friendUser");
query.order("-updatedAt");
query.findObjects(getContext(), new FindListener<Friend>() {
@Override
public void onSuccess(List<Friend> list) {
if (list != null && list.size() > 0) {
listener.onSuccess(list);
} else {
listener.onError(0, "暂无联系人");
}
}
@Override
public void onError(int i, String s) {
listener.onError(i, s);
}
});
}
/**
*
* @param f
* @param listener
*/
public void deleteFriend(Friend f,DeleteListener listener){
Friend friend =new Friend();
friend.delete(getContext(),f.getObjectId(),listener);
}
}

@ -0,0 +1,20 @@
package cn.bmob.imdemo.model.i;
import cn.bmob.imdemo.bean.User;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.BmobListener;
/**
* @author :smile
* @project:QueryUserListener
* @date :2016-02-01-16:23
*/
public abstract class QueryUserListener extends BmobListener<User> {
public abstract void done(User s, BmobException e);
@Override
protected void postDone(User o, BmobException e) {
done(o, e);
}
}

@ -0,0 +1,18 @@
package cn.bmob.imdemo.model.i;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.BmobListener;
/**
* @author :smile
* @project:UpdateCacheListener
* @date :2016-02-01-16:23
*/
public abstract class UpdateCacheListener extends BmobListener {
public abstract void done(BmobException e);
@Override
protected void postDone(Object o, BmobException e) {
done(e);
}
}

@ -0,0 +1,700 @@
package cn.bmob.imdemo.ui;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.orhanobut.logger.Logger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import butterknife.Bind;
import butterknife.OnClick;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.ChatAdapter;
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
import cn.bmob.imdemo.base.ParentWithNaviActivity;
import cn.bmob.imdemo.util.Util;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.bean.BmobIMAudioMessage;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMImageMessage;
import cn.bmob.newim.bean.BmobIMLocationMessage;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMTextMessage;
import cn.bmob.newim.bean.BmobIMVideoMessage;
import cn.bmob.newim.core.BmobIMClient;
import cn.bmob.newim.core.BmobRecordManager;
import cn.bmob.newim.event.MessageEvent;
import cn.bmob.newim.listener.MessageListHandler;
import cn.bmob.newim.listener.MessageSendListener;
import cn.bmob.newim.listener.MessagesQueryListener;
import cn.bmob.newim.listener.ObseverListener;
import cn.bmob.newim.listener.OnRecordChangeListener;
import cn.bmob.newim.notification.BmobNotificationManager;
import cn.bmob.v3.exception.BmobException;
/**
* @author :smile
* @project:ChatActivity
* @date :2016-01-25-18:23
*/
public class ChatActivity extends ParentWithNaviActivity implements ObseverListener,MessageListHandler{
@Bind(R.id.ll_chat)
LinearLayout ll_chat;
@Bind(R.id.sw_refresh)
SwipeRefreshLayout sw_refresh;
@Bind(R.id.rc_view)
RecyclerView rc_view;
@Bind(R.id.edit_msg)
EditText edit_msg;
@Bind(R.id.btn_chat_add)
Button btn_chat_add;
@Bind(R.id.btn_chat_emo)
Button btn_chat_emo;
@Bind(R.id.btn_speak)
Button btn_speak;
@Bind(R.id.btn_chat_voice)
Button btn_chat_voice;
@Bind(R.id.btn_chat_keyboard)
Button btn_chat_keyboard;
@Bind(R.id.btn_chat_send)
Button btn_chat_send;
@Bind(R.id.layout_more)
LinearLayout layout_more;
@Bind(R.id.layout_add)
LinearLayout layout_add;
@Bind(R.id.layout_emo)
LinearLayout layout_emo;
// 语音有关
@Bind(R.id.layout_record)
RelativeLayout layout_record;
@Bind(R.id.tv_voice_tips)
TextView tv_voice_tips;
@Bind(R.id.iv_record)
ImageView iv_record;
private Drawable[] drawable_Anims;// 话筒动画
BmobRecordManager recordManager;
ChatAdapter adapter;
protected LinearLayoutManager layoutManager;
BmobIMConversation c;
@Override
protected String title() {
return c.getConversationTitle();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
c= BmobIMConversation.obtain(BmobIMClient.getInstance(), (BmobIMConversation) getBundle().getSerializable("c"));
initNaviView();
initSwipeLayout();
initVoiceView();
initBottomView();
}
private void initSwipeLayout(){
sw_refresh.setEnabled(true);
layoutManager = new LinearLayoutManager(this);
rc_view.setLayoutManager(layoutManager);
adapter = new ChatAdapter(this,c);
rc_view.setAdapter(adapter);
ll_chat.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
ll_chat.getViewTreeObserver().removeGlobalOnLayoutListener(this);
sw_refresh.setRefreshing(true);
//自动刷新
queryMessages(null);
}
});
//下拉加载
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
BmobIMMessage msg = adapter.getFirstMessage();
queryMessages(msg);
}
});
//设置RecyclerView的点击事件
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
@Override
public void onItemClick(int position) {
Logger.i(""+position);
}
@Override
public boolean onItemLongClick(int position) {
//这里省了个懒,直接长按就删除了该消息
c.deleteMessage(adapter.getItem(position));
adapter.remove(position);
return true;
}
});
}
private void initBottomView(){
edit_msg.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN||event.getAction()==MotionEvent.ACTION_UP){
scrollToBottom();
}
return false;
}
});
edit_msg.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
scrollToBottom();
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!TextUtils.isEmpty(s)) {
btn_chat_send.setVisibility(View.VISIBLE);
btn_chat_keyboard.setVisibility(View.GONE);
btn_chat_voice.setVisibility(View.GONE);
} else {
if (btn_chat_voice.getVisibility() != View.VISIBLE) {
btn_chat_voice.setVisibility(View.VISIBLE);
btn_chat_send.setVisibility(View.GONE);
btn_chat_keyboard.setVisibility(View.GONE);
}
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
/**
*
* @param
* @return void
*/
private void initVoiceView() {
btn_speak.setOnTouchListener(new VoiceTouchListener());
initVoiceAnimRes();
initRecordManager();
}
/**
*
* @Title: initVoiceAnimRes
* @param
* @return void
*/
private void initVoiceAnimRes() {
drawable_Anims = new Drawable[] {
getResources().getDrawable(R.mipmap.chat_icon_voice2),
getResources().getDrawable(R.mipmap.chat_icon_voice3),
getResources().getDrawable(R.mipmap.chat_icon_voice4),
getResources().getDrawable(R.mipmap.chat_icon_voice5),
getResources().getDrawable(R.mipmap.chat_icon_voice6) };
}
private void initRecordManager(){
// 语音相关管理器
recordManager = BmobRecordManager.getInstance(this);
// 设置音量大小监听--在这里开发者可以自己实现当剩余10秒情况下的给用户的提示类似微信的语音那样
recordManager.setOnRecordChangeListener(new OnRecordChangeListener() {
@Override
public void onVolumnChanged(int value) {
iv_record.setImageDrawable(drawable_Anims[value]);
}
@Override
public void onTimeChanged(int recordTime, String localPath) {
Logger.i("voice", "已录音长度:" + recordTime);
if (recordTime >= BmobRecordManager.MAX_RECORD_TIME) {// 1分钟结束发送消息
// 需要重置按钮
btn_speak.setPressed(false);
btn_speak.setClickable(false);
// 取消录音框
layout_record.setVisibility(View.INVISIBLE);
// 发送语音消息
sendVoiceMessage(localPath, recordTime);
//是为了防止过了录音时间后,会多发一条语音出去的情况。
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
btn_speak.setClickable(true);
}
}, 1000);
}
}
});
}
/**
*
* @author smile
* @date 2014-7-1 6:10:16
*/
class VoiceTouchListener implements View.OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!Util.checkSdCard()) {
toast("发送语音需要sdcard支持");
return false;
}
try {
v.setPressed(true);
layout_record.setVisibility(View.VISIBLE);
tv_voice_tips.setText(getString(R.string.voice_cancel_tips));
// 开始录音
recordManager.startRecording(c.getConversationId());
} catch (Exception e) {
e.printStackTrace();
}
return true;
case MotionEvent.ACTION_MOVE: {
if (event.getY() < 0) {
tv_voice_tips.setText(getString(R.string.voice_cancel_tips));
tv_voice_tips.setTextColor(Color.RED);
} else {
tv_voice_tips.setText(getString(R.string.voice_up_tips));
tv_voice_tips.setTextColor(Color.WHITE);
}
return true;
}
case MotionEvent.ACTION_UP:
v.setPressed(false);
layout_record.setVisibility(View.INVISIBLE);
try {
if (event.getY() < 0) {// 放弃录音
recordManager.cancelRecording();
Logger.i("voice", "放弃发送语音");
} else {
int recordTime = recordManager.stopRecording();
if (recordTime > 1) {
// 发送语音文件
sendVoiceMessage(recordManager.getRecordFilePath(c.getConversationId()),recordTime);
} else {// 录音时间过短,则提示录音过短的提示
layout_record.setVisibility(View.GONE);
showShortToast().show();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
default:
return false;
}
}
}
Toast toast;
/**
* Toast
* @Title: showShortToast
* @return void
*/
private Toast showShortToast() {
if (toast == null) {
toast = new Toast(this);
}
View view = LayoutInflater.from(this).inflate(
R.layout.include_chat_voice_short, null);
toast.setView(view);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.setDuration(Toast.LENGTH_SHORT);
return toast;
}
@OnClick(R.id.edit_msg)
public void onEditClick(View view){
if (layout_more.getVisibility() == View.VISIBLE) {
layout_add.setVisibility(View.GONE);
layout_emo.setVisibility(View.GONE);
layout_more.setVisibility(View.GONE);
}
}
@OnClick(R.id.btn_chat_emo)
public void onEmoClick(View view){
if (layout_more.getVisibility() == View.GONE) {
showEditState(true);
} else {
if (layout_add.getVisibility() == View.VISIBLE) {
layout_add.setVisibility(View.GONE);
layout_emo.setVisibility(View.VISIBLE);
} else {
layout_more.setVisibility(View.GONE);
}
}
}
@OnClick(R.id.btn_chat_add)
public void onAddClick(View view){
if (layout_more.getVisibility() == View.GONE) {
layout_more.setVisibility(View.VISIBLE);
layout_add.setVisibility(View.VISIBLE);
layout_emo.setVisibility(View.GONE);
hideSoftInputView();
} else {
if (layout_emo.getVisibility() == View.VISIBLE) {
layout_emo.setVisibility(View.GONE);
layout_add.setVisibility(View.VISIBLE);
} else {
layout_more.setVisibility(View.GONE);
}
}
}
@OnClick(R.id.btn_chat_voice)
public void onVoiceClick(View view){
edit_msg.setVisibility(View.GONE);
layout_more.setVisibility(View.GONE);
btn_chat_voice.setVisibility(View.GONE);
btn_chat_keyboard.setVisibility(View.VISIBLE);
btn_speak.setVisibility(View.VISIBLE);
hideSoftInputView();
}
@OnClick(R.id.btn_chat_keyboard)
public void onKeyClick(View view){
showEditState(false);
}
@OnClick(R.id.btn_chat_send)
public void onSendClick(View view){
sendMessage();
}
@OnClick(R.id.tv_picture)
public void onPictureClick(View view){
// sendLocalImageMessage();
// sendOtherMessage();
sendVideoMessage();
}
@OnClick(R.id.tv_camera)
public void onCameraClick(View view){
sendRemoteImageMessage();
}
@OnClick(R.id.tv_location)
public void onLocationClick(View view){
sendLocationMessage();
}
/**
*
* @param isEmo
* @return void
*/
private void showEditState(boolean isEmo) {
edit_msg.setVisibility(View.VISIBLE);
btn_chat_keyboard.setVisibility(View.GONE);
btn_chat_voice.setVisibility(View.VISIBLE);
btn_speak.setVisibility(View.GONE);
edit_msg.requestFocus();
if (isEmo) {
layout_more.setVisibility(View.VISIBLE);
layout_more.setVisibility(View.VISIBLE);
layout_emo.setVisibility(View.VISIBLE);
layout_add.setVisibility(View.GONE);
hideSoftInputView();
} else {
layout_more.setVisibility(View.GONE);
showSoftInputView();
}
}
/**
*
*/
public void showSoftInputView() {
if (getWindow().getAttributes().softInputMode == WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
if (getCurrentFocus() != null)
((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
.showSoftInput(edit_msg, 0);
}
}
/**
*
*/
private void sendMessage(){
String text=edit_msg.getText().toString();
if(TextUtils.isEmpty(text.trim())){
toast("请输入内容");
return;
}
BmobIMTextMessage msg =new BmobIMTextMessage();
msg.setContent(text);
//可设置额外信息
Map<String,Object> map =new HashMap<>();
map.put("level", "1");//随意增加信息
msg.setExtraMap(map);
c.sendMessage(msg, listener);
}
/**
*
*/
public void sendRemoteImageMessage(){
BmobIMImageMessage image =new BmobIMImageMessage();
image.setRemoteUrl("http://img.lakalaec.com/ad/57ab6dc2-43f2-4087-81e2-b5ab5681642d.jpg");
c.sendMessage(image, listener);
}
/**
*
*/
public void sendLocalImageMessage(){
//正常情况下,需要调用系统的图库或拍照功能获取到图片的本地地址,开发者只需要将本地的文件地址传过去就可以发送文件类型的消息
BmobIMImageMessage image =new BmobIMImageMessage("/storage/emulated/0/bimagechooser/IMG_20160302_172003.jpg");
c.sendMessage(image, listener);
// //因此也可以使用BmobIMFileMessage来发送文件消息
// BmobIMFileMessage file =new BmobIMFileMessage("文件地址");
// c.sendMessage(file,listener);
}
/**
*
* @Title: sendVoiceMessage
* @param local
* @param length
* @return void
*/
private void sendVoiceMessage(String local, int length) {
BmobIMAudioMessage audio =new BmobIMAudioMessage(local);
//可设置额外信息-开发者设置的额外信息需要开发者自己从extra中取出来
Map<String,Object> map =new HashMap<>();
map.put("from", "优酷");
audio.setExtraMap(map);
//设置语音文件时长:可选
// audio.setDuration(length);
c.sendMessage(audio, listener);
}
/**
*
*/
private void sendVideoMessage(){
BmobIMVideoMessage video =new BmobIMVideoMessage("/storage/sdcard0/bimagechooser/11.png");
c.sendMessage(video, listener);
}
/**
*
*/
public void sendLocationMessage(){
//测试数据真实数据需要从地图SDK中获取
BmobIMLocationMessage location =new BmobIMLocationMessage("广州番禺区",23.5,112.0);
Map<String,Object> map =new HashMap<>();
map.put("from", "百度地图");
location.setExtraMap(map);
c.sendMessage(location, listener);
}
/**
*
*/
public MessageSendListener listener =new MessageSendListener() {
@Override
public void onProgress(int value) {
super.onProgress(value);
//文件类型的消息才有进度值
Logger.i("onProgress"+value);
}
@Override
public void onStart(BmobIMMessage msg) {
super.onStart(msg);
adapter.addMessage(msg);
edit_msg.setText("");
scrollToBottom();
}
@Override
public void done(BmobIMMessage msg, BmobException e) {
adapter.notifyDataSetChanged();
edit_msg.setText("");
scrollToBottom();
if (e != null) {
toast(e.getMessage());
}
}
};
/**msgnullmsg
* @param msg
*/
public void queryMessages(BmobIMMessage msg){
c.queryMessages(msg, 10, new MessagesQueryListener() {
@Override
public void done(List<BmobIMMessage> list, BmobException e) {
sw_refresh.setRefreshing(false);
if (e == null) {
if (null != list && list.size() > 0) {
adapter.addMessages(list);
layoutManager.scrollToPositionWithOffset(list.size() - 1, 0);
}
} else {
toast(e.getMessage() + "(" + e.getErrorCode() + ")");
}
}
});
}
private void scrollToBottom() {
layoutManager.scrollToPositionWithOffset(adapter.getItemCount() - 1, 0);
}
@Override
public void onMessageReceive(List<MessageEvent> list) {
Logger.i("聊天页面接收到消息:" + list.size());
//当注册页面消息监听时候,有消息(包含离线消息)到来时会回调该方法
for (int i=0;i<list.size();i++){
addMessage2Chat(list.get(i));
}
}
// /**接收到聊天消息
// * @param event
// */
// @Subscribe
// public void onEventMainThread(MessageEvent event){
// addMessage2Chat(event);
// }
//
// @Subscribe
// public void onEventMainThread(OfflineMessageEvent event){
// Map<String,List<MessageEvent>> map =event.getEventMap();
// if(map!=null&&map.size()>0){
// //只获取当前聊天对象的离线消息
// List<MessageEvent> list = map.get(c.getConversationId());
// if(list!=null && list.size()>0){
// for (int i=0;i<list.size();i++){
// addMessage2Chat(list.get(i));
// }
// }
// }
// }
/**
* @param event
*/
private void addMessage2Chat(MessageEvent event){
BmobIMMessage msg =event.getMessage();
if(c!=null && event!=null && c.getConversationId().equals(event.getConversation().getConversationId()) //如果是当前会话的消息
&& !msg.isTransient()){//并且不为暂态消息
if(adapter.findPosition(msg)<0){//如果未添加到界面中
adapter.addMessage(msg);
//更新该会话下面的已读状态
c.updateReceiveStatus(msg);
}
scrollToBottom();
}else{
Logger.i("不是与当前聊天对象的消息");
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (layout_more.getVisibility() == View.VISIBLE) {
layout_more.setVisibility(View.GONE);
return false;
} else {
return super.onKeyDown(keyCode, event);
}
} else {
return super.onKeyDown(keyCode, event);
}
}
@Override
protected void onResume() {
//锁屏期间的收到的未读消息需要添加到聊天界面中
addUnReadMessage();
//添加页面消息监听器
BmobIM.getInstance().addMessageListHandler(this);
// 有可能锁屏期间,在聊天界面出现通知栏,这时候需要清除通知
BmobNotificationManager.getInstance(this).cancelNotification();
super.onResume();
}
/**
*
*/
private void addUnReadMessage(){
List<MessageEvent> cache = BmobNotificationManager.getInstance(this).getNotificationCacheList();
if(cache.size()>0){
int size =cache.size();
for(int i=0;i<size;i++){
MessageEvent event = cache.get(i);
addMessage2Chat(event);
}
}
scrollToBottom();
}
@Override
protected void onPause() {
//移除页面消息监听器
BmobIM.getInstance().removeMessageListHandler(this);
super.onPause();
}
@Override
protected void onDestroy() {
//清理资源
if(recordManager!=null){
recordManager.clear();
}
//更新此会话的所有消息为已读状态
if(c!=null){
c.updateLocalCache();
}
hideSoftInputView();
super.onDestroy();
}
}

@ -0,0 +1,71 @@
package cn.bmob.imdemo.ui;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.greenrobot.eventbus.Subscribe;
import butterknife.Bind;
import butterknife.OnClick;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.base.BaseActivity;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.event.FinishEvent;
import cn.bmob.imdemo.model.UserModel;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.LogInListener;
/**
* @author :smile
* @project:LoginActivity
* @date :2016-01-15-18:23
*/
public class LoginActivity extends BaseActivity {
@Bind(R.id.et_username)
EditText et_username;
@Bind(R.id.et_password)
EditText et_password;
@Bind(R.id.btn_login)
Button btn_login;
@Bind(R.id.tv_register)
TextView tv_register;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
}
@OnClick(R.id.btn_login)
public void onLoginClick(View view){
UserModel.getInstance().login(et_username.getText().toString(), et_password.getText().toString(), new LogInListener() {
@Override
public void done(Object o, BmobException e) {
if (e == null) {
User user =(User)o;
BmobIM.getInstance().updateUserInfo(new BmobIMUserInfo(user.getObjectId(), user.getUsername(), user.getAvatar()));
startActivity(MainActivity.class, null, true);
} else {
toast(e.getMessage() + "(" + e.getErrorCode() + ")");
}
}
});
}
@OnClick(R.id.tv_register)
public void onRegisterClick(View view){
startActivity(RegisterActivity.class, null, false);
}
@Subscribe
public void onEventMainThread(FinishEvent event){
finish();
}
}

@ -0,0 +1,204 @@
package cn.bmob.imdemo.ui;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import com.orhanobut.logger.Logger;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.base.BaseActivity;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.db.NewFriendManager;
import cn.bmob.imdemo.event.RefreshEvent;
import cn.bmob.imdemo.ui.fragment.ContactFragment;
import cn.bmob.imdemo.ui.fragment.ConversationFragment;
import cn.bmob.imdemo.ui.fragment.SetFragment;
import cn.bmob.imdemo.util.IMMLeaks;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.core.ConnectionStatus;
import cn.bmob.newim.event.MessageEvent;
import cn.bmob.newim.event.OfflineMessageEvent;
import cn.bmob.newim.listener.ConnectListener;
import cn.bmob.newim.listener.ConnectStatusChangeListener;
import cn.bmob.newim.listener.ObseverListener;
import cn.bmob.newim.notification.BmobNotificationManager;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
/**
* @author :smile
* @project:MainActivity
* @date :2016-01-15-18:23
*/
public class MainActivity extends BaseActivity implements ObseverListener{
/*@Bind(R.id.btn_conversation)
Button btn_conversation;*/
@Bind(R.id.btn_set)
Button btn_set;
@Bind(R.id.btn_contact)
Button btn_contact;
/* @Bind(R.id.iv_conversation_tips)
ImageView iv_conversation_tips;*/
@Bind(R.id.iv_contact_tips)
ImageView iv_contact_tips;
private Button[] mTabs;
private ConversationFragment conversationFragment;
private SetFragment setFragment;
ContactFragment contactFragment;
private Fragment[] fragments;
private int index;
private int currentTabIndex;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//connect server
User user = BmobUser.getCurrentUser(this,User.class);
BmobIM.connect(user.getObjectId(), new ConnectListener() {
@Override
public void done(String uid, BmobException e) {
if (e == null) {
Logger.i("connect success");
//服务器连接成功就发送一个更新事件,同步更新会话及主页的小红点
EventBus.getDefault().post(new RefreshEvent());
} else {
Logger.e(e.getErrorCode() + "/" + e.getMessage());
}
}
});
//监听连接状态也可通过BmobIM.getInstance().getCurrentStatus()来获取当前的长连接状态
BmobIM.getInstance().setOnConnectStatusChangeListener(new ConnectStatusChangeListener() {
@Override
public void onChange(ConnectionStatus status) {
toast("" + status.getMsg());
}
});
//解决leancanary提示InputMethodManager内存泄露的问题
IMMLeaks.fixFocusedViewLeak(getApplication());
}
@Override
protected void initView() {
super.initView();
mTabs = new Button[2];
/*mTabs[0] = btn_conversation;*/
mTabs[0] = btn_contact;
mTabs[1] =btn_set;
mTabs[0].setSelected(true);
initTab();
}
private void initTab(){
//conversationFragment = new ConversationFragment();
setFragment = new SetFragment();
contactFragment=new ContactFragment();
fragments = new Fragment[] {contactFragment,setFragment};
//.add(R.id.fragment_container, conversationFragment)
//
//.show(conversationFragment)
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, contactFragment)
.add(R.id.fragment_container, setFragment)
.hide(setFragment)
.show(contactFragment)
.commit();
}
public void onTabSelect(View view) {
switch (view.getId()) {
case R.id.btn_contact:
index = 0;
break;
case R.id.btn_set:
index = 1;
break;
}
onTabIndex(index);
}
private void onTabIndex(int index){
if (currentTabIndex != index) {
FragmentTransaction trx = getSupportFragmentManager().beginTransaction();
trx.hide(fragments[currentTabIndex]);
if (!fragments[index].isAdded()) {
trx.add(R.id.fragment_container, fragments[index]);
}
trx.show(fragments[index]).commit();
}
mTabs[currentTabIndex].setSelected(false);
mTabs[index].setSelected(true);
currentTabIndex = index;
}
@Override
protected void onResume() {
super.onResume();
//显示小红点
checkRedPoint();
//进入应用后,通知栏应取消
BmobNotificationManager.getInstance(this).cancelNotification();
}
@Override
protected void onDestroy() {
super.onDestroy();
//清理导致内存泄露的资源
BmobIM.getInstance().clear();
}
/**
* @param event
*/
@Subscribe
public void onEventMainThread(MessageEvent event){
checkRedPoint();
}
/**线
* @param event
*/
@Subscribe
public void onEventMainThread(OfflineMessageEvent event){
checkRedPoint();
}
/**
* @param event
*/
@Subscribe
public void onEventMainThread(RefreshEvent event){
log("---主页接收到自定义消息---");
checkRedPoint();
}
private void checkRedPoint(){
int count = (int)BmobIM.getInstance().getAllUnReadCount();
/*if(count>0){
iv_conversation_tips.setVisibility(View.VISIBLE);
}else{
iv_conversation_tips.setVisibility(View.GONE);
}*/
//是否有好友添加的请求
if(NewFriendManager.getInstance(this).hasNewFriendInvitation()){
iv_contact_tips.setVisibility(View.VISIBLE);
}else{
iv_contact_tips.setVisibility(View.GONE);
}
}
}

@ -0,0 +1,148 @@
package cn.bmob.imdemo.ui;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.ViewTreeObserver;
import android.widget.LinearLayout;
import java.util.List;
import butterknife.Bind;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.ConversationAdapter;
import cn.bmob.imdemo.adapter.NewFriendAdapter;
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
import cn.bmob.imdemo.base.ParentWithNaviActivity;
import cn.bmob.imdemo.bean.Conversation;
import cn.bmob.imdemo.db.NewFriend;
import cn.bmob.imdemo.db.NewFriendManager;
/**
* @author :smile
* @project:NewFriendActivity
* @date :2016-01-25-18:23
*/
public class NewFriendActivity extends ParentWithNaviActivity {
@Bind(R.id.ll_root)
LinearLayout ll_root;
@Bind(R.id.rc_view)
RecyclerView rc_view;
@Bind(R.id.sw_refresh)
SwipeRefreshLayout sw_refresh;
NewFriendAdapter adapter;
LinearLayoutManager layoutManager;
@Override
protected String title() {
return "新朋友";
}
@Override
public Object right() {
return R.drawable.base_action_bar_add_bg_selector;
}
@Override
public ParentWithNaviActivity.ToolBarListener setToolBarListener() {
return new ParentWithNaviActivity.ToolBarListener() {
@Override
public void clickLeft() {
finish();
}
@Override
public void clickRight() {
startActivity(SearchUserActivity.class,null);
}
};
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_conversation);
initNaviView();
//单一布局
IMutlipleItem<NewFriend> mutlipleItem = new IMutlipleItem<NewFriend>() {
@Override
public int getItemViewType(int postion, NewFriend c) {
return 0;
}
@Override
public int getItemLayoutId(int viewtype) {
return R.layout.item_new_friend;
}
@Override
public int getItemCount(List<NewFriend> list) {
return list.size();
}
};
adapter = new NewFriendAdapter(this,mutlipleItem,null);
rc_view.setAdapter(adapter);
layoutManager = new LinearLayoutManager(this);
rc_view.setLayoutManager(layoutManager);
sw_refresh.setEnabled(true);
//批量更新未读未认证的消息为已读状态
NewFriendManager.getInstance(this).updateBatchStatus();
setListener();
}
private void setListener(){
ll_root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
ll_root.getViewTreeObserver().removeGlobalOnLayoutListener(this);
sw_refresh.setRefreshing(true);
query();
}
});
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
query();
}
});
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
@Override
public void onItemClick(int position) {
log("点击:"+position);
}
@Override
public boolean onItemLongClick(int position) {
NewFriendManager.getInstance(NewFriendActivity.this).deleteNewFriend(adapter.getItem(position));
adapter.remove(position);
return true;
}
});
}
@Override
public void onResume() {
super.onResume();
sw_refresh.setRefreshing(true);
query();
}
@Override
public void onPause() {
super.onPause();
}
/**
*/
public void query(){
adapter.bindDatas(NewFriendManager.getInstance(this).getAllNewFriend());
adapter.notifyDataSetChanged();
sw_refresh.setRefreshing(false);
}
}

@ -0,0 +1,67 @@
package cn.bmob.imdemo.ui;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import org.greenrobot.eventbus.EventBus;
import butterknife.Bind;
import butterknife.OnClick;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.base.ParentWithNaviActivity;
import cn.bmob.imdemo.event.FinishEvent;
import cn.bmob.imdemo.model.BaseModel;
import cn.bmob.imdemo.model.UserModel;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.LogInListener;
/**
* @author :smile
* @project:RegisterActivity
* @date :2016-01-15-18:23
*/
public class RegisterActivity extends ParentWithNaviActivity {
@Bind(R.id.et_username)
EditText et_username;
@Bind(R.id.et_password)
EditText et_password;
@Bind(R.id.btn_register)
Button btn_register;
@Bind(R.id.et_password_again)
EditText et_password_again;
@Override
protected String title() {
return "注册";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
initNaviView();
}
@OnClick(R.id.btn_register)
public void onRegisterClick(View view){
UserModel.getInstance().register(et_username.getText().toString(), et_password.getText().toString(),et_password_again.getText().toString(),new LogInListener() {
@Override
public void done(Object o, BmobException e) {
if(e==null){
EventBus.getDefault().post(new FinishEvent());
startActivity(MainActivity.class, null, true);
}else{
if(e.getErrorCode()== BaseModel.CODE_NOT_EQUAL){
et_password_again.setText("");
}
toast(e.getMessage()+"("+e.getErrorCode()+")");
}
}
});
}
}

@ -0,0 +1,115 @@
package cn.bmob.imdemo.ui;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.orhanobut.logger.Logger;
import org.greenrobot.eventbus.Subscribe;
import java.util.List;
import butterknife.Bind;
import butterknife.OnClick;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.adapter.SearchUserAdapter;
import cn.bmob.imdemo.base.ParentWithNaviActivity;
import cn.bmob.imdemo.model.BaseModel;
import cn.bmob.imdemo.model.UserModel;
import cn.bmob.v3.listener.FindListener;
/**
* @author :smile
* @project:SearchUserActivity
* @date :2016-01-25-18:23
*/
public class SearchUserActivity extends ParentWithNaviActivity {
@Bind(R.id.et_find_name)
EditText et_find_name;
@Bind(R.id.sw_refresh)
SwipeRefreshLayout sw_refresh;
@Bind(R.id.btn_search)
Button btn_search;
@Bind(R.id.rc_view)
RecyclerView rc_view;
LinearLayoutManager layoutManager;
SearchUserAdapter adapter;
@Override
protected String title() {
return "搜索好友";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_user);
initNaviView();
adapter =new SearchUserAdapter();
layoutManager = new LinearLayoutManager(this);
rc_view.setLayoutManager(layoutManager);
rc_view.setAdapter(adapter);
sw_refresh.setEnabled(true);
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
query();
}
});
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
@Override
public void onItemClick(int position) {
Bundle bundle = new Bundle();
User user = adapter.getItem(position);
bundle.putSerializable("u", user);
startActivity(UserInfoActivity.class, bundle, false);
}
@Override
public boolean onItemLongClick(int position) {
return true;
}
});
}
@OnClick(R.id.btn_search)
public void onSearchClick(View view){
sw_refresh.setRefreshing(true);
query();
}
public void query(){
String name =et_find_name.getText().toString();
if(TextUtils.isEmpty(name)){
toast("请填写用户名");
sw_refresh.setRefreshing(false);
return;
}
UserModel.getInstance().queryUsers(name, BaseModel.DEFAULT_LIMIT, new FindListener<User>() {
@Override
public void onSuccess(List<User> list) {
sw_refresh.setRefreshing(false);
adapter.setDatas(list);
adapter.notifyDataSetChanged();
}
@Override
public void onError(int i, String s) {
sw_refresh.setRefreshing(false);
adapter.setDatas(null);
adapter.notifyDataSetChanged();
toast(s + "(" + i + ")");
}
});
}
}

@ -0,0 +1,37 @@
package cn.bmob.imdemo.ui;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.base.BaseActivity;
import cn.bmob.imdemo.model.UserModel;
/**
* @author :smile
* @project:SplashActivity
* @date :2016-01-15-18:23
*/
public class SplashActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
Handler handler =new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
User user = UserModel.getInstance().getCurrentUser();
if (user == null) {
startActivity(LoginActivity.class,null,true);
}else{
startActivity(MainActivity.class,null,true);
}
}
},1000);
}
}

@ -0,0 +1,112 @@
package cn.bmob.imdemo.ui;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.HashMap;
import java.util.Map;
import butterknife.Bind;
import butterknife.OnClick;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.base.ImageLoaderFactory;
import cn.bmob.imdemo.base.ParentWithNaviActivity;
import cn.bmob.imdemo.bean.AddFriendMessage;
import cn.bmob.imdemo.bean.User;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMMessage;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.newim.core.BmobIMClient;
import cn.bmob.newim.listener.MessageSendListener;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
/**
*
*/
public class UserInfoActivity extends ParentWithNaviActivity {
@Bind(R.id.iv_avator)
ImageView iv_avator;
@Bind(R.id.tv_name)
TextView tv_name;
@Bind(R.id.btn_add_friend)
Button btn_add_friend;
@Bind(R.id.btn_chat)
Button btn_chat;
User user;
BmobIMUserInfo info;
@Override
protected String title() {
return "个人资料";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_info);
initNaviView();
user=(User)getBundle().getSerializable("u");
if(user.getObjectId().equals(getCurrentUid())){
btn_add_friend.setVisibility(View.GONE);
btn_chat.setVisibility(View.GONE);
}else{
btn_add_friend.setVisibility(View.VISIBLE);
btn_chat.setVisibility(View.VISIBLE);
}
//构造聊天方的用户信息:传入用户id、用户名和用户头像三个参数
info = new BmobIMUserInfo(user.getObjectId(),user.getUsername(),user.getAvatar());
ImageLoaderFactory.getLoader().loadAvator(iv_avator,user.getAvatar(),R.mipmap.head);
tv_name.setText(user.getUsername());
}
@OnClick(R.id.btn_add_friend)
public void onAddClick(View view){
sendAddFriendMessage();
}
/**
*
*/
private void sendAddFriendMessage(){
//启动一个会话如果isTransient设置为true,则不会创建在本地会话表中创建记录,
//设置isTransient设置为false,则会在本地数据库的会话列表中先创建(如果没有)与该用户的会话信息,且将用户信息存储到本地的用户表中
BmobIMConversation c = BmobIM.getInstance().startPrivateConversation(info, true,null);
//这个obtain方法才是真正创建一个管理消息发送的会话
BmobIMConversation conversation = BmobIMConversation.obtain(BmobIMClient.getInstance(), c);
AddFriendMessage msg =new AddFriendMessage();
User currentUser = BmobUser.getCurrentUser(this,User.class);
msg.setContent("很高兴认识你,可以加个好友吗?");//给对方的一个留言信息
Map<String,Object> map =new HashMap<>();
map.put("name", currentUser.getUsername());//发送者姓名,这里只是举个例子,其实可以不需要传发送者的信息过去
map.put("avatar",currentUser.getAvatar());//发送者的头像
map.put("uid",currentUser.getObjectId());//发送者的uid
msg.setExtraMap(map);
conversation.sendMessage(msg, new MessageSendListener() {
@Override
public void done(BmobIMMessage msg, BmobException e) {
if (e == null) {//发送成功
toast("好友请求发送成功,等待验证");
} else {//发送失败
toast("发送失败:" + e.getMessage());
}
}
});
}
@OnClick(R.id.btn_chat)
public void onChatClick(View view){
//启动一个会话设置isTransient设置为false,则会在本地数据库的会话列表中先创建(如果没有)与该用户的会话信息,且将用户信息存储到本地的用户表中
BmobIMConversation c = BmobIM.getInstance().startPrivateConversation(info,false,null);
Bundle bundle = new Bundle();
bundle.putSerializable("c", c);
startActivity(ChatActivity.class, bundle, false);
}
}

@ -0,0 +1,221 @@
package cn.bmob.imdemo.ui.fragment;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.ContactAdapter;
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
import cn.bmob.imdemo.base.ParentWithNaviActivity;
import cn.bmob.imdemo.base.ParentWithNaviFragment;
import cn.bmob.imdemo.bean.Friend;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.event.RefreshEvent;
import cn.bmob.imdemo.model.UserModel;
import cn.bmob.imdemo.ui.ChatActivity;
import cn.bmob.imdemo.ui.NewFriendActivity;
import cn.bmob.imdemo.ui.SearchUserActivity;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.bean.BmobIMUserInfo;
import cn.bmob.v3.listener.DeleteListener;
import cn.bmob.v3.listener.FindListener;
/**
* @author :smile
* @project:ContactFragment
* @date :2016-04-27-14:23
*/
public class ContactFragment extends ParentWithNaviFragment {
@Bind(R.id.rc_view)
RecyclerView rc_view;
@Bind(R.id.sw_refresh)
SwipeRefreshLayout sw_refresh;
ContactAdapter adapter;
LinearLayoutManager layoutManager;
@Override
protected String title() {
return "联系人";
}
@Override
public Object right() {
return R.drawable.base_action_bar_add_bg_selector;
}
@Override
public ParentWithNaviActivity.ToolBarListener setToolBarListener() {
return new ParentWithNaviActivity.ToolBarListener() {
@Override
public void clickLeft() {
}
@Override
public void clickRight() {
startActivity(SearchUserActivity.class,null);
}
};
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView =inflater.inflate(R.layout.fragment_conversation, container, false);
initNaviView();
ButterKnife.bind(this, rootView);
IMutlipleItem<Friend> mutlipleItem = new IMutlipleItem<Friend>() {
@Override
public int getItemViewType(int postion, Friend friend) {
if(postion==0){
return ContactAdapter.TYPE_NEW_FRIEND;
}else{
return ContactAdapter.TYPE_ITEM;
}
}
@Override
public int getItemLayoutId(int viewtype) {
if(viewtype== ContactAdapter.TYPE_NEW_FRIEND){
return R.layout.header_new_friend;
}else{
return R.layout.item_contact;
}
}
@Override
public int getItemCount(List<Friend> list) {
return list.size()+1;
}
};
adapter = new ContactAdapter(getActivity(),mutlipleItem,null);
rc_view.setAdapter(adapter);
layoutManager = new LinearLayoutManager(getActivity());
rc_view.setLayoutManager(layoutManager);
sw_refresh.setEnabled(true);
setListener();
return rootView;
}
private void setListener(){
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
rootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
sw_refresh.setRefreshing(true);
query();
}
});
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
query();
}
});
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
@Override
public void onItemClick(int position) {
if (position == 0) {//跳转到新朋友页面
startActivity(NewFriendActivity.class, null);
} else {
Friend friend = adapter.getItem(position);
User user = friend.getFriendUser();
BmobIMUserInfo info = new BmobIMUserInfo(user.getObjectId(), user.getUsername(), user.getAvatar());
//启动一个会话,实际上就是在本地数据库的会话列表中先创建(如果没有)与该用户的会话信息,且将用户信息存储到本地的用户表中
BmobIMConversation c = BmobIM.getInstance().startPrivateConversation(info, null);
Bundle bundle = new Bundle();
bundle.putSerializable("c", c);
startActivity(ChatActivity.class, bundle);
}
}
@Override
public boolean onItemLongClick(final int position) {
log("长按" + position);
if(position==0){
return true;
}
UserModel.getInstance().deleteFriend(adapter.getItem(position), new DeleteListener() {
@Override
public void onSuccess() {
toast("好友删除成功");
adapter.remove(position);
}
@Override
public void onFailure(int i, String s) {
toast("好友删除失败:" + i + ",s =" + s);
}
});
return true;
}
});
}
@Override
public void onResume() {
super.onResume();
sw_refresh.setRefreshing(true);
query();
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
/**
* @param event
*/
@Subscribe
public void onEventMainThread(RefreshEvent event){
//重新刷新列表
log("---联系人界面接收到自定义消息---");
adapter.notifyDataSetChanged();
}
/**
*/
public void query(){
UserModel.getInstance().queryFriends(new FindListener<Friend>() {
@Override
public void onSuccess(List<Friend> list) {
adapter.bindDatas(list);
adapter.notifyDataSetChanged();
sw_refresh.setRefreshing(false);
}
@Override
public void onError(int i, String s) {
adapter.bindDatas(null);
adapter.notifyDataSetChanged();
sw_refresh.setRefreshing(false);
}
});
}
}

@ -0,0 +1,236 @@
package cn.bmob.imdemo.ui.fragment;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.adapter.ConversationAdapter;
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
import cn.bmob.imdemo.base.ParentWithNaviActivity;
import cn.bmob.imdemo.base.ParentWithNaviFragment;
import cn.bmob.imdemo.bean.Conversation;
import cn.bmob.imdemo.bean.NewFriendConversation;
import cn.bmob.imdemo.bean.PrivateConversation;
import cn.bmob.imdemo.db.NewFriend;
import cn.bmob.imdemo.db.NewFriendManager;
import cn.bmob.imdemo.event.RefreshEvent;
import cn.bmob.imdemo.ui.SearchUserActivity;
import cn.bmob.newim.BmobIM;
import cn.bmob.newim.bean.BmobIMConversation;
import cn.bmob.newim.event.MessageEvent;
import cn.bmob.newim.event.OfflineMessageEvent;
/**
* @author :smile
* @project:ConversationFragment
* @date :2016-01-25-18:23
*/
public class ConversationFragment extends ParentWithNaviFragment {
@Bind(R.id.rc_view)
RecyclerView rc_view;
@Bind(R.id.sw_refresh)
SwipeRefreshLayout sw_refresh;
ConversationAdapter adapter;
LinearLayoutManager layoutManager;
@Override
protected String title() {
return "会话";
}
@Override
public Object right() {
return R.drawable.base_action_bar_add_bg_selector;
}
@Override
public ParentWithNaviActivity.ToolBarListener setToolBarListener() {
return new ParentWithNaviActivity.ToolBarListener() {
@Override
public void clickLeft() {
}
@Override
public void clickRight() {
startActivity(SearchUserActivity.class,null);
}
};
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView =inflater.inflate(R.layout.fragment_conversation, container, false);
initNaviView();
ButterKnife.bind(this, rootView);
//单一布局
IMutlipleItem<Conversation> mutlipleItem = new IMutlipleItem<Conversation>() {
@Override
public int getItemViewType(int postion, Conversation c) {
return 0;
}
@Override
public int getItemLayoutId(int viewtype) {
return R.layout.item_conversation;
}
@Override
public int getItemCount(List<Conversation> list) {
return list.size();
}
};
adapter = new ConversationAdapter(getActivity(),mutlipleItem,null);
rc_view.setAdapter(adapter);
layoutManager = new LinearLayoutManager(getActivity());
rc_view.setLayoutManager(layoutManager);
sw_refresh.setEnabled(true);
setListener();
return rootView;
}
private void setListener(){
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
rootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
sw_refresh.setRefreshing(true);
query();
}
});
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
query();
}
});
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
@Override
public void onItemClick(int position) {
adapter.getItem(position).onClick(getActivity());
}
@Override
public boolean onItemLongClick(int position) {
adapter.getItem(position).onLongClick(getActivity());
adapter.remove(position);
return true;
}
});
}
@Override
public void onResume() {
super.onResume();
sw_refresh.setRefreshing(true);
query();
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
/**
*/
public void query(){
// adapter.bindDatas(BmobIM.getInstance().loadAllConversation());
adapter.bindDatas(getConversations());
adapter.notifyDataSetChanged();
sw_refresh.setRefreshing(false);
}
/**
*
* @return
*/
private List<Conversation> getConversations(){
//添加会话
List<Conversation> conversationList = new ArrayList<>();
conversationList.clear();
List<BmobIMConversation> list =BmobIM.getInstance().loadAllConversation();
if(list!=null && list.size()>0){
for (BmobIMConversation item:list){
switch (item.getConversationType()){
case 1://私聊
conversationList.add(new PrivateConversation(item));
break;
default:
break;
}
}
}
//添加新朋友会话-获取好友请求表中最新一条记录
List<NewFriend> friends = NewFriendManager.getInstance(getActivity()).getAllNewFriend();
if(friends!=null && friends.size()>0){
conversationList.add(new NewFriendConversation(friends.get(0)));
}
//重新排序
Collections.sort(conversationList);
return conversationList;
}
/**
* @param event
*/
@Subscribe
public void onEventMainThread(RefreshEvent event){
log("---会话页接收到自定义消息---");
//因为新增`新朋友`这种会话类型
adapter.bindDatas(getConversations());
adapter.notifyDataSetChanged();
}
/**线
* @param event
*/
@Subscribe
public void onEventMainThread(OfflineMessageEvent event){
//重新刷新列表
adapter.bindDatas(getConversations());
adapter.notifyDataSetChanged();
}
/**
* @param event
* 1SDK
* 2SDK
*/
@Subscribe
public void onEventMainThread(MessageEvent event){
//重新获取本地消息并刷新列表
adapter.bindDatas(getConversations());
adapter.notifyDataSetChanged();
}
}

@ -0,0 +1,76 @@
package cn.bmob.imdemo.ui.fragment;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cn.bmob.imdemo.R;
import cn.bmob.imdemo.base.ParentWithNaviFragment;
import cn.bmob.imdemo.bean.User;
import cn.bmob.imdemo.model.UserModel;
import cn.bmob.imdemo.ui.LoginActivity;
import cn.bmob.imdemo.ui.UserInfoActivity;
import cn.bmob.newim.BmobIM;
import cn.bmob.v3.BmobUser;
/**
* @author :smile
* @project:SetFragment
* @date :2016-01-25-18:23
*/
public class SetFragment extends ParentWithNaviFragment {
@Bind(R.id.tv_set_name)
TextView tv_set_name;
@Bind(R.id.layout_info)
RelativeLayout layout_info;
@Override
protected String title() {
return "设置";
}
public static SetFragment newInstance() {
SetFragment fragment = new SetFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
public SetFragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView= inflater.inflate(R.layout.fragment_set,container, false);
initNaviView();
ButterKnife.bind(this, rootView);
String username = UserModel.getInstance().getCurrentUser().getUsername();
tv_set_name.setText(TextUtils.isEmpty(username)?"":username);
return rootView;
}
@OnClick(R.id.layout_info)
public void onInfoClick(View view){
Bundle bundle = new Bundle();
bundle.putSerializable("u", BmobUser.getCurrentUser(getActivity(),User.class));
startActivity(UserInfoActivity.class,bundle);
}
@OnClick(R.id.btn_logout)
public void onLogoutClick(View view){
UserModel.getInstance().logout();
//可断开连接
BmobIM.getInstance().disConnect();
getActivity().finish();
startActivity(LoginActivity.class,null);
}
}

@ -0,0 +1,40 @@
package cn.bmob.imdemo.util;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
/**
* @author :smile
* @project:DisplayConfig
* @date :2016-01-25-09:19
* Picasso
*/
public class DisplayConfig {
/**UIL:
* @param defaultRes
* @return
*/
public static DisplayImageOptions getDefaultOptions(boolean hasRounded,int defaultRes){
DisplayImageOptions.Builder builder = new DisplayImageOptions.Builder()
.cacheInMemory(true)//设置下载的图片是否缓存在内存中
.cacheOnDisc(true)//设置下载的图片是否缓存在SD卡中
.considerExifParams(true) //是否考虑JPEG图像EXIF参数旋转翻转
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型:设置为RGB565比起默认的ARGB_8888要节省大量的内存
// .delayBeforeLoading(100)//载入图片前稍做延时可以提高整体滑动的流畅度
.resetViewBeforeLoading(true);//设置图片在下载前是否重置,复位
if(hasRounded){
builder.displayer(new RoundedBitmapDisplayer(12));//是否设置为圆角,弧度为多少
}
if(defaultRes!=0){
builder.showImageForEmptyUri(defaultRes)//设置图片Uri为空或是错误的时候显示的图片
// .showImageOnLoading(defaultRes) //设置图片在下载期间显示的图片-->应该去掉-会造成ListView中图片闪烁
.showImageOnFail(defaultRes); //设置图片加载/解码过程中错误时候显示的图片
}
return builder.build();//构建完成
}
}

@ -0,0 +1,178 @@
package cn.bmob.imdemo.util;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Bundle;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import static android.content.Context.INPUT_METHOD_SERVICE;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.KITKAT;
public class IMMLeaks {
static class ReferenceCleaner
implements MessageQueue.IdleHandler, View.OnAttachStateChangeListener,
ViewTreeObserver.OnGlobalFocusChangeListener {
private final InputMethodManager inputMethodManager;
private final Field mHField;
private final Field mServedViewField;
private final Method finishInputLockedMethod;
ReferenceCleaner(InputMethodManager inputMethodManager, Field mHField, Field mServedViewField,
Method finishInputLockedMethod) {
this.inputMethodManager = inputMethodManager;
this.mHField = mHField;
this.mServedViewField = mServedViewField;
this.finishInputLockedMethod = finishInputLockedMethod;
}
@Override public void onGlobalFocusChanged(View oldFocus, View newFocus) {
if (newFocus == null) {
return;
}
if (oldFocus != null) {
oldFocus.removeOnAttachStateChangeListener(this);
}
Looper.myQueue().removeIdleHandler(this);
newFocus.addOnAttachStateChangeListener(this);
}
@Override public void onViewAttachedToWindow(View v) {
}
@Override public void onViewDetachedFromWindow(View v) {
v.removeOnAttachStateChangeListener(this);
Looper.myQueue().removeIdleHandler(this);
Looper.myQueue().addIdleHandler(this);
}
@Override public boolean queueIdle() {
clearInputMethodManagerLeak();
return false;
}
private void clearInputMethodManagerLeak() {
try {
Object lock = mHField.get(inputMethodManager);
if(lock==null){
return;
}
// This is highly dependent on the InputMethodManager implementation.
synchronized (lock) {
View servedView = (View) mServedViewField.get(inputMethodManager);
if (servedView != null) {
boolean servedViewAttached = servedView.getWindowVisibility() != View.GONE;
if (servedViewAttached) {
// The view held by the IMM was replaced without a global focus change. Let's make
// sure we get notified when that view detaches.
// Avoid double registration.
servedView.removeOnAttachStateChangeListener(this);
servedView.addOnAttachStateChangeListener(this);
} else {
// servedView is not attached. InputMethodManager is being stupid!
Activity activity = extractActivity(servedView.getContext());
if (activity == null || activity.getWindow() == null) {
// Unlikely case. Let's finish the input anyways.
finishInputLockedMethod.invoke(inputMethodManager);
} else {
View decorView = activity.getWindow().peekDecorView();
boolean windowAttached = decorView.getWindowVisibility() != View.GONE;
if (!windowAttached) {
finishInputLockedMethod.invoke(inputMethodManager);
} else {
decorView.requestFocusFromTouch();
}
}
}
}
}
} catch (Exception unexpected) {
Log.e("IMMLeaks", "Unexpected reflection exception", unexpected);
}
}
private Activity extractActivity(Context context) {
while (true) {
if (context instanceof Application) {
return null;
} else if (context instanceof Activity) {
return (Activity) context;
} else if (context instanceof ContextWrapper) {
Context baseContext = ((ContextWrapper) context).getBaseContext();
// Prevent Stack Overflow.
if (baseContext == context) {
return null;
}
context = baseContext;
} else {
return null;
}
}
}
}
/**
* Fix for https://code.google.com/p/android/issues/detail?id=171190 .
*
* When a view that has focus gets detached, we wait for the main thread to be idle and then
* check if the InputMethodManager is leaking a view. If yes, we tell it that the decor view got
* focus, which is what happens if you press home and come back from recent apps. This replaces
* the reference to the detached view with a reference to the decor view.
*
* Should be called from {@link Activity#onCreate(android.os.Bundle)} )}.
*/
public static void fixFocusedViewLeak(Application application) {
// Don't know about other versions yet.
if (SDK_INT < KITKAT || SDK_INT > 22) {
return;
}
final InputMethodManager inputMethodManager =
(InputMethodManager) application.getSystemService(INPUT_METHOD_SERVICE);
final Field mServedViewField;
final Field mHField;
final Method finishInputLockedMethod;
final Method focusInMethod;
try {
mServedViewField = InputMethodManager.class.getDeclaredField("mServedView");
mServedViewField.setAccessible(true);
mHField = InputMethodManager.class.getDeclaredField("mServedView");
mHField.setAccessible(true);
finishInputLockedMethod = InputMethodManager.class.getDeclaredMethod("finishInputLocked");
finishInputLockedMethod.setAccessible(true);
focusInMethod = InputMethodManager.class.getDeclaredMethod("focusIn", View.class);
focusInMethod.setAccessible(true);
} catch (Exception unexpected) {
Log.e("IMMLeaks", "Unexpected reflection exception", unexpected);
return;
}
application.registerActivityLifecycleCallbacks(new LifecycleCallbacksAdapter() {
@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
ReferenceCleaner cleaner =
new ReferenceCleaner(inputMethodManager, mHField, mServedViewField,
finishInputLockedMethod);
View rootView = activity.getWindow().getDecorView().getRootView();
ViewTreeObserver viewTreeObserver = rootView.getViewTreeObserver();
viewTreeObserver.addOnGlobalFocusChangeListener(cleaner);
}
});
}
}

@ -0,0 +1,36 @@
package cn.bmob.imdemo.util;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
/** Helper to avoid implementing all lifecycle callback methods. */
public class LifecycleCallbacksAdapter implements Application.ActivityLifecycleCallbacks {
@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override public void onActivityStarted(Activity activity) {
}
@Override public void onActivityResumed(Activity activity) {
}
@Override public void onActivityPaused(Activity activity) {
}
@Override public void onActivityStopped(Activity activity) {
}
@Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override public void onActivityDestroyed(Activity activity) {
}
}

@ -0,0 +1,78 @@
package cn.bmob.imdemo.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* @author :smile
* @project:TimeUtil
* @date :2016-01-26-17:27
*/
public class TimeUtil {
public final static String FORMAT_TIME = "HH:mm";
public final static String FORMAT_DATE_TIME = "yyyy-MM-dd HH:mm";
public final static String FORMAT_DATE_TIME_SECOND = "yyyy-MM-dd HH:mm:ss";
public final static String FORMAT_MONTH_DAY_TIME = "MM-dd HH:mm";
public static String getFormatToday(String dateFormat) {
Date currentTime = new Date();
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
return formatter.format(currentTime);
}
public static Date stringToDate(String dateStr, String dateFormat) {
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
try {
return formatter.parse(dateStr);
} catch (ParseException e) {
return null;
}
}
public static String dateToString(Date date, String dateFormat) {
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
return formatter.format(date);
}
public static String getChatTime(boolean hasYear,long timesamp) {
long clearTime = timesamp;
String result;
SimpleDateFormat sdf = new SimpleDateFormat("dd");
Date today = new Date(System.currentTimeMillis());
Date otherDay = new Date(clearTime);
int temp = Integer.parseInt(sdf.format(today))
- Integer.parseInt(sdf.format(otherDay));
switch (temp) {
case 0:
result = "今天 " + getHourAndMin(clearTime);
break;
case 1:
result = "昨天 " + getHourAndMin(clearTime);
break;
case 2:
result = "前天 " + getHourAndMin(clearTime);
break;
default:
result = getTime(hasYear,clearTime);
break;
}
return result;
}
public static String getTime(boolean hasYear,long time) {
String pattern=FORMAT_DATE_TIME;
if(!hasYear){
pattern = FORMAT_MONTH_DAY_TIME;
}
SimpleDateFormat format = new SimpleDateFormat(pattern);
return format.format(new Date(time));
}
public static String getHourAndMin(long time) {
SimpleDateFormat format = new SimpleDateFormat(FORMAT_TIME);
return format.format(new Date(time));
}
}

@ -0,0 +1,27 @@
package cn.bmob.imdemo.util;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
/**
* @author smile
* @project Util
* @date 2016-03-01-14:55
*/
public class Util {
public static boolean checkSdCard() {
if (android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED))
return true;
else
return false;
}
}

@ -0,0 +1,111 @@
package com.baidu.location.service;
import android.content.Context;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.LocationClientOption.LocationMode;
/**
*
* @author baidu
*
*/
public class LocationService {
private LocationClient client = null;
private LocationClientOption mOption,DIYoption;
private Object objLock = new Object();
/***
*
* @param locationContext
*/
public LocationService(Context locationContext){
synchronized (objLock) {
if(client == null){
client = new LocationClient(locationContext);
client.setLocOption(getDefaultLocationClientOption());
}
}
}
/***
*
* @param listener
* @return
*/
public boolean registerListener(BDLocationListener listener){
boolean isSuccess = false;
if(listener != null){
client.registerLocationListener(listener);
isSuccess = true;
}
return isSuccess;
}
public void unregisterListener(BDLocationListener listener){
if(listener != null){
client.unRegisterLocationListener(listener);
}
}
/***
*
* @param option
* @return isSuccessSetOption
*/
public boolean setLocationOption(LocationClientOption option){
boolean isSuccess = false;
if(option != null){
if(client.isStarted())
client.stop();
DIYoption = option;
client.setLocOption(option);
isSuccess = true;
}
return isSuccess;
}
public LocationClientOption getOption(){
return DIYoption;
}
/***
*
* @return DefaultLocationClientOption
*/
public LocationClientOption getDefaultLocationClientOption(){
if(mOption == null){
mOption = new LocationClientOption();
mOption.setLocationMode(LocationMode.Hight_Accuracy);//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
mOption.setCoorType("bd09ll");//可选默认gcj02设置返回的定位结果坐标系如果配合百度地图使用建议设置为bd09ll;
mOption.setScanSpan(3000);//可选默认0即仅定位一次设置发起定位请求的间隔需要大于等于1000ms才是有效的
mOption.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
mOption.setIsNeedLocationDescribe(true);//可选,设置是否需要地址描述
mOption.setNeedDeviceDirect(false);//可选,设置是否需要设备方向结果
mOption.setLocationNotify(false);//可选默认false设置是否当gps有效时按照1S1次频率输出GPS结果
mOption.setIgnoreKillProcess(true);//可选默认true定位SDK内部是一个SERVICE并放到了独立进程设置是否在stop的时候杀死这个进程默认不杀死
mOption.setIsNeedLocationDescribe(true);//可选默认false设置是否需要位置语义化结果可以在BDLocation.getLocationDescribe里得到结果类似于“在北京天安门附近”
mOption.setIsNeedLocationPoiList(true);//可选默认false设置是否需要POI结果可以在BDLocation.getPoiList里得到
mOption.SetIgnoreCacheException(false);//可选默认false设置是否收集CRASH信息默认收集
}
return mOption;
}
public void start(){
synchronized (objLock) {
if(client != null && !client.isStarted()){
client.start();
}
}
}
public void stop(){
synchronized (objLock) {
if(client != null && client.isStarted()){
client.stop();
}
}
}
}

@ -0,0 +1,28 @@
package com.baidu.location.service;
public class Utils {
public final static String CoorType_GCJ02 = "gcj02";
public final static String CoorType_BD09LL= "bd09ll";
public final static String CoorType_BD09MC= "bd09";
/***
*61 GPSGPS
*62 wifi
*63
*65
*66 线requestOfflineLocaiton
*67 线requestOfflineLocaiton
*68 线
*161
*162
*167
*502 keyKEY
*505 keyKEY
*601 keyKEY
*602 key mcodeaksha1;KEY
*501700keyKEY
*/
public static float[] EARTH_WEIGHT = {0.1f,0.2f,0.4f,0.6f,0.8f}; // 推算计算权重_地球
//public static float[] MOON_WEIGHT = {0.0167f,0.033f,0.067f,0.1f,0.133f};
//public static float[] MARS_WEIGHT = {0.034f,0.068f,0.152f,0.228f,0.304f};
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save