commit
f8e6f120ae
@ -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
|
@ -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_8" 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>
|
@ -0,0 +1 @@
|
|||||||
|
/build
|
@ -0,0 +1,132 @@
|
|||||||
|
<?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/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" />
|
||||||
|
<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" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
|
||||||
|
<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/mockable-android-22.jar" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||||
|
<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>
|
Binary file not shown.
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,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 {
|
||||||
|
/**
|
||||||
|
* Bmob应用key
|
||||||
|
*/
|
||||||
|
// 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,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,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,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,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,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,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,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,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,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,38 @@
|
|||||||
|
package cn.bmob.imdemo.bean;
|
||||||
|
|
||||||
|
import com.baidu.mapapi.map.BaiduMap;
|
||||||
|
import com.baidu.mapapi.map.Marker;
|
||||||
|
import com.baidu.mapapi.map.OverlayOptions;
|
||||||
|
import com.baidu.mapapi.map.Polyline;
|
||||||
|
import com.baidu.mapapi.overlayutil.OverlayManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by lifu on 16/6/11.
|
||||||
|
*/
|
||||||
|
public class FindUOverlayManager extends OverlayManager {
|
||||||
|
private List<OverlayOptions> optionsList = new ArrayList<OverlayOptions>();
|
||||||
|
public FindUOverlayManager(BaiduMap baiduMap) {
|
||||||
|
super(baiduMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<OverlayOptions> getOverlayOptions() {
|
||||||
|
return optionsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMarkerClick(Marker marker) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPolylineClick(Polyline polyline) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public void setData(List<OverlayOptions> optionsList) {
|
||||||
|
this.optionsList = optionsList;
|
||||||
|
}
|
||||||
|
}
|
@ -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,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,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,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,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,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,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;
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue