first
This commit is contained in:
commit
bcb1bd5dff
|
|
@ -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_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/NewIM.iml" filepath="$PROJECT_DIR$/NewIM.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id="NewIM" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="java-gradle" name="Java-Gradle">
|
||||
<configuration>
|
||||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
||||
<option name="BUILDABLE" value="false" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="NewIM" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<afterSyncTasks>
|
||||
<task>generateDebugSources</task>
|
||||
</afterSyncTasks>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/cn.bmob.android/bmob-im/2.0.5/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/cn.bmob.android/bmob-sdk/3.4.7-aar/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.2.0/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/22.2.0/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.0/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.orhanobut/logger/1.4/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="butterknife-7.0.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="baidumapapi_v3_5_0" level="project" />
|
||||
<orderEntry type="library" exported="" name="recyclerview-v7-22.2.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-22.2.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-v4-22.2.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="universal-image-loader-1.9.5" level="project" />
|
||||
<orderEntry type="library" exported="" name="logger-1.4" level="project" />
|
||||
<orderEntry type="library" exported="" name="eventbus-3.0.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="appcompat-v7-22.2.0" level="project" />
|
||||
<orderEntry type="library" exported="" scope="TEST" name="hamcrest-core-1.3" level="project" />
|
||||
<orderEntry type="library" exported="" scope="TEST" name="junit-4.12" level="project" />
|
||||
<orderEntry type="library" exported="" name="bmob-sdk-3.4.7-aar" level="project" />
|
||||
<orderEntry type="library" exported="" name="bmob-im-2.0.5" level="project" />
|
||||
<orderEntry type="library" exported="" name="locSDK_6.23" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
buildToolsVersion "22.0.1"
|
||||
|
||||
aaptOptions.cruncherEnabled = false
|
||||
aaptOptions.useNewCruncher = false
|
||||
|
||||
defaultConfig {
|
||||
applicationId "cn.bmob.imdemo"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 22
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
//自动删除 unaligned .apks
|
||||
applicationVariants.all { variant ->
|
||||
variant.assemble.doLast {
|
||||
variant.outputs.each { output ->
|
||||
File unaligned = output.packageApplication.outputFile;
|
||||
File aligned = output.outputFile
|
||||
if (!unaligned.getName().equalsIgnoreCase(aligned.getName())) {
|
||||
println "deleting " + unaligned.getName()
|
||||
unaligned.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dexOptions{
|
||||
incremental false
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile('com.android.support:appcompat-v7:22.2.0') {
|
||||
exclude module: 'support-annotations'
|
||||
}
|
||||
compile 'com.android.support:recyclerview-v7:22.2.0'
|
||||
compile 'com.jakewharton:butterknife:7.0.1'
|
||||
compile 'com.orhanobut:logger:1.4'
|
||||
compile 'org.greenrobot:eventbus:3.0.0'
|
||||
//bmob-im:自2.0.5开始提供aar格式:包含BmobNewIM_xxxx.jar、androidasync_2.1.6.jar、bmob_im_notification_strings.xml
|
||||
compile 'cn.bmob.android:bmob-im:2.0.5@aar'
|
||||
//bmob-sdk:3.4.7
|
||||
compile 'cn.bmob.android:bmob-sdk:3.4.7-aar'
|
||||
compile files('libs/baidumapapi_v3_5_0.jar')
|
||||
compile files('libs/locSDK_6.23.jar')
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,13 @@
|
|||
package cn.bmob.imdemo;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cn.bmob.imdemo">
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="9"
|
||||
android:targetSdkVersion="14" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- 监听网络的变化 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<!-- 设备休眠 -->
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<!-- sd卡存储 -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<!-- 摄像头 -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<!-- 录音 -->
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<!-- 通知震动 -->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<!-- 百度地图的权限 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
|
||||
<application
|
||||
android:name=".BmobIMApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".ui.SplashActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".ui.LoginActivity" />
|
||||
<activity android:name=".ui.MainActivity" />
|
||||
<activity android:name=".ui.RegisterActivity" />
|
||||
<activity android:name=".ui.SearchUserActivity" />
|
||||
<activity android:name=".ui.UserInfoActivity"/>
|
||||
<activity android:name=".ui.NewFriendActivity"/>
|
||||
|
||||
<activity
|
||||
android:name=".ui.ChatActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateAlwaysHidden|adjustResize" />
|
||||
|
||||
<!-- bmobim start -->
|
||||
<receiver android:name="cn.bmob.newim.core.ConnectChangeReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="cn.bmob.action.RECONNECT" />
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.USER_PRESENT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name="cn.bmob.newim.core.service.BmobIMService"
|
||||
android:process=":bmobcore" />
|
||||
<service
|
||||
android:name="cn.bmob.newim.core.service.NotifyService"
|
||||
android:process=":bmobcore" />
|
||||
<service android:name="cn.bmob.newim.core.service.ReConnectService" />
|
||||
<service android:name="cn.bmob.newim.core.service.HeartBeatService" />
|
||||
|
||||
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote">
|
||||
</service>
|
||||
|
||||
|
||||
<!-- 设置bmob appkey -->
|
||||
<meta-data
|
||||
android:name="Bmob_APP_KEY"
|
||||
android:value="44d76c5b8464f93f380b1083f049bb36" />
|
||||
<!-- bmobim end -->
|
||||
<meta-data
|
||||
android:name="com.baidu.lbsapi.API_KEY"
|
||||
android:value="tqoNSeUugf6ZBvfKPAv7Rpc40IV3bA8K" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package cn.bmob.imdemo;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
|
||||
import cn.bmob.imdemo.base.UniversalImageLoader;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:BmobIMApplication
|
||||
* @date :2016-01-13-10:19
|
||||
*/
|
||||
public class BmobIMApplication extends Application{
|
||||
|
||||
private static BmobIMApplication INSTANCE;
|
||||
public static BmobIMApplication INSTANCE(){
|
||||
return INSTANCE;
|
||||
}
|
||||
private void setInstance(BmobIMApplication app) {
|
||||
setBmobIMApplication(app);
|
||||
}
|
||||
private static void setBmobIMApplication(BmobIMApplication a) {
|
||||
BmobIMApplication.INSTANCE = a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
setInstance(this);
|
||||
//初始化
|
||||
Logger.init("smile");
|
||||
//只有主进程运行的时候才需要初始化
|
||||
if (getApplicationInfo().packageName.equals(getMyProcessName())){
|
||||
//im初始化
|
||||
BmobIM.init(this);
|
||||
//注册消息接收器
|
||||
BmobIM.registerDefaultMessageHandler(new DemoMessageHandler(this));
|
||||
}
|
||||
//uil初始化
|
||||
UniversalImageLoader.initImageLoader(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前运行的进程名
|
||||
* @return
|
||||
*/
|
||||
public static String getMyProcessName() {
|
||||
try {
|
||||
File file = new File("/proc/" + android.os.Process.myPid() + "/" + "cmdline");
|
||||
BufferedReader mBufferedReader = new BufferedReader(new FileReader(file));
|
||||
String processName = mBufferedReader.readLine().trim();
|
||||
mBufferedReader.close();
|
||||
return processName;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package cn.bmob.imdemo;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:Config
|
||||
* @date :2016-01-15-18:23
|
||||
*/
|
||||
public class Config {
|
||||
/**
|
||||
* 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,176 @@
|
|||
package cn.bmob.imdemo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import cn.bmob.imdemo.bean.AddFriendMessage;
|
||||
import cn.bmob.imdemo.bean.AgreeAddFriendMessage;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
import cn.bmob.imdemo.db.NewFriendManager;
|
||||
import cn.bmob.imdemo.event.RefreshEvent;
|
||||
import cn.bmob.imdemo.model.UserModel;
|
||||
import cn.bmob.imdemo.model.i.UpdateCacheListener;
|
||||
import cn.bmob.imdemo.ui.MainActivity;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessageType;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.event.MessageEvent;
|
||||
import cn.bmob.newim.event.OfflineMessageEvent;
|
||||
import cn.bmob.newim.listener.BmobIMMessageHandler;
|
||||
import cn.bmob.newim.notification.BmobNotificationManager;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
import cn.bmob.v3.listener.SaveListener;
|
||||
|
||||
/**消息接收器
|
||||
* @author smile
|
||||
* @project DemoMessageHandler
|
||||
* @date 2016-03-08-17:37
|
||||
*/
|
||||
public class DemoMessageHandler extends BmobIMMessageHandler{
|
||||
|
||||
private Context context;
|
||||
|
||||
public DemoMessageHandler(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageReceive(final MessageEvent event) {
|
||||
//当接收到服务器发来的消息时,此方法被调用
|
||||
Logger.i(event.getConversation().getConversationTitle() + "," + event.getMessage().getMsgType() + "," + event.getMessage().getContent());
|
||||
excuteMessage(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOfflineReceive(final OfflineMessageEvent event) {
|
||||
//每次调用connect方法时会查询一次离线消息,如果有,此方法会被调用
|
||||
Map<String,List<MessageEvent>> map =event.getEventMap();
|
||||
Logger.i("离线消息属于" + map.size() + "个用户");
|
||||
//挨个检测下离线消息所属的用户的信息是否需要更新
|
||||
for (Map.Entry<String, List<MessageEvent>> entry : map.entrySet()) {
|
||||
List<MessageEvent> list =entry.getValue();
|
||||
int size = list.size();
|
||||
for(int i=0;i<size;i++){
|
||||
excuteMessage(list.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理消息
|
||||
* @param event
|
||||
*/
|
||||
private void excuteMessage(final MessageEvent event){
|
||||
//检测用户信息是否需要更新
|
||||
UserModel.getInstance().updateUserInfo(event, new UpdateCacheListener() {
|
||||
@Override
|
||||
public void done(BmobException e) {
|
||||
BmobIMMessage msg = event.getMessage();
|
||||
if (BmobIMMessageType.getMessageTypeValue(msg.getMsgType()) == 0) {//用户自定义的消息类型,其类型值均为0
|
||||
processCustomMessage(msg, event.getFromUserInfo());
|
||||
} else {//SDK内部内部支持的消息类型
|
||||
if (BmobNotificationManager.getInstance(context).isShowNotification()) {//如果需要显示通知栏,SDK提供以下两种显示方式:
|
||||
Intent pendingIntent = new Intent(context, MainActivity.class);
|
||||
pendingIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
//1、多个用户的多条消息合并成一条通知:有XX个联系人发来了XX条消息
|
||||
BmobNotificationManager.getInstance(context).showNotification(event, pendingIntent);
|
||||
//2、自定义通知消息:始终只有一条通知,新消息覆盖旧消息
|
||||
// BmobIMUserInfo info =event.getFromUserInfo();
|
||||
// //这里可以是应用图标,也可以将聊天头像转成bitmap
|
||||
// Bitmap largetIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
|
||||
// BmobNotificationManager.getInstance(context).showNotification(largetIcon,
|
||||
// info.getName(),msg.getContent(),"您有一条新消息",pendingIntent);
|
||||
} else {//直接发送消息事件
|
||||
Logger.i("当前处于应用内,发送event");
|
||||
EventBus.getDefault().post(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自定义消息类型
|
||||
* @param msg
|
||||
*/
|
||||
private void processCustomMessage(BmobIMMessage msg,BmobIMUserInfo info){
|
||||
//自行处理自定义消息类型
|
||||
Logger.i(msg.getMsgType() + "," + msg.getContent() + "," + msg.getExtra());
|
||||
String type =msg.getMsgType();
|
||||
//发送页面刷新的广播
|
||||
EventBus.getDefault().post(new RefreshEvent());
|
||||
//处理消息
|
||||
if(type.equals("add")){//接收到的添加好友的请求
|
||||
NewFriend friend = AddFriendMessage.convert(msg);
|
||||
//本地好友请求表做下校验,本地没有的才允许显示通知栏--有可能离线消息会有些重复
|
||||
long id = NewFriendManager.getInstance(context).insertOrUpdateNewFriend(friend);
|
||||
if(id>0){
|
||||
showAddNotify(friend);
|
||||
}
|
||||
}else if(type.equals("agree")){//接收到的对方同意添加自己为好友,此时需要做的事情:1、添加对方为好友,2、显示通知
|
||||
AgreeAddFriendMessage agree = AgreeAddFriendMessage.convert(msg);
|
||||
addFriend(agree.getFromId());//添加消息的发送方为好友
|
||||
//这里应该也需要做下校验--来检测下是否已经同意过该好友请求,我这里省略了
|
||||
showAgreeNotify(info,agree);
|
||||
}else{
|
||||
Toast.makeText(context,"接收到的自定义消息:"+msg.getMsgType() + "," + msg.getContent() + "," + msg.getExtra(),Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示对方添加自己为好友的通知
|
||||
* @param friend
|
||||
*/
|
||||
private void showAddNotify(NewFriend friend){
|
||||
Intent pendingIntent = new Intent(context, MainActivity.class);
|
||||
pendingIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
//这里可以是应用图标,也可以将聊天头像转成bitmap
|
||||
Bitmap largetIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
|
||||
BmobNotificationManager.getInstance(context).showNotification(largetIcon,
|
||||
friend.getName(), friend.getMsg(), friend.getName() + "请求添加你为朋友", pendingIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示对方同意添加自己为好友的通知
|
||||
* @param info
|
||||
* @param agree
|
||||
*/
|
||||
private void showAgreeNotify(BmobIMUserInfo info,AgreeAddFriendMessage agree){
|
||||
Intent pendingIntent = new Intent(context, MainActivity.class);
|
||||
pendingIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
Bitmap largetIcon = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
|
||||
BmobNotificationManager.getInstance(context).showNotification(largetIcon,info.getName(),agree.getMsg(),agree.getMsg(),pendingIntent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加对方为自己的好友
|
||||
* @param uid
|
||||
*/
|
||||
private void addFriend(String uid){
|
||||
User user =new User();
|
||||
user.setObjectId(uid);
|
||||
UserModel.getInstance().agreeAddFriend(user, new SaveListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
Log.i("bmob", "onSuccess");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int i, String s) {
|
||||
Log.i("bmob", "onFailure:"+s+"-"+i);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
|
||||
/**
|
||||
* 同意添加好友的agree类型
|
||||
*/
|
||||
public class AgreeHolder extends BaseViewHolder implements View.OnClickListener,View.OnLongClickListener {
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.tv_message)
|
||||
protected TextView tv_message;
|
||||
|
||||
public AgreeHolder(Context context, ViewGroup root, OnRecyclerViewListener listener) {
|
||||
super(context, root, R.layout.item_chat_agree, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
final BmobIMMessage message = (BmobIMMessage)o;
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
String time = dateFormat.format(message.getCreateTime());
|
||||
String content = message.getContent();
|
||||
tv_message.setText(content);
|
||||
tv_time.setText(time);
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessageType;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:ChatAdapter
|
||||
* @date :2016-01-22-14:18
|
||||
*/
|
||||
public class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
|
||||
|
||||
//文本
|
||||
private final int TYPE_RECEIVER_TXT = 0;
|
||||
private final int TYPE_SEND_TXT = 1;
|
||||
//图片
|
||||
private final int TYPE_SEND_IMAGE = 2;
|
||||
private final int TYPE_RECEIVER_IMAGE = 3;
|
||||
//位置
|
||||
private final int TYPE_SEND_LOCATION = 4;
|
||||
private final int TYPE_RECEIVER_LOCATION = 5;
|
||||
//语音
|
||||
private final int TYPE_SEND_VOICE =6;
|
||||
private final int TYPE_RECEIVER_VOICE = 7;
|
||||
//视频
|
||||
private final int TYPE_SEND_VIDEO =8;
|
||||
private final int TYPE_RECEIVER_VIDEO = 9;
|
||||
|
||||
//同意添加好友成功后的样式
|
||||
private final int TYPE_AGREE = 10;
|
||||
|
||||
/**
|
||||
* 显示时间间隔:10分钟
|
||||
*/
|
||||
private final long TIME_INTERVAL = 10 * 60 * 1000;
|
||||
|
||||
private List<BmobIMMessage> msgs = new ArrayList<>();
|
||||
|
||||
private String currentUid="";
|
||||
BmobIMConversation c;
|
||||
|
||||
public ChatAdapter(Context context,BmobIMConversation c) {
|
||||
try {
|
||||
currentUid = BmobUser.getCurrentUser(context).getObjectId();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.c =c;
|
||||
}
|
||||
public int findPosition(BmobIMMessage message) {
|
||||
int index = this.getCount();
|
||||
int position = -1;
|
||||
while(index-- > 0) {
|
||||
if(message.equals(this.getItem(index))) {
|
||||
position = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
public int findPosition(long id) {
|
||||
int index = this.getCount();
|
||||
int position = -1;
|
||||
while(index-- > 0) {
|
||||
if(this.getItemId(index) == id) {
|
||||
position = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.msgs == null?0:this.msgs.size();
|
||||
}
|
||||
|
||||
public void addMessages(List<BmobIMMessage> messages) {
|
||||
msgs.addAll(0, messages);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void addMessage(BmobIMMessage message) {
|
||||
msgs.addAll(Arrays.asList(message));
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**获取消息
|
||||
* @param position
|
||||
* @return
|
||||
*/
|
||||
public BmobIMMessage getItem(int position){
|
||||
return this.msgs == null?null:(position >= this.msgs.size()?null:this.msgs.get(position));
|
||||
}
|
||||
|
||||
/**移除消息
|
||||
* @param position
|
||||
*/
|
||||
public void remove(int position){
|
||||
msgs.remove(position);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public BmobIMMessage getFirstMessage() {
|
||||
if (null != msgs && msgs.size() > 0) {
|
||||
return msgs.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
if (viewType == TYPE_SEND_TXT) {
|
||||
return new SendTextHolder(parent.getContext(), parent,c,onRecyclerViewListener);
|
||||
} else if (viewType == TYPE_SEND_IMAGE) {
|
||||
return new SendImageHolder(parent.getContext(), parent,c,onRecyclerViewListener);
|
||||
} else if (viewType == TYPE_SEND_LOCATION) {
|
||||
return new SendLocationHolder(parent.getContext(), parent,c,onRecyclerViewListener);
|
||||
} else if (viewType == TYPE_SEND_VOICE) {
|
||||
return new SendVoiceHolder(parent.getContext(), parent,c,onRecyclerViewListener);
|
||||
} else if (viewType == TYPE_RECEIVER_TXT) {
|
||||
return new ReceiveTextHolder(parent.getContext(), parent,onRecyclerViewListener);
|
||||
} else if (viewType == TYPE_RECEIVER_IMAGE) {
|
||||
return new ReceiveImageHolder(parent.getContext(), parent,onRecyclerViewListener);
|
||||
} else if (viewType == TYPE_RECEIVER_LOCATION) {
|
||||
return new ReceiveLocationHolder(parent.getContext(), parent,onRecyclerViewListener);
|
||||
} else if (viewType == TYPE_RECEIVER_VOICE) {
|
||||
return new ReceiveVoiceHolder(parent.getContext(), parent,onRecyclerViewListener);
|
||||
} else if (viewType == TYPE_SEND_VIDEO) {
|
||||
return new SendVideoHolder(parent.getContext(), parent,c,onRecyclerViewListener);
|
||||
} else if (viewType == TYPE_RECEIVER_VIDEO) {
|
||||
return new ReceiveVideoHolder(parent.getContext(), parent,onRecyclerViewListener);
|
||||
}else if(viewType ==TYPE_AGREE) {
|
||||
return new AgreeHolder(parent.getContext(),parent,onRecyclerViewListener);
|
||||
}else{//开发者自定义的其他类型,可自行处理
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
((BaseViewHolder)holder).bindData(msgs.get(position));
|
||||
if (holder instanceof ReceiveTextHolder) {
|
||||
((ReceiveTextHolder)holder).showTime(shouldShowTime(position));
|
||||
} else if (holder instanceof ReceiveImageHolder) {
|
||||
((ReceiveImageHolder)holder).showTime(shouldShowTime(position));
|
||||
}else if (holder instanceof ReceiveLocationHolder) {
|
||||
((ReceiveLocationHolder)holder).showTime(shouldShowTime(position));
|
||||
}else if (holder instanceof ReceiveVoiceHolder) {
|
||||
((ReceiveVoiceHolder)holder).showTime(shouldShowTime(position));
|
||||
}else if (holder instanceof SendTextHolder) {
|
||||
((SendTextHolder)holder).showTime(shouldShowTime(position));
|
||||
}else if (holder instanceof SendImageHolder) {
|
||||
((SendImageHolder)holder).showTime(shouldShowTime(position));
|
||||
}else if (holder instanceof SendLocationHolder) {
|
||||
((SendLocationHolder)holder).showTime(shouldShowTime(position));
|
||||
}else if (holder instanceof SendVoiceHolder) {
|
||||
((SendVoiceHolder)holder).showTime(shouldShowTime(position));
|
||||
}else if (holder instanceof SendVideoHolder) {//随便模拟的视频类型
|
||||
((SendVideoHolder)holder).showTime(shouldShowTime(position));
|
||||
}else if (holder instanceof ReceiveVideoHolder) {
|
||||
((ReceiveVideoHolder)holder).showTime(shouldShowTime(position));
|
||||
}else if (holder instanceof AgreeHolder) {//同意添加好友成功后的消息
|
||||
((AgreeHolder)holder).showTime(shouldShowTime(position));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
BmobIMMessage message = msgs.get(position);
|
||||
if(message.getMsgType().equals(BmobIMMessageType.IMAGE.getType())){
|
||||
return message.getFromId().equals(currentUid) ? TYPE_SEND_IMAGE: TYPE_RECEIVER_IMAGE;
|
||||
}else if(message.getMsgType().equals(BmobIMMessageType.LOCATION.getType())){
|
||||
return message.getFromId().equals(currentUid) ? TYPE_SEND_LOCATION: TYPE_RECEIVER_LOCATION;
|
||||
}else if(message.getMsgType().equals(BmobIMMessageType.VOICE.getType())){
|
||||
return message.getFromId().equals(currentUid) ? TYPE_SEND_VOICE: TYPE_RECEIVER_VOICE;
|
||||
}else if(message.getMsgType().equals(BmobIMMessageType.TEXT.getType())){
|
||||
return message.getFromId().equals(currentUid) ? TYPE_SEND_TXT: TYPE_RECEIVER_TXT;
|
||||
}else if(message.getMsgType().equals(BmobIMMessageType.VIDEO.getType())){
|
||||
return message.getFromId().equals(currentUid) ? TYPE_SEND_VIDEO: TYPE_RECEIVER_VIDEO;
|
||||
}else if(message.getMsgType().equals("agree")) {//显示欢迎
|
||||
return TYPE_AGREE;
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return msgs.size();
|
||||
}
|
||||
|
||||
private OnRecyclerViewListener onRecyclerViewListener;
|
||||
|
||||
public void setOnRecyclerViewListener(OnRecyclerViewListener onRecyclerViewListener) {
|
||||
this.onRecyclerViewListener = onRecyclerViewListener;
|
||||
}
|
||||
|
||||
private boolean shouldShowTime(int position) {
|
||||
if (position == 0) {
|
||||
return true;
|
||||
}
|
||||
long lastTime = msgs.get(position - 1).getCreateTime();
|
||||
long curTime = msgs.get(position).getCreateTime();
|
||||
return curTime - lastTime > TIME_INTERVAL;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseRecyclerAdapter;
|
||||
import cn.bmob.imdemo.adapter.base.BaseRecyclerHolder;
|
||||
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
|
||||
import cn.bmob.imdemo.bean.Friend;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.db.NewFriendManager;
|
||||
|
||||
/**联系人
|
||||
* 一种简洁的Adapter实现方式,可用于多种Item布局的recycleView实现,不用再写ViewHolder啦
|
||||
* @author :smile
|
||||
* @project:ContactNewAdapter
|
||||
* @date :2016-04-27-14:18
|
||||
*/
|
||||
public class ContactAdapter extends BaseRecyclerAdapter<Friend> {
|
||||
|
||||
public static final int TYPE_NEW_FRIEND = 0;
|
||||
public static final int TYPE_ITEM = 1;
|
||||
|
||||
public ContactAdapter(Context context, IMutlipleItem<Friend> items, Collection<Friend> datas) {
|
||||
super(context,items,datas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(BaseRecyclerHolder holder, Friend friend, int position) {
|
||||
if(holder.layoutId==R.layout.item_contact){
|
||||
User user =friend.getFriendUser();
|
||||
//好友头像
|
||||
holder.setImageView(user == null ? null : user.getAvatar(), R.mipmap.head, R.id.iv_recent_avatar);
|
||||
//好友名称
|
||||
holder.setText(R.id.tv_recent_name,user==null?"未知":user.getUsername());
|
||||
}else if(holder.layoutId==R.layout.header_new_friend){
|
||||
if(NewFriendManager.getInstance(context).hasNewFriendInvitation()){
|
||||
holder.setVisible(R.id.iv_msg_tips,View.VISIBLE);
|
||||
}else{
|
||||
holder.setVisible(R.id.iv_msg_tips, View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseRecyclerAdapter;
|
||||
import cn.bmob.imdemo.adapter.base.BaseRecyclerHolder;
|
||||
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
|
||||
import cn.bmob.imdemo.bean.Conversation;
|
||||
import cn.bmob.imdemo.util.TimeUtil;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessageType;
|
||||
|
||||
/**
|
||||
* 使用进一步封装的Conversation,教大家怎么自定义会话列表
|
||||
* @author smile
|
||||
*/
|
||||
public class ConversationAdapter extends BaseRecyclerAdapter<Conversation> {
|
||||
|
||||
public ConversationAdapter(Context context, IMutlipleItem<Conversation> items, Collection<Conversation> datas) {
|
||||
super(context,items,datas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(BaseRecyclerHolder holder, Conversation conversation, int position) {
|
||||
holder.setText(R.id.tv_recent_msg,conversation.getLastMessageContent());
|
||||
holder.setText(R.id.tv_recent_time,TimeUtil.getChatTime(false,conversation.getLastMessageTime()));
|
||||
//会话图标
|
||||
Object obj = conversation.getAvatar();
|
||||
if(obj instanceof String){
|
||||
String avatar=(String)obj;
|
||||
holder.setImageView(avatar, R.mipmap.head, R.id.iv_recent_avatar);
|
||||
}else{
|
||||
int defaultRes = (int)obj;
|
||||
holder.setImageView(null, defaultRes, R.id.iv_recent_avatar);
|
||||
}
|
||||
//会话标题
|
||||
holder.setText(R.id.tv_recent_name, conversation.getcName());
|
||||
//查询指定未读消息数
|
||||
long unread = conversation.getUnReadCount();
|
||||
if(unread>0){
|
||||
holder.setVisible(R.id.tv_recent_unread, View.VISIBLE);
|
||||
holder.setText(R.id.tv_recent_unread, String.valueOf(unread));
|
||||
}else{
|
||||
holder.setVisible(R.id.tv_recent_unread, View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import cn.bmob.imdemo.Config;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseRecyclerAdapter;
|
||||
import cn.bmob.imdemo.adapter.base.BaseRecyclerHolder;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.imdemo.bean.AgreeAddFriendMessage;
|
||||
import cn.bmob.imdemo.bean.Friend;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
import cn.bmob.imdemo.db.NewFriendManager;
|
||||
import cn.bmob.imdemo.model.UserModel;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.core.BmobIMClient;
|
||||
import cn.bmob.newim.listener.MessageSendListener;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
import cn.bmob.v3.listener.SaveListener;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:NewFriendAdapter
|
||||
* @date :2016-04-27-14:18
|
||||
*/
|
||||
public class NewFriendAdapter extends BaseRecyclerAdapter<NewFriend>{
|
||||
|
||||
public NewFriendAdapter(Context context, IMutlipleItem<NewFriend> items, Collection<NewFriend> datas) {
|
||||
super(context,items,datas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(final BaseRecyclerHolder holder, final NewFriend add, int position) {
|
||||
holder.setImageView(add == null ? null : add.getAvatar(), R.mipmap.head, R.id.iv_recent_avatar);
|
||||
holder.setText(R.id.tv_recent_name,add==null?"未知":add.getName());
|
||||
holder.setText(R.id.tv_recent_msg,add==null?"未知":add.getMsg());
|
||||
Integer status =add.getStatus();
|
||||
Logger.i("bindData:"+status+","+add.getUid()+","+add.getTime());
|
||||
if(status==null || status== Config.STATUS_VERIFY_NONE||status ==Config.STATUS_VERIFY_READED){//未添加/已读未添加
|
||||
holder.setText(R.id.btn_aggree,"接受");
|
||||
holder.setEnabled(R.id.btn_aggree,true);
|
||||
holder.setOnClickListener(R.id.btn_aggree,new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {//发送消息
|
||||
agreeAdd(add, new SaveListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
holder.setText(R.id.btn_aggree,"已添加");
|
||||
holder.setEnabled(R.id.btn_aggree,false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int i, String s) {
|
||||
holder.setEnabled(R.id.btn_aggree,true);
|
||||
toast("添加好友失败:" + s);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}else{
|
||||
holder.setText(R.id.btn_aggree,"已添加");
|
||||
holder.setEnabled(R.id.btn_aggree,false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加到好友表中...
|
||||
* @param add
|
||||
* @param listener
|
||||
*/
|
||||
private void agreeAdd(final NewFriend add, final SaveListener listener){
|
||||
User user =new User();
|
||||
user.setObjectId(add.getUid());
|
||||
UserModel.getInstance().agreeAddFriend(user, new SaveListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
sendAgreeAddFriendMessage(add, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int i, String s) {
|
||||
listener.onFailure(i, s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送同意添加好友的请求
|
||||
*/
|
||||
private void sendAgreeAddFriendMessage(final NewFriend add,final SaveListener listener){
|
||||
BmobIMUserInfo info = new BmobIMUserInfo(add.getUid(), add.getName(), add.getAvatar());
|
||||
//如果为true,则表明为暂态会话,也就是说该会话仅执行发送消息的操作,不会保存会话和消息到本地数据库中
|
||||
BmobIMConversation c = BmobIM.getInstance().startPrivateConversation(info,true,null);
|
||||
//这个obtain方法才是真正创建一个管理消息发送的会话
|
||||
BmobIMConversation conversation = BmobIMConversation.obtain(BmobIMClient.getInstance(),c);
|
||||
//而AgreeAddFriendMessage的isTransient设置为false,表明我希望在对方的会话数据库中保存该类型的消息
|
||||
AgreeAddFriendMessage msg =new AgreeAddFriendMessage();
|
||||
User currentUser = BmobUser.getCurrentUser(context, User.class);
|
||||
msg.setContent("我通过了你的好友验证请求,我们可以开始聊天了!");//---这句话是直接存储到对方的消息表中的
|
||||
Map<String,Object> map =new HashMap<>();
|
||||
map.put("msg",currentUser.getUsername()+"同意添加你为好友");//显示在通知栏上面的内容
|
||||
map.put("uid",add.getUid());//发送者的uid-方便请求添加的发送方找到该条添加好友的请求
|
||||
map.put("time", add.getTime());//添加好友的请求时间
|
||||
msg.setExtraMap(map);
|
||||
conversation.sendMessage(msg, new MessageSendListener() {
|
||||
@Override
|
||||
public void done(BmobIMMessage msg, BmobException e){
|
||||
if (e == null) {//发送成功
|
||||
//修改本地的好友请求记录
|
||||
NewFriendManager.getInstance(context).updateNewFriend(add,Config.STATUS_VERIFIED);
|
||||
listener.onSuccess();
|
||||
} else {//发送失败
|
||||
listener.onFailure(e.getErrorCode(),e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.MediaPlayer.OnPreparedListener;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.newim.bean.BmobIMAudioMessage;
|
||||
import cn.bmob.newim.core.BmobDownloadManager;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
|
||||
public class NewRecordPlayClickListener implements View.OnClickListener {
|
||||
|
||||
BmobIMAudioMessage message;
|
||||
ImageView iv_voice;
|
||||
private AnimationDrawable anim = null;
|
||||
Context mContext;
|
||||
String currentObjectId = "";
|
||||
MediaPlayer mediaPlayer = null;
|
||||
public static boolean isPlaying = false;
|
||||
public static NewRecordPlayClickListener currentPlayListener = null;
|
||||
static BmobIMAudioMessage currentMsg = null;
|
||||
|
||||
public NewRecordPlayClickListener(Context context, BmobIMAudioMessage msg,ImageView voice) {
|
||||
this.iv_voice = voice;
|
||||
this.message = msg;
|
||||
this.mContext = context.getApplicationContext();
|
||||
currentMsg = msg;
|
||||
currentPlayListener = this;
|
||||
try {
|
||||
currentObjectId = BmobUser.getCurrentUser(mContext).getObjectId();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public void startPlayRecord(String filePath, boolean isUseSpeaker) {
|
||||
if (!(new File(filePath).exists())) {
|
||||
return;
|
||||
}
|
||||
AudioManager audioManager = (AudioManager) mContext
|
||||
.getSystemService(Context.AUDIO_SERVICE);
|
||||
mediaPlayer = new MediaPlayer();
|
||||
if (isUseSpeaker) {
|
||||
audioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
audioManager.setSpeakerphoneOn(true);
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_RING);
|
||||
} else {
|
||||
audioManager.setSpeakerphoneOn(false);
|
||||
audioManager.setMode(AudioManager.MODE_IN_CALL);
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
|
||||
}
|
||||
|
||||
try {
|
||||
mediaPlayer.reset();
|
||||
// 单独使用此方法会报错播放错误:setDataSourceFD failed.: status=0x80000000
|
||||
// mediaPlayer.setDataSource(filePath);
|
||||
// 因此采用此方式会避免这种错误
|
||||
FileInputStream fis = new FileInputStream(new File(filePath));
|
||||
mediaPlayer.setDataSource(fis.getFD());
|
||||
mediaPlayer.prepare();
|
||||
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
|
||||
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer arg0) {
|
||||
isPlaying = true;
|
||||
currentMsg = message;
|
||||
arg0.start();
|
||||
startRecordAnimation();
|
||||
}
|
||||
});
|
||||
mediaPlayer
|
||||
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
stopPlayRecord();
|
||||
}
|
||||
|
||||
});
|
||||
currentPlayListener = this;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopPlayRecord() {
|
||||
stopRecordAnimation();
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.stop();
|
||||
mediaPlayer.release();
|
||||
}
|
||||
isPlaying = false;
|
||||
}
|
||||
|
||||
private void startRecordAnimation() {
|
||||
if (message.getFromId().equals(currentObjectId)) {
|
||||
iv_voice.setImageResource(R.drawable.anim_chat_voice_right);
|
||||
} else {
|
||||
iv_voice.setImageResource(R.drawable.anim_chat_voice_left);
|
||||
}
|
||||
anim = (AnimationDrawable) iv_voice.getDrawable();
|
||||
anim.start();
|
||||
}
|
||||
|
||||
private void stopRecordAnimation() {
|
||||
if (message.getFromId().equals(currentObjectId)) {
|
||||
iv_voice.setImageResource(R.mipmap.voice_left3);
|
||||
} else {
|
||||
iv_voice.setImageResource(R.mipmap.voice_right3);
|
||||
}
|
||||
if (anim != null) {
|
||||
anim.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View arg0) {
|
||||
if (isPlaying) {
|
||||
currentPlayListener.stopPlayRecord();
|
||||
if (currentMsg != null
|
||||
&& currentMsg.hashCode() == message.hashCode()) {
|
||||
currentMsg = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (message.getFromId().equals(currentObjectId)) {// 如果是自己发送的语音消息,则播放本地地址
|
||||
String localPath = message.getContent().split("&")[0];
|
||||
startPlayRecord(localPath, true);
|
||||
} else {// 如果是收到的消息,则需要先下载后播放
|
||||
String localPath = BmobDownloadManager.getDownLoadFilePath(message);
|
||||
startPlayRecord(localPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
/**为RecycleView添加点击事件
|
||||
* @author smile
|
||||
* @project OnRecyclerViewListener
|
||||
* @date 2016-03-03-16:39
|
||||
*/
|
||||
public interface OnRecyclerViewListener {
|
||||
void onItemClick(int position);
|
||||
boolean onItemLongClick(int position);
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMImageMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
|
||||
/**
|
||||
* 接收到的文本类型
|
||||
*/
|
||||
public class ReceiveImageHolder extends BaseViewHolder {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.iv_picture)
|
||||
protected ImageView iv_picture;
|
||||
@Bind(R.id.progress_load)
|
||||
protected ProgressBar progress_load;
|
||||
|
||||
public ReceiveImageHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
|
||||
super(context, root, R.layout.item_chat_received_image,onRecyclerViewListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
BmobIMMessage msg = (BmobIMMessage)o;
|
||||
//用户信息的获取必须在buildFromDB之前,否则会报错'Entity is detached from DAO context'
|
||||
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
|
||||
String time = dateFormat.format(msg.getCreateTime());
|
||||
tv_time.setText(time);
|
||||
//可使用buildFromDB方法转化为指定类型的消息
|
||||
final BmobIMImageMessage message = BmobIMImageMessage.buildFromDB(false,msg);
|
||||
//显示图片
|
||||
ImageLoaderFactory.getLoader().load(iv_picture,message.getRemoteUrl(), R.mipmap.ic_launcher,new ImageLoadingListener(){;
|
||||
|
||||
@Override
|
||||
public void onLoadingStarted(String s, View view) {
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingComplete(String s, View view, Bitmap bitmap) {
|
||||
progress_load.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingCancelled(String s, View view) {
|
||||
progress_load.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingFailed(String s, View view, FailReason failReason) {
|
||||
progress_load.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击" + info.getName() + "的头像");
|
||||
}
|
||||
});
|
||||
|
||||
iv_picture.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击图片:"+message.getRemoteUrl()+"");
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
iv_picture.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMLocationMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
|
||||
/**
|
||||
* 接收到的位置类型
|
||||
*/
|
||||
public class ReceiveLocationHolder extends BaseViewHolder {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.tv_location)
|
||||
protected TextView tv_location;
|
||||
|
||||
public ReceiveLocationHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
|
||||
super(context, root, R.layout.item_chat_received_location,onRecyclerViewListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
BmobIMMessage msg = (BmobIMMessage)o;
|
||||
//用户信息的获取必须在buildFromDB之前,否则会报错'Entity is detached from DAO context'
|
||||
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
|
||||
//加载头像
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
|
||||
String time = dateFormat.format(msg.getCreateTime());
|
||||
tv_time.setText(time);
|
||||
//
|
||||
final BmobIMLocationMessage message = BmobIMLocationMessage.buildFromDB(msg);
|
||||
tv_location.setText(message.getAddress());
|
||||
//
|
||||
tv_location.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("经度:" + message.getLongitude() + ",维度:" + message.getLatitude());
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
});
|
||||
tv_location.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击"+info.getName()+"头像");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.OnClick;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
|
||||
/**
|
||||
* 接收到的文本类型
|
||||
*/
|
||||
public class ReceiveTextHolder extends BaseViewHolder {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.tv_message)
|
||||
protected TextView tv_message;
|
||||
|
||||
public ReceiveTextHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
|
||||
super(context, root, R.layout.item_chat_received_message,onRecyclerViewListener);
|
||||
}
|
||||
|
||||
@OnClick({R.id.iv_avatar})
|
||||
public void onAvatarClick(View view) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
final BmobIMMessage message = (BmobIMMessage)o;
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
|
||||
String time = dateFormat.format(message.getCreateTime());
|
||||
tv_time.setText(time);
|
||||
final BmobIMUserInfo info = message.getBmobIMUserInfo();
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
|
||||
String content = message.getContent();
|
||||
tv_message.setText(content);
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击" + info.getName() + "的头像");
|
||||
}
|
||||
});
|
||||
tv_message.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击"+message.getContent());
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tv_message.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.OnClick;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
|
||||
/**
|
||||
* 接收到的视频类型--这是举个例子,并没有展示出视频缩略图等信息,开发者可自行设置
|
||||
*/
|
||||
public class ReceiveVideoHolder extends BaseViewHolder {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.tv_message)
|
||||
protected TextView tv_message;
|
||||
|
||||
public ReceiveVideoHolder(Context context, ViewGroup root, OnRecyclerViewListener onRecyclerViewListener) {
|
||||
super(context, root, R.layout.item_chat_received_message,onRecyclerViewListener);
|
||||
}
|
||||
|
||||
@OnClick({R.id.iv_avatar})
|
||||
public void onAvatarClick(View view) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
final BmobIMMessage message = (BmobIMMessage)o;
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
|
||||
String time = dateFormat.format(message.getCreateTime());
|
||||
tv_time.setText(time);
|
||||
final BmobIMUserInfo info = message.getBmobIMUserInfo();
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
|
||||
String content = message.getContent();
|
||||
tv_message.setText("接收到的视频文件:"+content);
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击" + info.getName() + "的头像");
|
||||
}
|
||||
});
|
||||
|
||||
tv_message.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击"+message.getContent());
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tv_message.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMAudioMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.core.BmobDownloadManager;
|
||||
import cn.bmob.newim.listener.FileDownloadListener;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
|
||||
/**
|
||||
* 接收到的文本类型
|
||||
*/
|
||||
public class ReceiveVoiceHolder extends BaseViewHolder {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.tv_voice_length)
|
||||
protected TextView tv_voice_length;
|
||||
@Bind(R.id.iv_voice)
|
||||
protected ImageView iv_voice;
|
||||
|
||||
@Bind(R.id.progress_load)
|
||||
protected ProgressBar progress_load;
|
||||
|
||||
private String currentUid="";
|
||||
|
||||
public ReceiveVoiceHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
|
||||
super(context, root, R.layout.item_chat_received_voice,onRecyclerViewListener);
|
||||
try {
|
||||
currentUid = BmobUser.getCurrentUser(context).getObjectId();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
BmobIMMessage msg = (BmobIMMessage)o;
|
||||
//用户信息的获取必须在buildFromDB之前,否则会报错'Entity is detached from DAO context'
|
||||
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
|
||||
String time = dateFormat.format(msg.getCreateTime());
|
||||
tv_time.setText(time);
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击" + info.getName() + "的头像");
|
||||
}
|
||||
});
|
||||
//显示特有属性
|
||||
final BmobIMAudioMessage message = BmobIMAudioMessage.buildFromDB(false, msg);
|
||||
boolean isExists = BmobDownloadManager.isAudioExist(currentUid, message);
|
||||
if(!isExists){//若指定格式的录音文件不存在,则需要下载,因为其文件比较小,故放在此下载
|
||||
BmobDownloadManager downloadTask = new BmobDownloadManager(getContext(),msg,new FileDownloadListener() {
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
tv_voice_length.setVisibility(View.GONE);
|
||||
iv_voice.setVisibility(View.INVISIBLE);//只有下载完成才显示播放的按钮
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done(BmobException e) {
|
||||
if(e==null){
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_voice_length.setVisibility(View.VISIBLE);
|
||||
tv_voice_length.setText(message.getDuration()+"\''");
|
||||
iv_voice.setVisibility(View.VISIBLE);
|
||||
}else{
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_voice_length.setVisibility(View.GONE);
|
||||
iv_voice.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
downloadTask.execute(message.getContent());
|
||||
}else{
|
||||
tv_voice_length.setVisibility(View.VISIBLE);
|
||||
tv_voice_length.setText(message.getDuration() + "\''");
|
||||
}
|
||||
iv_voice.setOnClickListener(new NewRecordPlayClickListener(getContext(), message, iv_voice));
|
||||
|
||||
iv_voice.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:SearchUserAdapter
|
||||
* @date :2016-01-22-14:18
|
||||
*/
|
||||
public class SearchUserAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
|
||||
|
||||
private List<User> users = new ArrayList<>();
|
||||
|
||||
public SearchUserAdapter() {
|
||||
}
|
||||
|
||||
public void setDatas(List<User> list) {
|
||||
users.clear();
|
||||
if (null != list) {
|
||||
users.addAll(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**获取用户
|
||||
* @param position
|
||||
* @return
|
||||
*/
|
||||
public User getItem(int position){
|
||||
return users.get(position);
|
||||
}
|
||||
|
||||
private OnRecyclerViewListener onRecyclerViewListener;
|
||||
|
||||
public void setOnRecyclerViewListener(OnRecyclerViewListener onRecyclerViewListener) {
|
||||
this.onRecyclerViewListener = onRecyclerViewListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new SearchUserHolder(parent.getContext(), parent, onRecyclerViewListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
((BaseViewHolder)holder).bindData(users.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return users.size();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.ui.UserInfoActivity;
|
||||
|
||||
public class SearchUserHolder extends BaseViewHolder {
|
||||
|
||||
@Bind(R.id.avatar)
|
||||
public ImageView avatar;
|
||||
@Bind(R.id.name)
|
||||
public TextView name;
|
||||
@Bind(R.id.btn_add)
|
||||
public Button btn_add;
|
||||
|
||||
public SearchUserHolder(Context context, ViewGroup root,OnRecyclerViewListener onRecyclerViewListener) {
|
||||
super(context, root, R.layout.item_search_user,onRecyclerViewListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
final User user =(User)o;
|
||||
ImageLoaderFactory.getLoader().loadAvator(avatar,user.getAvatar(), R.mipmap.head);
|
||||
name.setText(user.getUsername());
|
||||
btn_add.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {//查看个人详情
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("u", user);
|
||||
startActivity(UserInfoActivity.class,bundle);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMImageMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMSendStatus;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.listener.MessageSendListener;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
|
||||
/**
|
||||
* 发送的文本类型
|
||||
*/
|
||||
public class SendImageHolder extends BaseViewHolder {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.iv_fail_resend)
|
||||
protected ImageView iv_fail_resend;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.iv_picture)
|
||||
protected ImageView iv_picture;
|
||||
|
||||
@Bind(R.id.tv_send_status)
|
||||
protected TextView tv_send_status;
|
||||
|
||||
@Bind(R.id.progress_load)
|
||||
protected ProgressBar progress_load;
|
||||
BmobIMConversation c;
|
||||
|
||||
public SendImageHolder(Context context, ViewGroup root,BmobIMConversation c,OnRecyclerViewListener onRecyclerViewListener) {
|
||||
super(context, root, R.layout.item_chat_sent_image,onRecyclerViewListener);
|
||||
this.c =c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
BmobIMMessage msg = (BmobIMMessage)o;
|
||||
//用户信息的获取必须在buildFromDB之前,否则会报错'Entity is detached from DAO context'
|
||||
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null,R.mipmap.head);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
|
||||
String time = dateFormat.format(msg.getCreateTime());
|
||||
tv_time.setText(time);
|
||||
//
|
||||
final BmobIMImageMessage message = BmobIMImageMessage.buildFromDB(true, msg);
|
||||
int status =message.getSendStatus();
|
||||
if (status == BmobIMSendStatus.SENDFAILED.getStatus() ||status == BmobIMSendStatus.UPLOADAILED.getStatus()) {
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
tv_send_status.setVisibility(View.VISIBLE);
|
||||
tv_send_status.setText("已发送");
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
//发送的不是远程图片地址,则取本地地址
|
||||
ImageLoaderFactory.getLoader().load(iv_picture,TextUtils.isEmpty(message.getRemoteUrl()) ? message.getLocalPath():message.getRemoteUrl(),R.mipmap.ic_launcher,null);
|
||||
// ViewUtil.setPicture(TextUtils.isEmpty(message.getRemoteUrl()) ? message.getLocalPath():message.getRemoteUrl(), R.mipmap.ic_launcher, iv_picture,null);
|
||||
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击" + info.getName() + "的头像");
|
||||
}
|
||||
});
|
||||
iv_picture.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击图片:"+(TextUtils.isEmpty(message.getRemoteUrl()) ? message.getLocalPath():message.getRemoteUrl())+"");
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
iv_picture.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
//重发
|
||||
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
c.resendMessage(message, new MessageSendListener() {
|
||||
@Override
|
||||
public void onStart(BmobIMMessage msg) {
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done(BmobIMMessage msg, BmobException e) {
|
||||
if (e == null) {
|
||||
tv_send_status.setVisibility(View.VISIBLE);
|
||||
tv_send_status.setText("已发送");
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
} else {
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMLocationMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMSendStatus;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.listener.MessageSendListener;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
|
||||
/**
|
||||
* 发送的语音类型
|
||||
*/
|
||||
public class SendLocationHolder extends BaseViewHolder {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.iv_fail_resend)
|
||||
protected ImageView iv_fail_resend;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.layout_location)
|
||||
protected LinearLayout layout_location;
|
||||
|
||||
@Bind(R.id.tv_location)
|
||||
protected TextView tv_location;
|
||||
|
||||
@Bind(R.id.tv_send_status)
|
||||
protected TextView tv_send_status;
|
||||
|
||||
@Bind(R.id.progress_load)
|
||||
protected ProgressBar progress_load;
|
||||
BmobIMConversation c;
|
||||
public SendLocationHolder(Context context, ViewGroup root,BmobIMConversation c,OnRecyclerViewListener onRecyclerViewListener) {
|
||||
super(context, root, R.layout.item_chat_sent_location,onRecyclerViewListener);
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
BmobIMMessage msg = (BmobIMMessage)o;
|
||||
//用户信息的获取必须在buildFromDB之前,否则会报错'Entity is detached from DAO context'
|
||||
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
|
||||
String time = dateFormat.format(msg.getCreateTime());
|
||||
tv_time.setText(time);
|
||||
|
||||
final BmobIMLocationMessage message = BmobIMLocationMessage.buildFromDB(msg);
|
||||
tv_location.setText(message.getAddress());
|
||||
int status =message.getSendStatus();
|
||||
if (status == BmobIMSendStatus.SENDFAILED.getStatus()) {
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
}
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击" + info.getName() + "的头像");
|
||||
}
|
||||
});
|
||||
|
||||
tv_location.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("经度:" + message.getLongitude() + ",维度:" + message.getLatitude());
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
});
|
||||
tv_location.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
//重发
|
||||
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
c.resendMessage(message, new MessageSendListener() {
|
||||
@Override
|
||||
public void onStart(BmobIMMessage msg) {
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done(BmobIMMessage msg, BmobException e) {
|
||||
if (e == null) {
|
||||
tv_send_status.setVisibility(View.VISIBLE);
|
||||
tv_send_status.setText("已发送");
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
} else {
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMSendStatus;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.listener.MessageSendListener;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
|
||||
/**
|
||||
* 发送的文本类型
|
||||
*/
|
||||
public class SendTextHolder extends BaseViewHolder implements View.OnClickListener,View.OnLongClickListener {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.iv_fail_resend)
|
||||
protected ImageView iv_fail_resend;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.tv_message)
|
||||
protected TextView tv_message;
|
||||
@Bind(R.id.tv_send_status)
|
||||
protected TextView tv_send_status;
|
||||
|
||||
@Bind(R.id.progress_load)
|
||||
protected ProgressBar progress_load;
|
||||
|
||||
BmobIMConversation c;
|
||||
|
||||
public SendTextHolder(Context context, ViewGroup root,BmobIMConversation c,OnRecyclerViewListener listener) {
|
||||
super(context, root, R.layout.item_chat_sent_message, listener);
|
||||
this.c =c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
final BmobIMMessage message = (BmobIMMessage)o;
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
final BmobIMUserInfo info = message.getBmobIMUserInfo();
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
|
||||
String time = dateFormat.format(message.getCreateTime());
|
||||
String content = message.getContent();
|
||||
tv_message.setText(content);
|
||||
tv_time.setText(time);
|
||||
|
||||
int status =message.getSendStatus();
|
||||
if (status == BmobIMSendStatus.SENDFAILED.getStatus()) {
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
tv_message.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击"+message.getContent());
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tv_message.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击" + info.getName() + "的头像");
|
||||
}
|
||||
});
|
||||
|
||||
//重发
|
||||
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
c.resendMessage(message, new MessageSendListener() {
|
||||
@Override
|
||||
public void onStart(BmobIMMessage msg) {
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done(BmobIMMessage msg, BmobException e) {
|
||||
if(e==null){
|
||||
tv_send_status.setVisibility(View.VISIBLE);
|
||||
tv_send_status.setText("已发送");
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
}else{
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMSendStatus;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.listener.MessageSendListener;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
|
||||
/**
|
||||
* 发送的视频类型---这是举个例子,并没有展示出视频缩略图等信息,开发者可自行实现
|
||||
*/
|
||||
public class SendVideoHolder extends BaseViewHolder implements View.OnClickListener,View.OnLongClickListener {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.iv_fail_resend)
|
||||
protected ImageView iv_fail_resend;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.tv_message)
|
||||
protected TextView tv_message;
|
||||
@Bind(R.id.tv_send_status)
|
||||
protected TextView tv_send_status;
|
||||
|
||||
@Bind(R.id.progress_load)
|
||||
protected ProgressBar progress_load;
|
||||
|
||||
BmobIMConversation c;
|
||||
|
||||
public SendVideoHolder(Context context, ViewGroup root, BmobIMConversation c, OnRecyclerViewListener listener) {
|
||||
super(context, root, R.layout.item_chat_sent_message, listener);
|
||||
this.c =c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
final BmobIMMessage message = (BmobIMMessage)o;
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
final BmobIMUserInfo info = message.getBmobIMUserInfo();
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
|
||||
|
||||
String time = dateFormat.format(message.getCreateTime());
|
||||
String content = message.getContent();
|
||||
tv_message.setText("发送的视频文件:"+content);
|
||||
tv_time.setText(time);
|
||||
|
||||
int status =message.getSendStatus();
|
||||
if (status == BmobIMSendStatus.SENDFAILED.getStatus()) {
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
tv_message.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击"+message.getContent());
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tv_message.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击" + info.getName() + "的头像");
|
||||
}
|
||||
});
|
||||
|
||||
//重发
|
||||
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
c.resendMessage(message, new MessageSendListener() {
|
||||
@Override
|
||||
public void onStart(BmobIMMessage msg) {
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done(BmobIMMessage msg, BmobException e) {
|
||||
if(e==null){
|
||||
tv_send_status.setVisibility(View.VISIBLE);
|
||||
tv_send_status.setText("已发送");
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
}else{
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
package cn.bmob.imdemo.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.base.BaseViewHolder;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.newim.bean.BmobIMAudioMessage;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMSendStatus;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.listener.MessageSendListener;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
|
||||
/**
|
||||
* 发送的语音类型
|
||||
*/
|
||||
public class SendVoiceHolder extends BaseViewHolder {
|
||||
|
||||
@Bind(R.id.iv_avatar)
|
||||
protected ImageView iv_avatar;
|
||||
|
||||
@Bind(R.id.iv_fail_resend)
|
||||
protected ImageView iv_fail_resend;
|
||||
|
||||
@Bind(R.id.tv_time)
|
||||
protected TextView tv_time;
|
||||
|
||||
@Bind(R.id.tv_voice_length)
|
||||
protected TextView tv_voice_length;
|
||||
@Bind(R.id.iv_voice)
|
||||
protected ImageView iv_voice;
|
||||
|
||||
@Bind(R.id.tv_send_status)
|
||||
protected TextView tv_send_status;
|
||||
|
||||
@Bind(R.id.progress_load)
|
||||
protected ProgressBar progress_load;
|
||||
|
||||
BmobIMConversation c;
|
||||
public SendVoiceHolder(Context context, ViewGroup root,BmobIMConversation c,OnRecyclerViewListener onRecyclerViewListener) {
|
||||
super(context, root, R.layout.item_chat_sent_voice,onRecyclerViewListener);
|
||||
this.c =c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindData(Object o) {
|
||||
BmobIMMessage msg = (BmobIMMessage)o;
|
||||
//用户信息的获取必须在buildFromDB之前,否则会报错'Entity is detached from DAO context'
|
||||
final BmobIMUserInfo info = msg.getBmobIMUserInfo();
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avatar,info != null ? info.getAvatar() : null, R.mipmap.head);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");
|
||||
String time = dateFormat.format(msg.getCreateTime());
|
||||
tv_time.setText(time);
|
||||
//使用buildFromDB方法转化成指定类型的消息
|
||||
final BmobIMAudioMessage message = BmobIMAudioMessage.buildFromDB(true,msg);
|
||||
tv_voice_length.setText(message.getDuration()+"\''");
|
||||
|
||||
int status =message.getSendStatus();
|
||||
if (status == BmobIMSendStatus.SENDFAILED.getStatus()||status == BmobIMSendStatus.UPLOADAILED.getStatus()) {//发送失败/上传失败
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
tv_voice_length.setVisibility(View.INVISIBLE);
|
||||
} else if (status== BmobIMSendStatus.SENDING.getStatus()) {
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
tv_voice_length.setVisibility(View.INVISIBLE);
|
||||
} else {//发送成功
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.GONE);
|
||||
tv_voice_length.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
iv_voice.setOnClickListener(new NewRecordPlayClickListener(getContext(),message,iv_voice));
|
||||
|
||||
iv_voice.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onRecyclerViewListener != null) {
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
iv_avatar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toast("点击" + info.getName() + "的头像");
|
||||
}
|
||||
});
|
||||
//重发
|
||||
iv_fail_resend.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
c.resendMessage(message, new MessageSendListener() {
|
||||
@Override
|
||||
public void onStart(BmobIMMessage msg) {
|
||||
progress_load.setVisibility(View.VISIBLE);
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done(BmobIMMessage msg, BmobException e) {
|
||||
if(e==null){
|
||||
tv_send_status.setVisibility(View.VISIBLE);
|
||||
tv_send_status.setText("已发送");
|
||||
iv_fail_resend.setVisibility(View.GONE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
}else{
|
||||
iv_fail_resend.setVisibility(View.VISIBLE);
|
||||
progress_load.setVisibility(View.GONE);
|
||||
tv_send_status.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showTime(boolean isShow) {
|
||||
tv_time.setVisibility(isShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
package cn.bmob.imdemo.adapter.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
|
||||
import cn.bmob.imdemo.base.BaseActivity;
|
||||
|
||||
|
||||
/**
|
||||
* 支持添加自定义头部布局;
|
||||
* 支持扩展多种item布局;
|
||||
* 支持设置recycleview点击/长按事件
|
||||
* @param <T>
|
||||
* @author smile
|
||||
* @link https://github.com/bodismile/BaseRecyclerAdapter
|
||||
*/
|
||||
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseRecyclerHolder> {
|
||||
/**
|
||||
* 默认布局
|
||||
*/
|
||||
private final int TYPE_DEFAULT = 0;
|
||||
/**
|
||||
* 当list没有值得时候显示的布局
|
||||
*/
|
||||
private final int TYPE_HEADER = 1;
|
||||
/**
|
||||
* 多重布局
|
||||
*/
|
||||
private final int TYPE_MUTIPLE = 2;
|
||||
/**
|
||||
* 带header的多重布局
|
||||
*/
|
||||
private final int TYPE_MUTIPLE_HEADER = 3;
|
||||
|
||||
protected final Context context;
|
||||
protected List<T> lists;
|
||||
protected IMutlipleItem<T> items;
|
||||
protected OnRecyclerViewListener listener;
|
||||
|
||||
/**
|
||||
* 支持一种或多种Item布局
|
||||
*
|
||||
* @param context
|
||||
* @param items
|
||||
* @param datas
|
||||
*/
|
||||
public BaseRecyclerAdapter(Context context, IMutlipleItem<T> items, Collection<T> datas) {
|
||||
this.context = context;
|
||||
this.items = items;
|
||||
this.lists = datas == null ? new ArrayList<T>() : new ArrayList<T>(datas);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定数据
|
||||
* @param datas
|
||||
* @return
|
||||
*/
|
||||
public BaseRecyclerAdapter<T> bindDatas(Collection<T> datas) {
|
||||
this.lists = datas == null ? new ArrayList<T>() : new ArrayList<T>(datas);
|
||||
notifyDataSetChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除数据
|
||||
* @param position
|
||||
*/
|
||||
public void remove(int position) {
|
||||
int more = getItemCount() - lists.size();
|
||||
lists.remove(position - more);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定position的Item
|
||||
* @param position
|
||||
* @return
|
||||
*/
|
||||
public T getItem(int position) {
|
||||
int more = getItemCount() - lists.size();
|
||||
return lists.get(position - more);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
int layoutId = items.getItemLayoutId(viewType);
|
||||
LayoutInflater inflater = LayoutInflater.from(context);
|
||||
View root = inflater.inflate(layoutId, parent, false);
|
||||
return new BaseRecyclerHolder(layoutId, root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(BaseRecyclerHolder holder, int position) {
|
||||
int type = getViewTypeByPosition(position);
|
||||
if(type==TYPE_HEADER){
|
||||
bindView(holder, null, position);
|
||||
}else if(type==TYPE_MUTIPLE){
|
||||
bindView(holder, lists.get(position), position);
|
||||
}else if(type==TYPE_MUTIPLE_HEADER){
|
||||
int headerCount = getItemCount() - lists.size();
|
||||
bindView(holder, lists.get(position - headerCount), position);
|
||||
}else{
|
||||
bindView(holder, null, position);
|
||||
}
|
||||
holder.itemView.setOnClickListener(getOnClickListener(position));
|
||||
holder.itemView.setOnLongClickListener(getOnLongClickListener(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
if (items != null) {//当有多重布局的时候,则采用多重布局
|
||||
return items.getItemCount(lists);
|
||||
}
|
||||
return lists.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
int type = getViewTypeByPosition(position);
|
||||
if(type==TYPE_HEADER){
|
||||
return items.getItemViewType(position, null);
|
||||
}else if(type==TYPE_MUTIPLE){
|
||||
return items.getItemViewType(position, lists.get(position));
|
||||
}else if(type==TYPE_MUTIPLE_HEADER){
|
||||
int headerCount = getItemCount() - lists.size();
|
||||
return items.getItemViewType(position, lists.get(position - headerCount));
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**获取指定position的布局类型
|
||||
* @param position
|
||||
*/
|
||||
private int getViewTypeByPosition(int position) {
|
||||
if (items == null) {//默认布局
|
||||
return TYPE_DEFAULT;
|
||||
} else {//多布局
|
||||
if (lists != null && lists.size() > 0) {//list有值的时候
|
||||
if (getItemCount() > lists.size()) {//是否有自定义的Header
|
||||
int headerCount = getItemCount() - lists.size();
|
||||
if (position >= headerCount) {//当前位置大于header个数
|
||||
return TYPE_MUTIPLE_HEADER;
|
||||
} else {//当前点击的是header
|
||||
return TYPE_HEADER;
|
||||
}
|
||||
} else {
|
||||
return TYPE_MUTIPLE;
|
||||
}
|
||||
} else {//list还没有值的时候
|
||||
return TYPE_HEADER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置点击/长按等事件监听器
|
||||
* @param onRecyclerViewListener
|
||||
*/
|
||||
public void setOnRecyclerViewListener(OnRecyclerViewListener onRecyclerViewListener) {
|
||||
this.listener = onRecyclerViewListener;
|
||||
}
|
||||
|
||||
public View.OnClickListener getOnClickListener(final int position) {
|
||||
return new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null && v != null) {
|
||||
listener.onItemClick(position);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public View.OnLongClickListener getOnLongClickListener(final int position) {
|
||||
return new View.OnLongClickListener() {
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (listener != null && v != null) {
|
||||
listener.onItemLongClick(position);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 需实现此方法
|
||||
* @param holder
|
||||
* @param item
|
||||
*/
|
||||
public abstract void bindView(BaseRecyclerHolder holder, T item, int position);
|
||||
|
||||
private Toast toast;
|
||||
public void toast(final Object obj) {
|
||||
try {
|
||||
((BaseActivity)context).runOnUiThread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (toast == null)
|
||||
toast = Toast.makeText(context,"", Toast.LENGTH_SHORT);
|
||||
toast.setText(obj.toString());
|
||||
toast.show();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package cn.bmob.imdemo.adapter.base;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
|
||||
/**
|
||||
* 与BaseRecyclerAdapter一起使用
|
||||
*
|
||||
*/
|
||||
public class BaseRecyclerHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private final SparseArray<View> mViews;
|
||||
public int layoutId;
|
||||
|
||||
public BaseRecyclerHolder(int layoutId,View itemView) {
|
||||
super(itemView);
|
||||
this.layoutId =layoutId;
|
||||
this.mViews = new SparseArray<>(8);
|
||||
}
|
||||
|
||||
public SparseArray<View> getAllView() {
|
||||
return mViews;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param viewId
|
||||
* @return
|
||||
*/
|
||||
protected <T extends View> T getView(int viewId) {
|
||||
View view = mViews.get(viewId);
|
||||
if (view == null) {
|
||||
view = itemView.findViewById(viewId);
|
||||
mViews.put(viewId, view);
|
||||
}
|
||||
return (T) view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param viewId
|
||||
* @param text
|
||||
* @return
|
||||
*/
|
||||
public BaseRecyclerHolder setText(int viewId, String text) {
|
||||
TextView view = getView(viewId);
|
||||
view.setText(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置Enabled
|
||||
* @param viewId
|
||||
* @param enable
|
||||
* @return
|
||||
*/
|
||||
public BaseRecyclerHolder setEnabled(int viewId,boolean enable){
|
||||
View v = getView(viewId);
|
||||
v.setEnabled(enable);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击事件
|
||||
* @param viewId
|
||||
* @param listener
|
||||
* @return
|
||||
*/
|
||||
public BaseRecyclerHolder setOnClickListener(int viewId, View.OnClickListener listener){
|
||||
View v = getView(viewId);
|
||||
v.setOnClickListener(listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param viewId
|
||||
* @param visibility
|
||||
* @return
|
||||
*/
|
||||
public BaseRecyclerHolder setVisible(int viewId,int visibility) {
|
||||
View view = getView(viewId);
|
||||
view.setVisibility(visibility);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param viewId
|
||||
* @param drawableId
|
||||
* @return
|
||||
*/
|
||||
public BaseRecyclerHolder setImageResource(int viewId, int drawableId) {
|
||||
ImageView view = getView(viewId);
|
||||
view.setImageResource(drawableId);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param viewId
|
||||
* @param bm
|
||||
* @return
|
||||
*/
|
||||
public BaseRecyclerHolder setImageBitmap(int viewId, Bitmap bm) {
|
||||
ImageView view = getView(viewId);
|
||||
view.setImageBitmap(bm);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param avatar
|
||||
* @param defaultRes
|
||||
* @param viewId
|
||||
* @return
|
||||
*/
|
||||
public BaseRecyclerHolder setImageView(String avatar, int defaultRes, int viewId) {
|
||||
ImageView iv = getView(viewId);
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv,avatar, defaultRes);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package cn.bmob.imdemo.adapter.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
|
||||
import cn.bmob.imdemo.base.BaseActivity;
|
||||
|
||||
/**
|
||||
* 建议使用BaseRecyclerAdapter
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class BaseViewHolder<T> extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener {
|
||||
|
||||
public OnRecyclerViewListener onRecyclerViewListener;
|
||||
protected Context context;
|
||||
|
||||
public BaseViewHolder(Context context, ViewGroup root, int layoutRes,OnRecyclerViewListener listener) {
|
||||
super(LayoutInflater.from(context).inflate(layoutRes, root, false));
|
||||
this.context=context;
|
||||
ButterKnife.bind(this, itemView);
|
||||
this.onRecyclerViewListener =listener;
|
||||
itemView.setOnClickListener(this);
|
||||
itemView.setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return itemView.getContext();
|
||||
}
|
||||
|
||||
public abstract void bindData(T t);
|
||||
|
||||
private Toast toast;
|
||||
public void toast(final Object obj) {
|
||||
try {
|
||||
((BaseActivity)context).runOnUiThread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (toast == null)
|
||||
toast = Toast.makeText(context,"", Toast.LENGTH_SHORT);
|
||||
toast.setText(obj.toString());
|
||||
toast.show();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemClick(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if(onRecyclerViewListener!=null){
|
||||
onRecyclerViewListener.onItemLongClick(getAdapterPosition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**启动指定Activity
|
||||
* @param target
|
||||
* @param bundle
|
||||
*/
|
||||
public void startActivity(Class<? extends Activity> target, Bundle bundle) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(getContext(), target);
|
||||
if (bundle != null)
|
||||
intent.putExtra(getContext().getPackageName(), bundle);
|
||||
getContext().startActivity(intent);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package cn.bmob.imdemo.adapter.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2016/5/6.
|
||||
*/
|
||||
public interface IMutlipleItem<T> {
|
||||
|
||||
/**
|
||||
* 多种布局的layout文件
|
||||
* @param viewtype
|
||||
* @return
|
||||
*/
|
||||
int getItemLayoutId(int viewtype);
|
||||
|
||||
/**
|
||||
* 多种布局类型
|
||||
* @param postion
|
||||
* @param t
|
||||
* @return
|
||||
*/
|
||||
int getItemViewType(int postion, T t);
|
||||
|
||||
/**
|
||||
* 返回布局个数
|
||||
* @param list
|
||||
* @return
|
||||
*/
|
||||
int getItemCount(List<T> list);
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
package cn.bmob.imdemo.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import cn.bmob.imdemo.Config;
|
||||
|
||||
/**基类
|
||||
* @author :smile
|
||||
* @project:BaseActivity
|
||||
* @date :2016-01-15-18:23
|
||||
*/
|
||||
public class BaseActivity extends FragmentActivity {
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(int layoutResID) {
|
||||
super.setContentView(layoutResID);
|
||||
ButterKnife.bind(this);
|
||||
initView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentView(View view, ViewGroup.LayoutParams params) {
|
||||
super.setContentView(view, params);
|
||||
ButterKnife.bind(this);
|
||||
initView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
ButterKnife.unbind(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(Boolean empty){
|
||||
|
||||
}
|
||||
|
||||
protected void initView() {}
|
||||
|
||||
protected void runOnMain(Runnable runnable) {
|
||||
runOnUiThread(runnable);
|
||||
}
|
||||
|
||||
protected final static String NULL = "";
|
||||
private Toast toast;
|
||||
public void toast(final Object obj) {
|
||||
try {
|
||||
runOnMain(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (toast == null)
|
||||
toast = Toast.makeText(BaseActivity.this, NULL,Toast.LENGTH_SHORT);
|
||||
toast.setText(obj.toString());
|
||||
toast.show();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void startActivity(Class<? extends Activity> target, Bundle bundle,boolean finish) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(this, target);
|
||||
if (bundle != null)
|
||||
intent.putExtra(getPackageName(), bundle);
|
||||
startActivity(intent);
|
||||
if (finish)
|
||||
finish();
|
||||
}
|
||||
|
||||
public Bundle getBundle() {
|
||||
if (getIntent() != null && getIntent().hasExtra(getPackageName()))
|
||||
return getIntent().getBundleExtra(getPackageName());
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏软键盘
|
||||
*/
|
||||
public void hideSoftInputView() {
|
||||
InputMethodManager manager = ((InputMethodManager) this.getSystemService(Activity.INPUT_METHOD_SERVICE));
|
||||
if (getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
|
||||
if (getCurrentFocus() != null)
|
||||
manager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
|
||||
}
|
||||
}
|
||||
|
||||
/**隐藏软键盘-一般是EditText.getWindowToken()
|
||||
* @param token
|
||||
*/
|
||||
public void hideSoftInput(IBinder token) {
|
||||
if (token != null) {
|
||||
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
im.hideSoftInputFromWindow(token,InputMethodManager.HIDE_NOT_ALWAYS);
|
||||
}
|
||||
}
|
||||
|
||||
/**Log日志
|
||||
* @param msg
|
||||
*/
|
||||
public void log(String msg){
|
||||
if(Config.DEBUG){
|
||||
Logger.i(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package cn.bmob.imdemo.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import cn.bmob.imdemo.Config;
|
||||
|
||||
/**基类
|
||||
* @author :smile
|
||||
* @project:BaseActivity
|
||||
* @date :2016-01-15-18:23
|
||||
*/
|
||||
public class BaseFragment extends Fragment {
|
||||
|
||||
protected void runOnMain(Runnable runnable) {
|
||||
getActivity().runOnUiThread(runnable);
|
||||
}
|
||||
|
||||
protected final static String NULL = "";
|
||||
private Toast toast;
|
||||
public void toast(final Object obj) {
|
||||
try {
|
||||
runOnMain(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (toast == null)
|
||||
toast = Toast.makeText(getActivity(), NULL,Toast.LENGTH_SHORT);
|
||||
toast.setText(obj.toString());
|
||||
toast.show();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void hideSoftInput(IBinder token) {
|
||||
if (token != null) {
|
||||
InputMethodManager im = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
im.hideSoftInputFromWindow(token,InputMethodManager.HIDE_NOT_ALWAYS);
|
||||
}
|
||||
}
|
||||
|
||||
/**启动指定Activity
|
||||
* @param target
|
||||
* @param bundle
|
||||
*/
|
||||
public void startActivity(Class<? extends Activity> target, Bundle bundle) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(getActivity(), target);
|
||||
if (bundle != null)
|
||||
intent.putExtra(getActivity().getPackageName(), bundle);
|
||||
getActivity().startActivity(intent);
|
||||
}
|
||||
|
||||
/**Log日志
|
||||
* @param msg
|
||||
*/
|
||||
public void log(String msg){
|
||||
if(Config.DEBUG){
|
||||
Logger.i(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package cn.bmob.imdemo.base;
|
||||
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||
|
||||
/**
|
||||
* 抽象的图片加载接口
|
||||
* @author smile
|
||||
*/
|
||||
public interface ILoader {
|
||||
|
||||
/**
|
||||
* 加载圆形头像
|
||||
* @param iv
|
||||
* @param url
|
||||
* @param defaultRes
|
||||
*/
|
||||
void loadAvator(ImageView iv, String url, int defaultRes);
|
||||
|
||||
/**
|
||||
* 加载图片,添加监听器
|
||||
* @param iv
|
||||
* @param url
|
||||
* @param defaultRes
|
||||
* @param listener
|
||||
*/
|
||||
void load(ImageView iv,String url,int defaultRes,ImageLoadingListener listener);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package cn.bmob.imdemo.base;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2016/5/24.
|
||||
*/
|
||||
public class ImageLoaderFactory {
|
||||
|
||||
private static volatile ILoader sInstance;
|
||||
|
||||
private ImageLoaderFactory() {}
|
||||
|
||||
public static ILoader getLoader() {
|
||||
if (sInstance == null) {
|
||||
synchronized (ImageLoaderFactory.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new UniversalImageLoader();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
package cn.bmob.imdemo.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
|
||||
/**封装了导航条的类均需继承该类
|
||||
* @author :smile
|
||||
* @project:ParentWithNaviActivity
|
||||
* @date :2015-08-18-11:29
|
||||
*/
|
||||
public abstract class ParentWithNaviActivity extends BaseActivity {
|
||||
|
||||
public ToolBarListener listener;
|
||||
public TextView tv_title;
|
||||
public ImageView tv_left;
|
||||
public TextView tv_right;
|
||||
|
||||
/**导航栏标题:必填项
|
||||
* @return
|
||||
*/
|
||||
protected abstract String title();
|
||||
|
||||
/**导航栏左边:可以为string或图片资源id,非必须
|
||||
* @return
|
||||
*/
|
||||
public Object left(){return null;}
|
||||
|
||||
/**导航栏右边:可以为string或图片资源id,非必须
|
||||
* @return
|
||||
*/
|
||||
public Object right(){return null;}
|
||||
|
||||
/**设置导航栏监听,非必须
|
||||
* @return
|
||||
*/
|
||||
public ToolBarListener setToolBarListener(){return null;}
|
||||
|
||||
/**
|
||||
* 初始化导航条
|
||||
*/
|
||||
public void initNaviView(){
|
||||
tv_title = getView(R.id.tv_title);
|
||||
tv_right = getView(R.id.tv_right);
|
||||
tv_left = getView(R.id.tv_left);
|
||||
setNaviListener(setToolBarListener());
|
||||
tv_left.setOnClickListener(clickListener);
|
||||
tv_right.setOnClickListener(clickListener);
|
||||
tv_title.setText(title());
|
||||
refreshTop();
|
||||
}
|
||||
|
||||
View.OnClickListener clickListener = new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.tv_left:
|
||||
if (listener == null)
|
||||
finish();
|
||||
else{
|
||||
listener.clickLeft();
|
||||
}
|
||||
break;
|
||||
case R.id.tv_right:
|
||||
if (listener != null)
|
||||
listener.clickRight();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected void refreshTop() {
|
||||
setLeftView(left()==null ? R.drawable.base_action_bar_back_bg_selector: left());
|
||||
setValue(R.id.tv_right, right());
|
||||
this.tv_title.setText(title());
|
||||
}
|
||||
|
||||
private void setLeftView(Object obj){
|
||||
if(obj !=null && !obj.equals("")){
|
||||
tv_left.setVisibility(View.VISIBLE);
|
||||
if(obj instanceof Integer){
|
||||
tv_left.setImageResource(Integer.parseInt(obj.toString()));
|
||||
}else{
|
||||
tv_left.setImageResource(R.drawable.base_action_bar_back_bg_selector);
|
||||
}
|
||||
}else{
|
||||
tv_left.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setValue(int id,Object obj){
|
||||
if (obj != null && !obj.equals("")) {
|
||||
((TextView) getView(id)).setText("");
|
||||
getView(id).setBackgroundDrawable(new BitmapDrawable());
|
||||
if (obj instanceof String) {
|
||||
((TextView) getView(id)).setText(obj.toString());
|
||||
} else if (obj instanceof Integer) {
|
||||
getView(id).setBackgroundResource(Integer.parseInt(obj.toString()));
|
||||
}
|
||||
} else {
|
||||
((TextView) getView(id)).setText("");
|
||||
getView(id).setBackgroundDrawable(new BitmapDrawable());
|
||||
}
|
||||
}
|
||||
|
||||
protected void setNaviListener(ToolBarListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends View> T getView(int id) {
|
||||
return (T) findViewById(id);
|
||||
}
|
||||
|
||||
public boolean handleBackPressed(){
|
||||
return false;
|
||||
}
|
||||
|
||||
/**获取Drawable资源
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public Drawable getDrawableResources(int id){
|
||||
return getResources().getDrawable(id);
|
||||
}
|
||||
|
||||
public interface ToolBarListener {
|
||||
void clickLeft();
|
||||
|
||||
void clickRight();
|
||||
}
|
||||
|
||||
/**启动指定Activity
|
||||
* @param target
|
||||
* @param bundle
|
||||
*/
|
||||
public void startActivity(Class<? extends Activity> target, Bundle bundle) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(this, target);
|
||||
if (bundle != null)
|
||||
intent.putExtra(this.getPackageName(), bundle);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public String getCurrentUid(){
|
||||
return BmobUser.getCurrentUser(this,User.class).getObjectId();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
package cn.bmob.imdemo.base;
|
||||
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviActivity.ToolBarListener;
|
||||
|
||||
/**封装了导航条的Fragment类均需继承该类
|
||||
* @author :smile
|
||||
* @project:ParentWithNaviFragment
|
||||
* @date :2015-08-18-14:19
|
||||
*/
|
||||
public abstract class ParentWithNaviFragment extends BaseFragment {
|
||||
|
||||
protected View rootView = null;
|
||||
private ToolBarListener listener;
|
||||
private TextView tv_title;
|
||||
public TextView tv_right;
|
||||
public ImageView tv_left;
|
||||
public LinearLayout ll_navi;
|
||||
|
||||
/**
|
||||
* 初始化导航条
|
||||
*/
|
||||
public void initNaviView(){
|
||||
tv_title = getView(R.id.tv_title);
|
||||
tv_right = getView(R.id.tv_right);
|
||||
tv_left = getView(R.id.tv_left);
|
||||
setListener(setToolBarListener());
|
||||
tv_left.setOnClickListener(clickListener);
|
||||
tv_right.setOnClickListener(clickListener);
|
||||
tv_title.setText(title());
|
||||
refreshTop();
|
||||
}
|
||||
|
||||
View.OnClickListener clickListener = new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.tv_left:
|
||||
if (listener != null){
|
||||
listener.clickLeft();
|
||||
}
|
||||
break;
|
||||
case R.id.tv_right:
|
||||
if (listener != null)
|
||||
listener.clickRight();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void refreshTop() {
|
||||
setLeftView(left());
|
||||
setValue(R.id.tv_right, right());
|
||||
this.tv_title.setText(title());
|
||||
}
|
||||
|
||||
private void setLeftView(Object obj){
|
||||
if(obj !=null && !obj.equals("")){
|
||||
tv_left.setVisibility(View.VISIBLE);
|
||||
if(obj instanceof Integer){
|
||||
tv_left.setImageResource(Integer.parseInt(obj.toString()));
|
||||
}else{
|
||||
tv_left.setImageResource(R.drawable.base_action_bar_back_bg_selector);
|
||||
}
|
||||
}else{
|
||||
tv_left.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setValue(int id,Object obj){
|
||||
if (obj != null && !obj.equals("")) {
|
||||
((TextView) getView(id)).setText("");
|
||||
getView(id).setBackgroundDrawable(new BitmapDrawable());
|
||||
if (obj instanceof String) {
|
||||
((TextView) getView(id)).setText(obj.toString());
|
||||
} else if (obj instanceof Integer) {
|
||||
getView(id).setBackgroundResource(Integer.parseInt(obj.toString()));
|
||||
}
|
||||
} else {
|
||||
((TextView) getView(id)).setText("");
|
||||
getView(id).setBackgroundDrawable(new BitmapDrawable());
|
||||
}
|
||||
}
|
||||
|
||||
private void setListener(ToolBarListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/**导航栏标题
|
||||
* @return
|
||||
*/
|
||||
protected abstract String title();
|
||||
|
||||
/**导航栏右边:可以为string或图片资源id,不是必填项
|
||||
* @return
|
||||
*/
|
||||
public Object right(){
|
||||
return null;
|
||||
}
|
||||
|
||||
/**导航栏左边
|
||||
* @return
|
||||
*/
|
||||
public Object left(){return null;}
|
||||
|
||||
/**设置导航条背景色
|
||||
* @param color
|
||||
*/
|
||||
public void setNavBackground(int color){
|
||||
ll_navi.setBackgroundColor(color);
|
||||
}
|
||||
|
||||
/**设置右边按钮的文字大小
|
||||
* @param dimenId
|
||||
*/
|
||||
public void setRightTextSize(float dimenId){
|
||||
tv_right.setTextSize(dimenId);
|
||||
}
|
||||
|
||||
/**设置导航栏监听
|
||||
* @return
|
||||
*/
|
||||
public ToolBarListener setToolBarListener(){return null;}
|
||||
|
||||
protected <T extends View> T getView(int id) {
|
||||
return (T) rootView.findViewById(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package cn.bmob.imdemo.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
|
||||
import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
|
||||
import com.nostra13.universalimageloader.core.download.ImageDownloader;
|
||||
import com.nostra13.universalimageloader.core.imageaware.ImageAware;
|
||||
import com.nostra13.universalimageloader.core.imageaware.ImageViewAware;
|
||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import cn.bmob.imdemo.util.DisplayConfig;
|
||||
|
||||
/**
|
||||
* 使用UIL图片框架加载图片,后续方便扩展其他图片框架,比如glide或fresco
|
||||
* Created by Administrator on 2016/5/24.
|
||||
*/
|
||||
public class UniversalImageLoader implements ILoader{
|
||||
|
||||
public UniversalImageLoader(){}
|
||||
|
||||
@Override
|
||||
public void loadAvator(ImageView iv, String url, int defaultRes) {
|
||||
if(!TextUtils.isEmpty(url)){
|
||||
display(iv,url,true,defaultRes,null);
|
||||
} else {
|
||||
iv.setImageResource(defaultRes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(ImageView iv, String url, int defaultRes,ImageLoadingListener listener) {
|
||||
if(!TextUtils.isEmpty(url)){
|
||||
display(iv,url.trim(),false,defaultRes,listener);
|
||||
} else {
|
||||
iv.setImageResource(defaultRes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示图片
|
||||
* @param iv
|
||||
* @param url
|
||||
* @param defaultRes
|
||||
* @param listener
|
||||
*/
|
||||
private void display(ImageView iv,String url,boolean isCircle,int defaultRes,ImageLoadingListener listener){
|
||||
if(!url.equals(iv.getTag())){//增加tag标记,减少UIL的display次数
|
||||
iv.setTag(url);
|
||||
//不直接display imageview改为ImageAware,解决ListView滚动时重复加载图片
|
||||
ImageAware imageAware = new ImageViewAware(iv, false);
|
||||
ImageLoader.getInstance().displayImage(url, imageAware, DisplayConfig.getDefaultOptions(isCircle,defaultRes),listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化ImageLoader
|
||||
* @param context
|
||||
*/
|
||||
public static void initImageLoader(Context context) {
|
||||
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
|
||||
config.threadPoolSize(3);
|
||||
config.memoryCache(new WeakMemoryCache());
|
||||
config.threadPriority(Thread.NORM_PRIORITY - 2);
|
||||
config.denyCacheImageMultipleSizesInMemory();
|
||||
config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
|
||||
config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
|
||||
config.tasksProcessingOrder(QueueProcessingType.LIFO);
|
||||
// config.writeDebugLogs(); // Remove for release app
|
||||
// Initialize ImageLoader with configuration.
|
||||
ImageLoader.getInstance().init(config.build());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package cn.bmob.imdemo.bean;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import cn.bmob.imdemo.Config;
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
import cn.bmob.newim.bean.BmobIMExtraMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
/**添加好友请求
|
||||
* @author :smile
|
||||
* @project:AddFriendMessage
|
||||
* @date :2016-01-30-17:28
|
||||
*/
|
||||
public class AddFriendMessage extends BmobIMExtraMessage{
|
||||
|
||||
public AddFriendMessage(){}
|
||||
|
||||
/**将BmobIMMessage转成NewFriend
|
||||
* @param msg 消息
|
||||
* @return
|
||||
*/
|
||||
public static NewFriend convert(BmobIMMessage msg){
|
||||
NewFriend add =new NewFriend();
|
||||
String content = msg.getContent();
|
||||
add.setMsg(content);
|
||||
add.setTime(msg.getCreateTime());
|
||||
add.setStatus(Config.STATUS_VERIFY_NONE);
|
||||
try {
|
||||
String extra = msg.getExtra();
|
||||
if(!TextUtils.isEmpty(extra)){
|
||||
JSONObject json =new JSONObject(extra);
|
||||
String name = json.getString("name");
|
||||
add.setName(name);
|
||||
String avatar = json.getString("avatar");
|
||||
add.setAvatar(avatar);
|
||||
add.setUid(json.getString("uid"));
|
||||
}else{
|
||||
Logger.i("AddFriendMessage的extra为空");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return add;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getMsgType() {
|
||||
return "add";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransient() {
|
||||
//设置为true,表明为暂态消息,那么这条消息并不会保存到本地db中,SDK只负责发送出去
|
||||
//设置为false,则会保存到指定会话的数据库中
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
package cn.bmob.imdemo.bean;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import cn.bmob.newim.bean.BmobIMExtraMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
|
||||
/**同意添加好友请求-仅仅只用于发送同意添加好友的消息
|
||||
* @author smile
|
||||
* @project AgreeAddFriendMessage
|
||||
* @date 2016-03-04-10:41
|
||||
* 接收到对方发送的同意添加自己为好友的请求时,需要做两个事情:1、在本地数据库中新建一个会话,因此需要设置isTransient为false,2、添加对方到自己的好友表中
|
||||
*/
|
||||
public class AgreeAddFriendMessage extends BmobIMExtraMessage{
|
||||
|
||||
//以下均是从extra里面抽离出来的字段,方便获取
|
||||
private String uid;//最初的发送方
|
||||
private Long time;
|
||||
private String msg;//用于通知栏显示的内容
|
||||
|
||||
@Override
|
||||
public String getMsgType() {
|
||||
return "agree";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransient() {
|
||||
//如果需要在对方的会话表中新增一条该类型的消息,则设置为false,表明是非暂态会话
|
||||
//此处将同意添加好友的请求设置为false,为了演示怎样向会话表和消息表中新增一个类型
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public Long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public AgreeAddFriendMessage(){}
|
||||
|
||||
/**
|
||||
* 继承BmobIMMessage的属性
|
||||
* @param msg
|
||||
*/
|
||||
private AgreeAddFriendMessage(BmobIMMessage msg){
|
||||
super.parse(msg);
|
||||
}
|
||||
|
||||
/**将BmobIMMessage转成AgreeAddFriendMessage
|
||||
* @param msg 消息
|
||||
* @return
|
||||
*/
|
||||
public static AgreeAddFriendMessage convert(BmobIMMessage msg){
|
||||
AgreeAddFriendMessage agree =new AgreeAddFriendMessage(msg);
|
||||
try {
|
||||
String extra = msg.getExtra();
|
||||
if(!TextUtils.isEmpty(extra)){
|
||||
JSONObject json =new JSONObject(extra);
|
||||
Long time = json.getLong("time");
|
||||
String uid =json.getString("uid");
|
||||
String m =json.getString("msg");
|
||||
agree.setMsg(m);
|
||||
agree.setUid(uid);
|
||||
agree.setTime(time);
|
||||
}else{
|
||||
Logger.i("AgreeAddFriendMessage的extra为空");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return agree;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
package cn.bmob.imdemo.bean;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import cn.bmob.newim.bean.BmobIMConversationType;
|
||||
|
||||
/**
|
||||
* 对BmobIMConveration的抽象封装,方便开发者扩展会话类型
|
||||
* @author smile
|
||||
* @date 2016-05-25
|
||||
*/
|
||||
public abstract class Conversation implements Serializable,Comparable{
|
||||
|
||||
/**
|
||||
* 会话id
|
||||
*/
|
||||
protected String cId;
|
||||
/**
|
||||
* 会话类型
|
||||
*/
|
||||
protected BmobIMConversationType cType;
|
||||
/**
|
||||
* 会话名称
|
||||
*/
|
||||
protected String cName;
|
||||
|
||||
/**
|
||||
* 获取头像-用于会话界面显示
|
||||
*/
|
||||
abstract public Object getAvatar();
|
||||
|
||||
/**
|
||||
* 获取最后一条消息的时间
|
||||
*/
|
||||
abstract public long getLastMessageTime();
|
||||
|
||||
/**
|
||||
* 获取最后一条消息的时间
|
||||
* @return
|
||||
*/
|
||||
abstract public String getLastMessageContent();
|
||||
|
||||
/**
|
||||
* 获取未读会话个数
|
||||
* @return
|
||||
*/
|
||||
abstract public int getUnReadCount();
|
||||
|
||||
/**
|
||||
* 将所有消息标记为已读
|
||||
*/
|
||||
abstract public void readAllMessages();
|
||||
|
||||
/**
|
||||
* 点击事件
|
||||
* @param context
|
||||
*/
|
||||
abstract public void onClick(Context context);
|
||||
|
||||
/**
|
||||
* 长按事件
|
||||
* @param context
|
||||
*/
|
||||
abstract public void onLongClick(Context context);
|
||||
|
||||
public String getcName() {
|
||||
return cName;
|
||||
}
|
||||
|
||||
public String getcId(){
|
||||
return cId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Conversation that = (Conversation) o;
|
||||
if (!cId.equals(that.cId)) return false;
|
||||
return cType == that.cType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = cId.hashCode();
|
||||
result = 31 * result + cType.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(Object another) {
|
||||
if (another instanceof Conversation){
|
||||
Conversation anotherConversation = (Conversation) another;
|
||||
long timeGap = anotherConversation.getLastMessageTime() - getLastMessageTime();
|
||||
if (timeGap > 0) return 1;
|
||||
else if (timeGap < 0) return -1;
|
||||
return 0;
|
||||
}else{
|
||||
throw new ClassCastException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package cn.bmob.imdemo.bean;
|
||||
|
||||
import cn.bmob.v3.BmobObject;
|
||||
|
||||
/**好友表
|
||||
* @author smile
|
||||
* @project Friend
|
||||
* @date 2016-04-26
|
||||
*/
|
||||
public class Friend extends BmobObject{
|
||||
|
||||
private User user;
|
||||
private User friendUser;
|
||||
|
||||
//拼音
|
||||
private transient String pinyin;
|
||||
|
||||
public String getPinyin() {
|
||||
return pinyin;
|
||||
}
|
||||
|
||||
public void setPinyin(String pinyin) {
|
||||
this.pinyin = pinyin;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public User getFriendUser() {
|
||||
return friendUser;
|
||||
}
|
||||
|
||||
public void setFriendUser(User friendUser) {
|
||||
this.friendUser = friendUser;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
package cn.bmob.imdemo.bean;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import cn.bmob.imdemo.BmobIMApplication;
|
||||
import cn.bmob.imdemo.Config;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
import cn.bmob.imdemo.db.NewFriendManager;
|
||||
import cn.bmob.imdemo.ui.NewFriendActivity;
|
||||
import cn.bmob.imdemo.util.TimeUtil;
|
||||
|
||||
/**
|
||||
* 新朋友会话
|
||||
* Created by Administrator on 2016/5/25.
|
||||
*/
|
||||
public class NewFriendConversation extends Conversation{
|
||||
|
||||
NewFriend lastFriend;
|
||||
|
||||
public NewFriendConversation(NewFriend friend){
|
||||
this.lastFriend=friend;
|
||||
this.cName="新朋友";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastMessageContent() {
|
||||
if(lastFriend!=null){
|
||||
Integer status =lastFriend.getStatus();
|
||||
String name = lastFriend.getName();
|
||||
if(TextUtils.isEmpty(name)){
|
||||
name = lastFriend.getUid();
|
||||
}
|
||||
//目前的好友请求都是别人发给我的
|
||||
if(status==null || status== Config.STATUS_VERIFY_NONE||status ==Config.STATUS_VERIFY_READED){
|
||||
return name+"请求添加好友";
|
||||
}else{
|
||||
return "我已添加"+name;
|
||||
}
|
||||
}else{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastMessageTime() {
|
||||
if(lastFriend!=null){
|
||||
return lastFriend.getTime();
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAvatar() {
|
||||
return R.mipmap.new_friends_icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnReadCount() {
|
||||
return NewFriendManager.getInstance(BmobIMApplication.INSTANCE()).getNewInvitationCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAllMessages() {
|
||||
//批量更新未读未认证的消息为已读状态
|
||||
NewFriendManager.getInstance(BmobIMApplication.INSTANCE()).updateBatchStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Context context) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(context, NewFriendActivity.class);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongClick(Context context) {
|
||||
NewFriendManager.getInstance(context).deleteNewFriend(lastFriend);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
package cn.bmob.imdemo.bean;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.ui.ChatActivity;
|
||||
import cn.bmob.imdemo.util.TimeUtil;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMConversationType;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessageType;
|
||||
|
||||
/**
|
||||
* 私聊会话
|
||||
* Created by Administrator on 2016/5/25.
|
||||
*/
|
||||
public class PrivateConversation extends Conversation{
|
||||
|
||||
private BmobIMConversation conversation;
|
||||
private BmobIMMessage lastMsg;
|
||||
|
||||
public PrivateConversation(BmobIMConversation conversation){
|
||||
this.conversation = conversation;
|
||||
cType = BmobIMConversationType.setValue(conversation.getConversationType());
|
||||
cId = conversation.getConversationId();
|
||||
if (cType == BmobIMConversationType.PRIVATE){
|
||||
cName=conversation.getConversationTitle();
|
||||
if (TextUtils.isEmpty(cName)) cName = cId;
|
||||
}else{
|
||||
cName="未知会话";
|
||||
}
|
||||
List<BmobIMMessage> msgs =conversation.getMessages();
|
||||
if(msgs!=null && msgs.size()>0){
|
||||
lastMsg =msgs.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAllMessages() {
|
||||
conversation.updateLocalCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAvatar() {
|
||||
if (cType == BmobIMConversationType.PRIVATE){
|
||||
String avatar = conversation.getConversationIcon();
|
||||
if (TextUtils.isEmpty(avatar)){//头像为空,使用默认头像
|
||||
return R.mipmap.head;
|
||||
}else{
|
||||
return avatar;
|
||||
}
|
||||
}else{
|
||||
return R.mipmap.head;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastMessageContent() {
|
||||
if(lastMsg!=null){
|
||||
String content =lastMsg.getContent();
|
||||
if(lastMsg.getMsgType().equals(BmobIMMessageType.TEXT.getType()) || lastMsg.getMsgType().equals("agree")){
|
||||
return content;
|
||||
}else if(lastMsg.getMsgType().equals(BmobIMMessageType.IMAGE.getType())){
|
||||
return "[图片]";
|
||||
}else if(lastMsg.getMsgType().equals(BmobIMMessageType.VOICE.getType())){
|
||||
return "[语音]";
|
||||
}else if(lastMsg.getMsgType().equals(BmobIMMessageType.LOCATION.getType())){
|
||||
return"[位置]";
|
||||
}else if(lastMsg.getMsgType().equals(BmobIMMessageType.VIDEO.getType())){
|
||||
return "[视频]";
|
||||
}else{//开发者自定义的消息类型,需要自行处理
|
||||
return "[未知]";
|
||||
}
|
||||
}else{//防止消息错乱
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastMessageTime() {
|
||||
if(lastMsg!=null) {
|
||||
return lastMsg.getCreateTime();
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnReadCount() {
|
||||
return (int)BmobIM.getInstance().getUnReadCount(conversation.getConversationId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Context context) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(context, ChatActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("c", conversation);
|
||||
if (bundle != null) {
|
||||
intent.putExtra(context.getPackageName(), bundle);
|
||||
}
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLongClick(Context context) {
|
||||
//以下两种方式均可以删除会话
|
||||
// BmobIM.getInstance().deleteConversation(conversation.getConversationId());
|
||||
BmobIM.getInstance().deleteConversation(conversation);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package cn.bmob.imdemo.bean;
|
||||
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:User
|
||||
* @date :2016-01-22-18:11
|
||||
*/
|
||||
public class User extends BmobUser {
|
||||
|
||||
private String avatar;
|
||||
|
||||
public User(){}
|
||||
|
||||
public User(NewFriend friend){
|
||||
setObjectId(friend.getUid());
|
||||
setUsername(friend.getName());
|
||||
setAvatar(friend.getAvatar());
|
||||
}
|
||||
|
||||
public String getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public void setAvatar(String avatar) {
|
||||
this.avatar = avatar;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package cn.bmob.imdemo.db;
|
||||
|
||||
// THIS CODE IS GENERATED BY greenDAO, EDIT ONLY INSIDE THE "KEEP"-SECTIONS
|
||||
|
||||
// KEEP INCLUDES - put your custom includes here
|
||||
// KEEP INCLUDES END
|
||||
/**
|
||||
* Entity mapped to table "newfriend".
|
||||
*/
|
||||
public class NewFriend implements java.io.Serializable {
|
||||
|
||||
private Long id;
|
||||
private String uid;
|
||||
private String msg;
|
||||
private String name;
|
||||
private String avatar;
|
||||
private Integer status;
|
||||
private Long time;
|
||||
|
||||
// KEEP FIELDS - put your custom fields here
|
||||
// KEEP FIELDS END
|
||||
|
||||
public NewFriend() {
|
||||
}
|
||||
|
||||
public NewFriend(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public NewFriend(Long id, String uid, String msg, String name, String avatar, Integer status, Long time) {
|
||||
this.id = id;
|
||||
this.uid = uid;
|
||||
this.msg = msg;
|
||||
this.name = name;
|
||||
this.avatar = avatar;
|
||||
this.status = status;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public void setAvatar(String avatar) {
|
||||
this.avatar = avatar;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(Long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
// KEEP METHODS - put your custom methods here
|
||||
// KEEP METHODS END
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
package cn.bmob.imdemo.db;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import cn.bmob.imdemo.Config;
|
||||
import cn.bmob.imdemo.bean.AgreeAddFriendMessage;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.db.dao.DaoMaster;
|
||||
import cn.bmob.imdemo.db.dao.DaoSession;
|
||||
import cn.bmob.imdemo.db.dao.NewFriendDao;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMReceiveStatus;
|
||||
import cn.bmob.newim.db.dao.MessageDao;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2016/4/27.
|
||||
*/
|
||||
public class NewFriendManager {
|
||||
|
||||
private DaoMaster.DevOpenHelper openHelper;
|
||||
Context mContecxt;
|
||||
String uid=null;
|
||||
private static HashMap<String, NewFriendManager> daoMap = new HashMap<>();
|
||||
|
||||
/**获取DB实例
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static NewFriendManager getInstance(Context context) {
|
||||
User user = BmobUser.getCurrentUser(context, User.class);
|
||||
String loginId=user.getObjectId();
|
||||
if(TextUtils.isEmpty(loginId)){
|
||||
throw new RuntimeException("you must login.");
|
||||
}
|
||||
NewFriendManager dao = daoMap.get(loginId);
|
||||
if (dao == null) {
|
||||
dao = new NewFriendManager(context,loginId);
|
||||
daoMap.put(loginId, dao);
|
||||
}
|
||||
return dao;
|
||||
}
|
||||
|
||||
private NewFriendManager(Context context, String uId){
|
||||
clear();
|
||||
this.mContecxt =context.getApplicationContext();
|
||||
this.uid=uId;
|
||||
String DBName = uId+".demodb";
|
||||
this.openHelper = new DaoMaster.DevOpenHelper(mContecxt, DBName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空资源
|
||||
*/
|
||||
public void clear() {
|
||||
if(openHelper !=null) {
|
||||
openHelper.close();
|
||||
openHelper = null;
|
||||
mContecxt=null;
|
||||
uid =null;
|
||||
}
|
||||
}
|
||||
|
||||
private DaoSession openReadableDb() {
|
||||
checkInit();
|
||||
SQLiteDatabase db = openHelper.getReadableDatabase();
|
||||
DaoMaster daoMaster = new DaoMaster(db);
|
||||
DaoSession daoSession = daoMaster.newSession();
|
||||
return daoSession;
|
||||
}
|
||||
|
||||
private DaoSession openWritableDb(){
|
||||
checkInit();
|
||||
SQLiteDatabase db = openHelper.getWritableDatabase();
|
||||
DaoMaster daoMaster = new DaoMaster(db);
|
||||
DaoSession daoSession = daoMaster.newSession();
|
||||
return daoSession;
|
||||
}
|
||||
|
||||
private void checkInit(){
|
||||
if(openHelper ==null){
|
||||
throw new RuntimeException("请初始化db");
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
|
||||
/**获取本地所有的邀请信息
|
||||
* @return
|
||||
*/
|
||||
public List<NewFriend> getAllNewFriend(){
|
||||
NewFriendDao dao =openReadableDb().getNewFriendDao();
|
||||
return dao.queryBuilder().orderDesc(NewFriendDao.Properties.Time).list();
|
||||
}
|
||||
|
||||
/**创建或更新新朋友信息
|
||||
* @param info
|
||||
* @return long:返回插入或修改的id
|
||||
*/
|
||||
public long insertOrUpdateNewFriend(NewFriend info){
|
||||
NewFriendDao dao = openWritableDb().getNewFriendDao();
|
||||
NewFriend local = getNewFriend(info.getUid(), info.getTime());
|
||||
if(local==null){
|
||||
return dao.insertOrReplace(info);
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本地的好友请求
|
||||
* @param uid
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
private NewFriend getNewFriend(String uid,Long time){
|
||||
NewFriendDao dao = openReadableDb().getNewFriendDao();
|
||||
return dao.queryBuilder().where(NewFriendDao.Properties.Uid.eq(uid))
|
||||
.where(NewFriendDao.Properties.Time.eq(time)).build().unique();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有新的好友邀请
|
||||
* @return
|
||||
*/
|
||||
public boolean hasNewFriendInvitation(){
|
||||
List<NewFriend> infos =getNoVerifyNewFriend();
|
||||
if(infos!=null && infos.size()>0){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取未读的好友邀请
|
||||
* @return
|
||||
*/
|
||||
public int getNewInvitationCount(){
|
||||
List<NewFriend> infos =getNoVerifyNewFriend();
|
||||
if(infos!=null && infos.size()>0){
|
||||
return infos.size();
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取所有未读未验证的好友请求
|
||||
* @return
|
||||
*/
|
||||
private List<NewFriend> getNoVerifyNewFriend(){
|
||||
NewFriendDao dao = openReadableDb().getNewFriendDao();
|
||||
return dao.queryBuilder().where(NewFriendDao.Properties.Status.eq(Config.STATUS_VERIFY_NONE))
|
||||
.build().list();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新未读未验证的状态为已读
|
||||
*/
|
||||
public void updateBatchStatus(){
|
||||
List<NewFriend> infos =getNoVerifyNewFriend();
|
||||
if(infos!=null && infos.size()>0){
|
||||
int size =infos.size();
|
||||
List<NewFriend> all =new ArrayList<>();
|
||||
for (int i = 0; i < size; i++) {
|
||||
NewFriend msg =infos.get(i);
|
||||
msg.setStatus(Config.STATUS_VERIFY_READED);
|
||||
all.add(msg);
|
||||
}
|
||||
insertBatchMessages(infos);
|
||||
}
|
||||
}
|
||||
|
||||
/**批量插入消息
|
||||
* @param msgs
|
||||
*/
|
||||
public void insertBatchMessages(List<NewFriend> msgs){
|
||||
NewFriendDao dao =openWritableDb().getNewFriendDao();
|
||||
dao.insertOrReplaceInTx(msgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改指定好友请求的状态
|
||||
* @param friend
|
||||
* @param status
|
||||
* @return
|
||||
*/
|
||||
public long updateNewFriend(NewFriend friend,int status){
|
||||
NewFriendDao dao = openWritableDb().getNewFriendDao();
|
||||
friend.setStatus(status);
|
||||
return dao.insertOrReplace(friend);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定的添加请求
|
||||
* @param friend
|
||||
*/
|
||||
public void deleteNewFriend(NewFriend friend){
|
||||
NewFriendDao dao =openWritableDb().getNewFriendDao();
|
||||
dao.delete(friend);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package cn.bmob.imdemo.db.dao;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
import de.greenrobot.dao.AbstractDaoMaster;
|
||||
import de.greenrobot.dao.identityscope.IdentityScopeType;
|
||||
|
||||
import cn.bmob.imdemo.db.dao.NewFriendDao;
|
||||
|
||||
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
|
||||
/**
|
||||
* Master of DAO (schema version 1): knows all DAOs.
|
||||
*/
|
||||
public class DaoMaster extends AbstractDaoMaster {
|
||||
public static final int SCHEMA_VERSION = 1;
|
||||
|
||||
/** Creates underlying database table using DAOs. */
|
||||
public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {
|
||||
NewFriendDao.createTable(db, ifNotExists);
|
||||
}
|
||||
|
||||
/** Drops underlying database table using DAOs. */
|
||||
public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
|
||||
NewFriendDao.dropTable(db, ifExists);
|
||||
}
|
||||
|
||||
public static abstract class OpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
public OpenHelper(Context context, String name, CursorFactory factory) {
|
||||
super(context, name, factory, SCHEMA_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
|
||||
createAllTables(db, false);
|
||||
}
|
||||
}
|
||||
|
||||
/** WARNING: Drops all table on Upgrade! Use only during development. */
|
||||
public static class DevOpenHelper extends OpenHelper {
|
||||
public DevOpenHelper(Context context, String name, CursorFactory factory) {
|
||||
super(context, name, factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
|
||||
dropAllTables(db, true);
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
|
||||
public DaoMaster(SQLiteDatabase db) {
|
||||
super(db, SCHEMA_VERSION);
|
||||
registerDaoClass(NewFriendDao.class);
|
||||
}
|
||||
|
||||
public DaoSession newSession() {
|
||||
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
|
||||
}
|
||||
|
||||
public DaoSession newSession(IdentityScopeType type) {
|
||||
return new DaoSession(db, type, daoConfigMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package cn.bmob.imdemo.db.dao;
|
||||
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import de.greenrobot.dao.AbstractDao;
|
||||
import de.greenrobot.dao.AbstractDaoSession;
|
||||
import de.greenrobot.dao.identityscope.IdentityScopeType;
|
||||
import de.greenrobot.dao.internal.DaoConfig;
|
||||
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
|
||||
import cn.bmob.imdemo.db.dao.NewFriendDao;
|
||||
|
||||
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see de.greenrobot.dao.AbstractDaoSession
|
||||
*/
|
||||
public class DaoSession extends AbstractDaoSession {
|
||||
|
||||
private final DaoConfig newFriendDaoConfig;
|
||||
|
||||
private final NewFriendDao newFriendDao;
|
||||
|
||||
public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
|
||||
daoConfigMap) {
|
||||
super(db);
|
||||
|
||||
newFriendDaoConfig = daoConfigMap.get(NewFriendDao.class).clone();
|
||||
newFriendDaoConfig.initIdentityScope(type);
|
||||
|
||||
newFriendDao = new NewFriendDao(newFriendDaoConfig, this);
|
||||
|
||||
registerDao(NewFriend.class, newFriendDao);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
newFriendDaoConfig.getIdentityScope().clear();
|
||||
}
|
||||
|
||||
public NewFriendDao getNewFriendDao() {
|
||||
return newFriendDao;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
package cn.bmob.imdemo.db.dao;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
|
||||
import de.greenrobot.dao.AbstractDao;
|
||||
import de.greenrobot.dao.Property;
|
||||
import de.greenrobot.dao.internal.DaoConfig;
|
||||
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
|
||||
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
|
||||
/**
|
||||
* DAO for table "newfriend".
|
||||
*/
|
||||
public class NewFriendDao extends AbstractDao<NewFriend, Long> {
|
||||
|
||||
public static final String TABLENAME = "newfriend";
|
||||
|
||||
/**
|
||||
* Properties of entity NewFriend.<br/>
|
||||
* Can be used for QueryBuilder and for referencing column names.
|
||||
*/
|
||||
public static class Properties {
|
||||
public final static Property Id = new Property(0, Long.class, "id", true, "_id");
|
||||
public final static Property Uid = new Property(1, String.class, "uid", false, "UID");
|
||||
public final static Property Msg = new Property(2, String.class, "msg", false, "MSG");
|
||||
public final static Property Name = new Property(3, String.class, "name", false, "NAME");
|
||||
public final static Property Avatar = new Property(4, String.class, "avatar", false, "AVATAR");
|
||||
public final static Property Status = new Property(5, Integer.class, "status", false, "STATUS");
|
||||
public final static Property Time = new Property(6, Long.class, "time", false, "TIME");
|
||||
};
|
||||
|
||||
|
||||
public NewFriendDao(DaoConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
public NewFriendDao(DaoConfig config, DaoSession daoSession) {
|
||||
super(config, daoSession);
|
||||
}
|
||||
|
||||
/** Creates the underlying database table. */
|
||||
public static void createTable(SQLiteDatabase db, boolean ifNotExists) {
|
||||
String constraint = ifNotExists? "IF NOT EXISTS ": "";
|
||||
db.execSQL("CREATE TABLE " + constraint + "\"newfriend\" (" + //
|
||||
"\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
|
||||
"\"UID\" TEXT," + // 1: uid
|
||||
"\"MSG\" TEXT," + // 2: msg
|
||||
"\"NAME\" TEXT," + // 3: name
|
||||
"\"AVATAR\" TEXT," + // 4: avatar
|
||||
"\"STATUS\" INTEGER," + // 5: status
|
||||
"\"TIME\" INTEGER);"); // 6: time
|
||||
}
|
||||
|
||||
/** Drops the underlying database table. */
|
||||
public static void dropTable(SQLiteDatabase db, boolean ifExists) {
|
||||
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"newfriend\"";
|
||||
db.execSQL(sql);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@Override
|
||||
protected void bindValues(SQLiteStatement stmt, NewFriend entity) {
|
||||
stmt.clearBindings();
|
||||
|
||||
Long id = entity.getId();
|
||||
if (id != null) {
|
||||
stmt.bindLong(1, id);
|
||||
}
|
||||
|
||||
String uid = entity.getUid();
|
||||
if (uid != null) {
|
||||
stmt.bindString(2, uid);
|
||||
}
|
||||
|
||||
String msg = entity.getMsg();
|
||||
if (msg != null) {
|
||||
stmt.bindString(3, msg);
|
||||
}
|
||||
|
||||
String name = entity.getName();
|
||||
if (name != null) {
|
||||
stmt.bindString(4, name);
|
||||
}
|
||||
|
||||
String avatar = entity.getAvatar();
|
||||
if (avatar != null) {
|
||||
stmt.bindString(5, avatar);
|
||||
}
|
||||
|
||||
Integer status = entity.getStatus();
|
||||
if (status != null) {
|
||||
stmt.bindLong(6, status);
|
||||
}
|
||||
|
||||
Long time = entity.getTime();
|
||||
if (time != null) {
|
||||
stmt.bindLong(7, time);
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@Override
|
||||
public Long readKey(Cursor cursor, int offset) {
|
||||
return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@Override
|
||||
public NewFriend readEntity(Cursor cursor, int offset) {
|
||||
NewFriend entity = new NewFriend( //
|
||||
cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
|
||||
cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // uid
|
||||
cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // msg
|
||||
cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // name
|
||||
cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // avatar
|
||||
cursor.isNull(offset + 5) ? null : cursor.getInt(offset + 5), // status
|
||||
cursor.isNull(offset + 6) ? null : cursor.getLong(offset + 6) // time
|
||||
);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@Override
|
||||
public void readEntity(Cursor cursor, NewFriend entity, int offset) {
|
||||
entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
|
||||
entity.setUid(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
|
||||
entity.setMsg(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
|
||||
entity.setName(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
|
||||
entity.setAvatar(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
|
||||
entity.setStatus(cursor.isNull(offset + 5) ? null : cursor.getInt(offset + 5));
|
||||
entity.setTime(cursor.isNull(offset + 6) ? null : cursor.getLong(offset + 6));
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@Override
|
||||
protected Long updateKeyAfterInsert(NewFriend entity, long rowId) {
|
||||
entity.setId(rowId);
|
||||
return rowId;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@Override
|
||||
public Long getKey(NewFriend entity) {
|
||||
if(entity != null) {
|
||||
return entity.getId();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
@Override
|
||||
protected boolean isEntityUpdateable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package cn.bmob.imdemo.event;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:FinishEvent
|
||||
* @date :2016-01-25-15:25
|
||||
*/
|
||||
public class FinishEvent {
|
||||
|
||||
public FinishEvent(){}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package cn.bmob.imdemo.event;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2016/4/28.
|
||||
*/
|
||||
public class RefreshEvent {
|
||||
public RefreshEvent(){}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package cn.bmob.imdemo.model;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import cn.bmob.imdemo.BmobIMApplication;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:BaseModel
|
||||
* @date :2016-01-23-10:37
|
||||
*/
|
||||
public abstract class BaseModel {
|
||||
|
||||
public int CODE_NULL=1000;
|
||||
public static int CODE_NOT_EQUAL=1001;
|
||||
|
||||
public static final int DEFAULT_LIMIT=20;
|
||||
|
||||
public Context getContext(){
|
||||
return BmobIMApplication.INSTANCE();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
package cn.bmob.imdemo.model;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import cn.bmob.imdemo.bean.Friend;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
import cn.bmob.imdemo.model.i.QueryUserListener;
|
||||
import cn.bmob.imdemo.model.i.UpdateCacheListener;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.event.MessageEvent;
|
||||
import cn.bmob.v3.BmobQuery;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
import cn.bmob.v3.listener.DeleteListener;
|
||||
import cn.bmob.v3.listener.FindListener;
|
||||
import cn.bmob.v3.listener.LogInListener;
|
||||
import cn.bmob.v3.listener.SaveListener;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:UserModel
|
||||
* @date :2016-01-22-18:09
|
||||
*/
|
||||
public class UserModel extends BaseModel {
|
||||
|
||||
private static UserModel ourInstance = new UserModel();
|
||||
|
||||
public static UserModel getInstance() {
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
private UserModel() {}
|
||||
|
||||
/** 登录
|
||||
* @param username
|
||||
* @param password
|
||||
* @param listener
|
||||
*/
|
||||
public void login(String username, String password, final LogInListener listener) {
|
||||
if(TextUtils.isEmpty(username)){
|
||||
listener.internalDone(new BmobException(CODE_NULL, "请填写用户名"));
|
||||
return;
|
||||
}
|
||||
if(TextUtils.isEmpty(password)){
|
||||
listener.internalDone(new BmobException(CODE_NULL, "请填写密码"));
|
||||
return;
|
||||
}
|
||||
final User user =new User();
|
||||
user.setUsername(username);
|
||||
user.setPassword(password);
|
||||
user.login(getContext(), new SaveListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
listener.done(getCurrentUser(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int i, String s) {
|
||||
listener.done(user, new BmobException(i, s));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
public void logout(){
|
||||
BmobUser.logOut(getContext());
|
||||
}
|
||||
|
||||
public User getCurrentUser(){
|
||||
return BmobUser.getCurrentUser(getContext(), User.class);
|
||||
}
|
||||
/**
|
||||
* @param username
|
||||
* @param password
|
||||
* @param pwdagain
|
||||
* @param listener
|
||||
*/
|
||||
public void register(String username,String password, String pwdagain, final LogInListener listener) {
|
||||
if(TextUtils.isEmpty(username)){
|
||||
listener.internalDone(new BmobException(CODE_NULL, "请填写用户名"));
|
||||
return;
|
||||
}
|
||||
if(TextUtils.isEmpty(password)){
|
||||
listener.internalDone(new BmobException(CODE_NULL, "请填写密码"));
|
||||
return;
|
||||
}
|
||||
if(TextUtils.isEmpty(pwdagain)){
|
||||
listener.internalDone(new BmobException(CODE_NULL, "请填写确认密码"));
|
||||
return;
|
||||
}
|
||||
if(!password.equals(pwdagain)){
|
||||
listener.internalDone(new BmobException(CODE_NOT_EQUAL, "两次输入的密码不一致,请重新输入"));
|
||||
return;
|
||||
}
|
||||
final User user = new User();
|
||||
user.setUsername(username);
|
||||
user.setPassword(password);
|
||||
user.signUp(getContext(), new SaveListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
listener.done(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int i, String s) {
|
||||
listener.done(null, new BmobException(i, s));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**查询用户
|
||||
* @param username
|
||||
* @param limit
|
||||
* @param listener
|
||||
*/
|
||||
public void queryUsers(String username,int limit,final FindListener<User> listener){
|
||||
BmobQuery<User> query = new BmobQuery<>();
|
||||
//去掉当前用户
|
||||
try {
|
||||
BmobUser user = BmobUser.getCurrentUser(getContext());
|
||||
query.addWhereNotEqualTo("username",user.getUsername());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
query.addWhereContains("username", username);
|
||||
query.setLimit(limit);
|
||||
query.order("-createdAt");
|
||||
query.findObjects(getContext(), new FindListener<User>() {
|
||||
@Override
|
||||
public void onSuccess(List<User> list) {
|
||||
if (list != null && list.size() > 0) {
|
||||
listener.onSuccess(list);
|
||||
} else {
|
||||
listener.onError(CODE_NULL, "查无此人");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, String s) {
|
||||
listener.onError(i, s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**查询用户信息
|
||||
* @param objectId
|
||||
* @param listener
|
||||
*/
|
||||
public void queryUserInfo(String objectId, final QueryUserListener listener){
|
||||
BmobQuery<User> query = new BmobQuery<>();
|
||||
query.addWhereEqualTo("objectId", objectId);
|
||||
query.findObjects(getContext(), new FindListener<User>() {
|
||||
@Override
|
||||
public void onSuccess(List<User> list) {
|
||||
if(list!=null && list.size()>0){
|
||||
listener.internalDone(list.get(0), null);
|
||||
}else{
|
||||
listener.internalDone(new BmobException(000, "查无此人"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, String s) {
|
||||
listener.internalDone(new BmobException(i, s));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**更新用户资料和会话资料
|
||||
* @param event
|
||||
* @param listener
|
||||
*/
|
||||
public void updateUserInfo(MessageEvent event,final UpdateCacheListener listener){
|
||||
final BmobIMConversation conversation=event.getConversation();
|
||||
final BmobIMUserInfo info =event.getFromUserInfo();
|
||||
final BmobIMMessage msg =event.getMessage();
|
||||
String username =info.getName();
|
||||
String title =conversation.getConversationTitle();
|
||||
Logger.i("" + username + "," + title);
|
||||
//sdk内部,将新会话的会话标题用objectId表示,因此需要比对用户名和会话标题--单聊,后续会根据会话类型进行判断
|
||||
if(!username.equals(title)) {
|
||||
UserModel.getInstance().queryUserInfo(info.getUserId(), new QueryUserListener() {
|
||||
@Override
|
||||
public void done(User s, BmobException e) {
|
||||
if(e==null){
|
||||
String name =s.getUsername();
|
||||
String avatar = s.getAvatar();
|
||||
Logger.i("query success:"+name+","+avatar);
|
||||
conversation.setConversationIcon(avatar);
|
||||
conversation.setConversationTitle(name);
|
||||
info.setName(name);
|
||||
info.setAvatar(avatar);
|
||||
//更新用户资料
|
||||
BmobIM.getInstance().updateUserInfo(info);
|
||||
//更新会话资料-如果消息是暂态消息,则不更新会话资料
|
||||
if(!msg.isTransient()){
|
||||
BmobIM.getInstance().updateConversation(conversation);
|
||||
}
|
||||
}else{
|
||||
Logger.e(e);
|
||||
}
|
||||
listener.done(null);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
listener.internalDone(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意添加好友:1、发送同意添加的请求,2、添加对方到自己的好友列表中
|
||||
*/
|
||||
public void agreeAddFriend(User friend,SaveListener listener){
|
||||
Friend f = new Friend();
|
||||
User user =BmobUser.getCurrentUser(getContext(), User.class);
|
||||
f.setUser(user);
|
||||
f.setFriendUser(friend);
|
||||
f.save(getContext(),listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询好友
|
||||
* @param listener
|
||||
*/
|
||||
public void queryFriends(final FindListener<Friend> listener){
|
||||
BmobQuery<Friend> query = new BmobQuery<>();
|
||||
User user =BmobUser.getCurrentUser(getContext(), User.class);
|
||||
query.addWhereEqualTo("user", user);
|
||||
query.include("friendUser");
|
||||
query.order("-updatedAt");
|
||||
query.findObjects(getContext(), new FindListener<Friend>() {
|
||||
@Override
|
||||
public void onSuccess(List<Friend> list) {
|
||||
if (list != null && list.size() > 0) {
|
||||
listener.onSuccess(list);
|
||||
} else {
|
||||
listener.onError(0, "暂无联系人");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, String s) {
|
||||
listener.onError(i, s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除好友
|
||||
* @param f
|
||||
* @param listener
|
||||
*/
|
||||
public void deleteFriend(Friend f,DeleteListener listener){
|
||||
Friend friend =new Friend();
|
||||
friend.delete(getContext(),f.getObjectId(),listener);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package cn.bmob.imdemo.model.i;
|
||||
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
import cn.bmob.v3.listener.BmobListener;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:QueryUserListener
|
||||
* @date :2016-02-01-16:23
|
||||
*/
|
||||
public abstract class QueryUserListener extends BmobListener<User> {
|
||||
|
||||
public abstract void done(User s, BmobException e);
|
||||
|
||||
@Override
|
||||
protected void postDone(User o, BmobException e) {
|
||||
done(o, e);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package cn.bmob.imdemo.model.i;
|
||||
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
import cn.bmob.v3.listener.BmobListener;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:UpdateCacheListener
|
||||
* @date :2016-02-01-16:23
|
||||
*/
|
||||
public abstract class UpdateCacheListener extends BmobListener {
|
||||
public abstract void done(BmobException e);
|
||||
|
||||
@Override
|
||||
protected void postDone(Object o, BmobException e) {
|
||||
done(e);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,700 @@
|
|||
package cn.bmob.imdemo.ui;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.OnClick;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.ChatAdapter;
|
||||
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviActivity;
|
||||
import cn.bmob.imdemo.util.Util;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.bean.BmobIMAudioMessage;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMImageMessage;
|
||||
import cn.bmob.newim.bean.BmobIMLocationMessage;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMTextMessage;
|
||||
import cn.bmob.newim.bean.BmobIMVideoMessage;
|
||||
import cn.bmob.newim.core.BmobIMClient;
|
||||
import cn.bmob.newim.core.BmobRecordManager;
|
||||
import cn.bmob.newim.event.MessageEvent;
|
||||
import cn.bmob.newim.listener.MessageListHandler;
|
||||
import cn.bmob.newim.listener.MessageSendListener;
|
||||
import cn.bmob.newim.listener.MessagesQueryListener;
|
||||
import cn.bmob.newim.listener.ObseverListener;
|
||||
import cn.bmob.newim.listener.OnRecordChangeListener;
|
||||
import cn.bmob.newim.notification.BmobNotificationManager;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
|
||||
/**聊天界面
|
||||
* @author :smile
|
||||
* @project:ChatActivity
|
||||
* @date :2016-01-25-18:23
|
||||
*/
|
||||
public class ChatActivity extends ParentWithNaviActivity implements ObseverListener,MessageListHandler{
|
||||
|
||||
@Bind(R.id.ll_chat)
|
||||
LinearLayout ll_chat;
|
||||
|
||||
@Bind(R.id.sw_refresh)
|
||||
SwipeRefreshLayout sw_refresh;
|
||||
|
||||
@Bind(R.id.rc_view)
|
||||
RecyclerView rc_view;
|
||||
|
||||
@Bind(R.id.edit_msg)
|
||||
EditText edit_msg;
|
||||
|
||||
@Bind(R.id.btn_chat_add)
|
||||
Button btn_chat_add;
|
||||
@Bind(R.id.btn_chat_emo)
|
||||
Button btn_chat_emo;
|
||||
@Bind(R.id.btn_speak)
|
||||
Button btn_speak;
|
||||
@Bind(R.id.btn_chat_voice)
|
||||
Button btn_chat_voice;
|
||||
@Bind(R.id.btn_chat_keyboard)
|
||||
Button btn_chat_keyboard;
|
||||
@Bind(R.id.btn_chat_send)
|
||||
Button btn_chat_send;
|
||||
|
||||
@Bind(R.id.layout_more)
|
||||
LinearLayout layout_more;
|
||||
@Bind(R.id.layout_add)
|
||||
LinearLayout layout_add;
|
||||
@Bind(R.id.layout_emo)
|
||||
LinearLayout layout_emo;
|
||||
|
||||
// 语音有关
|
||||
@Bind(R.id.layout_record)
|
||||
RelativeLayout layout_record;
|
||||
@Bind(R.id.tv_voice_tips)
|
||||
TextView tv_voice_tips;
|
||||
@Bind(R.id.iv_record)
|
||||
ImageView iv_record;
|
||||
private Drawable[] drawable_Anims;// 话筒动画
|
||||
BmobRecordManager recordManager;
|
||||
|
||||
ChatAdapter adapter;
|
||||
protected LinearLayoutManager layoutManager;
|
||||
BmobIMConversation c;
|
||||
|
||||
@Override
|
||||
protected String title() {
|
||||
return c.getConversationTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_chat);
|
||||
c= BmobIMConversation.obtain(BmobIMClient.getInstance(), (BmobIMConversation) getBundle().getSerializable("c"));
|
||||
initNaviView();
|
||||
initSwipeLayout();
|
||||
initVoiceView();
|
||||
initBottomView();
|
||||
}
|
||||
|
||||
private void initSwipeLayout(){
|
||||
sw_refresh.setEnabled(true);
|
||||
layoutManager = new LinearLayoutManager(this);
|
||||
rc_view.setLayoutManager(layoutManager);
|
||||
adapter = new ChatAdapter(this,c);
|
||||
rc_view.setAdapter(adapter);
|
||||
ll_chat.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
ll_chat.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
sw_refresh.setRefreshing(true);
|
||||
//自动刷新
|
||||
queryMessages(null);
|
||||
}
|
||||
});
|
||||
//下拉加载
|
||||
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
BmobIMMessage msg = adapter.getFirstMessage();
|
||||
queryMessages(msg);
|
||||
}
|
||||
});
|
||||
//设置RecyclerView的点击事件
|
||||
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
|
||||
@Override
|
||||
public void onItemClick(int position) {
|
||||
Logger.i(""+position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(int position) {
|
||||
//这里省了个懒,直接长按就删除了该消息
|
||||
c.deleteMessage(adapter.getItem(position));
|
||||
adapter.remove(position);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initBottomView(){
|
||||
edit_msg.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if(event.getAction()==MotionEvent.ACTION_DOWN||event.getAction()==MotionEvent.ACTION_UP){
|
||||
scrollToBottom();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
edit_msg.addTextChangedListener(new TextWatcher() {
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (!TextUtils.isEmpty(s)) {
|
||||
btn_chat_send.setVisibility(View.VISIBLE);
|
||||
btn_chat_keyboard.setVisibility(View.GONE);
|
||||
btn_chat_voice.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (btn_chat_voice.getVisibility() != View.VISIBLE) {
|
||||
btn_chat_voice.setVisibility(View.VISIBLE);
|
||||
btn_chat_send.setVisibility(View.GONE);
|
||||
btn_chat_keyboard.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化语音布局
|
||||
* @param
|
||||
* @return void
|
||||
*/
|
||||
private void initVoiceView() {
|
||||
btn_speak.setOnTouchListener(new VoiceTouchListener());
|
||||
initVoiceAnimRes();
|
||||
initRecordManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化语音动画资源
|
||||
* @Title: initVoiceAnimRes
|
||||
* @param
|
||||
* @return void
|
||||
*/
|
||||
private void initVoiceAnimRes() {
|
||||
drawable_Anims = new Drawable[] {
|
||||
getResources().getDrawable(R.mipmap.chat_icon_voice2),
|
||||
getResources().getDrawable(R.mipmap.chat_icon_voice3),
|
||||
getResources().getDrawable(R.mipmap.chat_icon_voice4),
|
||||
getResources().getDrawable(R.mipmap.chat_icon_voice5),
|
||||
getResources().getDrawable(R.mipmap.chat_icon_voice6) };
|
||||
}
|
||||
|
||||
private void initRecordManager(){
|
||||
// 语音相关管理器
|
||||
recordManager = BmobRecordManager.getInstance(this);
|
||||
// 设置音量大小监听--在这里开发者可以自己实现:当剩余10秒情况下的给用户的提示,类似微信的语音那样
|
||||
recordManager.setOnRecordChangeListener(new OnRecordChangeListener() {
|
||||
|
||||
@Override
|
||||
public void onVolumnChanged(int value) {
|
||||
iv_record.setImageDrawable(drawable_Anims[value]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeChanged(int recordTime, String localPath) {
|
||||
Logger.i("voice", "已录音长度:" + recordTime);
|
||||
if (recordTime >= BmobRecordManager.MAX_RECORD_TIME) {// 1分钟结束,发送消息
|
||||
// 需要重置按钮
|
||||
btn_speak.setPressed(false);
|
||||
btn_speak.setClickable(false);
|
||||
// 取消录音框
|
||||
layout_record.setVisibility(View.INVISIBLE);
|
||||
// 发送语音消息
|
||||
sendVoiceMessage(localPath, recordTime);
|
||||
//是为了防止过了录音时间后,会多发一条语音出去的情况。
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
btn_speak.setClickable(true);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 长按说话
|
||||
* @author smile
|
||||
* @date 2014-7-1 下午6:10:16
|
||||
*/
|
||||
class VoiceTouchListener implements View.OnTouchListener {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (!Util.checkSdCard()) {
|
||||
toast("发送语音需要sdcard支持!");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
v.setPressed(true);
|
||||
layout_record.setVisibility(View.VISIBLE);
|
||||
tv_voice_tips.setText(getString(R.string.voice_cancel_tips));
|
||||
// 开始录音
|
||||
recordManager.startRecording(c.getConversationId());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
if (event.getY() < 0) {
|
||||
tv_voice_tips.setText(getString(R.string.voice_cancel_tips));
|
||||
tv_voice_tips.setTextColor(Color.RED);
|
||||
} else {
|
||||
tv_voice_tips.setText(getString(R.string.voice_up_tips));
|
||||
tv_voice_tips.setTextColor(Color.WHITE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case MotionEvent.ACTION_UP:
|
||||
v.setPressed(false);
|
||||
layout_record.setVisibility(View.INVISIBLE);
|
||||
try {
|
||||
if (event.getY() < 0) {// 放弃录音
|
||||
recordManager.cancelRecording();
|
||||
Logger.i("voice", "放弃发送语音");
|
||||
} else {
|
||||
int recordTime = recordManager.stopRecording();
|
||||
if (recordTime > 1) {
|
||||
// 发送语音文件
|
||||
sendVoiceMessage(recordManager.getRecordFilePath(c.getConversationId()),recordTime);
|
||||
} else {// 录音时间过短,则提示录音过短的提示
|
||||
layout_record.setVisibility(View.GONE);
|
||||
showShortToast().show();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Toast toast;
|
||||
|
||||
/**
|
||||
* 显示录音时间过短的Toast
|
||||
* @Title: showShortToast
|
||||
* @return void
|
||||
*/
|
||||
private Toast showShortToast() {
|
||||
if (toast == null) {
|
||||
toast = new Toast(this);
|
||||
}
|
||||
View view = LayoutInflater.from(this).inflate(
|
||||
R.layout.include_chat_voice_short, null);
|
||||
toast.setView(view);
|
||||
toast.setGravity(Gravity.CENTER, 0, 0);
|
||||
toast.setDuration(Toast.LENGTH_SHORT);
|
||||
return toast;
|
||||
}
|
||||
|
||||
@OnClick(R.id.edit_msg)
|
||||
public void onEditClick(View view){
|
||||
if (layout_more.getVisibility() == View.VISIBLE) {
|
||||
layout_add.setVisibility(View.GONE);
|
||||
layout_emo.setVisibility(View.GONE);
|
||||
layout_more.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_chat_emo)
|
||||
public void onEmoClick(View view){
|
||||
if (layout_more.getVisibility() == View.GONE) {
|
||||
showEditState(true);
|
||||
} else {
|
||||
if (layout_add.getVisibility() == View.VISIBLE) {
|
||||
layout_add.setVisibility(View.GONE);
|
||||
layout_emo.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
layout_more.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_chat_add)
|
||||
public void onAddClick(View view){
|
||||
if (layout_more.getVisibility() == View.GONE) {
|
||||
layout_more.setVisibility(View.VISIBLE);
|
||||
layout_add.setVisibility(View.VISIBLE);
|
||||
layout_emo.setVisibility(View.GONE);
|
||||
hideSoftInputView();
|
||||
} else {
|
||||
if (layout_emo.getVisibility() == View.VISIBLE) {
|
||||
layout_emo.setVisibility(View.GONE);
|
||||
layout_add.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
layout_more.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@OnClick(R.id.btn_chat_voice)
|
||||
public void onVoiceClick(View view){
|
||||
edit_msg.setVisibility(View.GONE);
|
||||
layout_more.setVisibility(View.GONE);
|
||||
btn_chat_voice.setVisibility(View.GONE);
|
||||
btn_chat_keyboard.setVisibility(View.VISIBLE);
|
||||
btn_speak.setVisibility(View.VISIBLE);
|
||||
hideSoftInputView();
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_chat_keyboard)
|
||||
public void onKeyClick(View view){
|
||||
showEditState(false);
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_chat_send)
|
||||
public void onSendClick(View view){
|
||||
sendMessage();
|
||||
}
|
||||
|
||||
@OnClick(R.id.tv_picture)
|
||||
public void onPictureClick(View view){
|
||||
// sendLocalImageMessage();
|
||||
// sendOtherMessage();
|
||||
sendVideoMessage();
|
||||
}
|
||||
@OnClick(R.id.tv_camera)
|
||||
public void onCameraClick(View view){
|
||||
sendRemoteImageMessage();
|
||||
}
|
||||
|
||||
@OnClick(R.id.tv_location)
|
||||
public void onLocationClick(View view){
|
||||
sendLocationMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据是否点击笑脸来显示文本输入框的状态
|
||||
* @param isEmo 用于区分文字和表情
|
||||
* @return void
|
||||
*/
|
||||
private void showEditState(boolean isEmo) {
|
||||
edit_msg.setVisibility(View.VISIBLE);
|
||||
btn_chat_keyboard.setVisibility(View.GONE);
|
||||
btn_chat_voice.setVisibility(View.VISIBLE);
|
||||
btn_speak.setVisibility(View.GONE);
|
||||
edit_msg.requestFocus();
|
||||
if (isEmo) {
|
||||
layout_more.setVisibility(View.VISIBLE);
|
||||
layout_more.setVisibility(View.VISIBLE);
|
||||
layout_emo.setVisibility(View.VISIBLE);
|
||||
layout_add.setVisibility(View.GONE);
|
||||
hideSoftInputView();
|
||||
} else {
|
||||
layout_more.setVisibility(View.GONE);
|
||||
showSoftInputView();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示软键盘
|
||||
*/
|
||||
public void showSoftInputView() {
|
||||
if (getWindow().getAttributes().softInputMode == WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
|
||||
if (getCurrentFocus() != null)
|
||||
((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
|
||||
.showSoftInput(edit_msg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送文本消息
|
||||
*/
|
||||
private void sendMessage(){
|
||||
String text=edit_msg.getText().toString();
|
||||
if(TextUtils.isEmpty(text.trim())){
|
||||
toast("请输入内容");
|
||||
return;
|
||||
}
|
||||
BmobIMTextMessage msg =new BmobIMTextMessage();
|
||||
msg.setContent(text);
|
||||
//可设置额外信息
|
||||
Map<String,Object> map =new HashMap<>();
|
||||
map.put("level", "1");//随意增加信息
|
||||
msg.setExtraMap(map);
|
||||
c.sendMessage(msg, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接发送远程图片地址
|
||||
*/
|
||||
public void sendRemoteImageMessage(){
|
||||
BmobIMImageMessage image =new BmobIMImageMessage();
|
||||
image.setRemoteUrl("http://img.lakalaec.com/ad/57ab6dc2-43f2-4087-81e2-b5ab5681642d.jpg");
|
||||
c.sendMessage(image, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送本地图片地址
|
||||
*/
|
||||
public void sendLocalImageMessage(){
|
||||
//正常情况下,需要调用系统的图库或拍照功能获取到图片的本地地址,开发者只需要将本地的文件地址传过去就可以发送文件类型的消息
|
||||
BmobIMImageMessage image =new BmobIMImageMessage("/storage/emulated/0/bimagechooser/IMG_20160302_172003.jpg");
|
||||
c.sendMessage(image, listener);
|
||||
// //因此也可以使用BmobIMFileMessage来发送文件消息
|
||||
// BmobIMFileMessage file =new BmobIMFileMessage("文件地址");
|
||||
// c.sendMessage(file,listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送语音消息
|
||||
* @Title: sendVoiceMessage
|
||||
* @param local
|
||||
* @param length
|
||||
* @return void
|
||||
*/
|
||||
private void sendVoiceMessage(String local, int length) {
|
||||
BmobIMAudioMessage audio =new BmobIMAudioMessage(local);
|
||||
//可设置额外信息-开发者设置的额外信息,需要开发者自己从extra中取出来
|
||||
Map<String,Object> map =new HashMap<>();
|
||||
map.put("from", "优酷");
|
||||
audio.setExtraMap(map);
|
||||
//设置语音文件时长:可选
|
||||
// audio.setDuration(length);
|
||||
c.sendMessage(audio, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送视频文件
|
||||
*/
|
||||
private void sendVideoMessage(){
|
||||
BmobIMVideoMessage video =new BmobIMVideoMessage("/storage/sdcard0/bimagechooser/11.png");
|
||||
c.sendMessage(video, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送地理位置
|
||||
*/
|
||||
public void sendLocationMessage(){
|
||||
//测试数据,真实数据需要从地图SDK中获取
|
||||
BmobIMLocationMessage location =new BmobIMLocationMessage("广州番禺区",23.5,112.0);
|
||||
Map<String,Object> map =new HashMap<>();
|
||||
map.put("from", "百度地图");
|
||||
location.setExtraMap(map);
|
||||
c.sendMessage(location, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息发送监听器
|
||||
*/
|
||||
public MessageSendListener listener =new MessageSendListener() {
|
||||
|
||||
@Override
|
||||
public void onProgress(int value) {
|
||||
super.onProgress(value);
|
||||
//文件类型的消息才有进度值
|
||||
Logger.i("onProgress:"+value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(BmobIMMessage msg) {
|
||||
super.onStart(msg);
|
||||
adapter.addMessage(msg);
|
||||
edit_msg.setText("");
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done(BmobIMMessage msg, BmobException e) {
|
||||
adapter.notifyDataSetChanged();
|
||||
edit_msg.setText("");
|
||||
scrollToBottom();
|
||||
if (e != null) {
|
||||
toast(e.getMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**首次加载,可设置msg为null,下拉刷新的时候,默认取消息表的第一个msg作为刷新的起始时间点,默认按照消息时间的降序排列
|
||||
* @param msg
|
||||
*/
|
||||
public void queryMessages(BmobIMMessage msg){
|
||||
c.queryMessages(msg, 10, new MessagesQueryListener() {
|
||||
@Override
|
||||
public void done(List<BmobIMMessage> list, BmobException e) {
|
||||
sw_refresh.setRefreshing(false);
|
||||
if (e == null) {
|
||||
if (null != list && list.size() > 0) {
|
||||
adapter.addMessages(list);
|
||||
layoutManager.scrollToPositionWithOffset(list.size() - 1, 0);
|
||||
}
|
||||
} else {
|
||||
toast(e.getMessage() + "(" + e.getErrorCode() + ")");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void scrollToBottom() {
|
||||
layoutManager.scrollToPositionWithOffset(adapter.getItemCount() - 1, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageReceive(List<MessageEvent> list) {
|
||||
Logger.i("聊天页面接收到消息:" + list.size());
|
||||
//当注册页面消息监听时候,有消息(包含离线消息)到来时会回调该方法
|
||||
for (int i=0;i<list.size();i++){
|
||||
addMessage2Chat(list.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
// /**接收到聊天消息
|
||||
// * @param event
|
||||
// */
|
||||
// @Subscribe
|
||||
// public void onEventMainThread(MessageEvent event){
|
||||
// addMessage2Chat(event);
|
||||
// }
|
||||
//
|
||||
// @Subscribe
|
||||
// public void onEventMainThread(OfflineMessageEvent event){
|
||||
// Map<String,List<MessageEvent>> map =event.getEventMap();
|
||||
// if(map!=null&&map.size()>0){
|
||||
// //只获取当前聊天对象的离线消息
|
||||
// List<MessageEvent> list = map.get(c.getConversationId());
|
||||
// if(list!=null && list.size()>0){
|
||||
// for (int i=0;i<list.size();i++){
|
||||
// addMessage2Chat(list.get(i));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/**添加消息到聊天界面中
|
||||
* @param event
|
||||
*/
|
||||
private void addMessage2Chat(MessageEvent event){
|
||||
BmobIMMessage msg =event.getMessage();
|
||||
if(c!=null && event!=null && c.getConversationId().equals(event.getConversation().getConversationId()) //如果是当前会话的消息
|
||||
&& !msg.isTransient()){//并且不为暂态消息
|
||||
if(adapter.findPosition(msg)<0){//如果未添加到界面中
|
||||
adapter.addMessage(msg);
|
||||
//更新该会话下面的已读状态
|
||||
c.updateReceiveStatus(msg);
|
||||
}
|
||||
scrollToBottom();
|
||||
}else{
|
||||
Logger.i("不是与当前聊天对象的消息");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (layout_more.getVisibility() == View.VISIBLE) {
|
||||
layout_more.setVisibility(View.GONE);
|
||||
return false;
|
||||
} else {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
} else {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
//锁屏期间的收到的未读消息需要添加到聊天界面中
|
||||
addUnReadMessage();
|
||||
//添加页面消息监听器
|
||||
BmobIM.getInstance().addMessageListHandler(this);
|
||||
// 有可能锁屏期间,在聊天界面出现通知栏,这时候需要清除通知
|
||||
BmobNotificationManager.getInstance(this).cancelNotification();
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加未读的通知栏消息到聊天界面
|
||||
*/
|
||||
private void addUnReadMessage(){
|
||||
List<MessageEvent> cache = BmobNotificationManager.getInstance(this).getNotificationCacheList();
|
||||
if(cache.size()>0){
|
||||
int size =cache.size();
|
||||
for(int i=0;i<size;i++){
|
||||
MessageEvent event = cache.get(i);
|
||||
addMessage2Chat(event);
|
||||
}
|
||||
}
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
//移除页面消息监听器
|
||||
BmobIM.getInstance().removeMessageListHandler(this);
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
//清理资源
|
||||
if(recordManager!=null){
|
||||
recordManager.clear();
|
||||
}
|
||||
//更新此会话的所有消息为已读状态
|
||||
if(c!=null){
|
||||
c.updateLocalCache();
|
||||
}
|
||||
hideSoftInputView();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package cn.bmob.imdemo.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.OnClick;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.base.BaseActivity;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.event.FinishEvent;
|
||||
import cn.bmob.imdemo.model.UserModel;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
import cn.bmob.v3.listener.LogInListener;
|
||||
|
||||
/**登陆界面
|
||||
* @author :smile
|
||||
* @project:LoginActivity
|
||||
* @date :2016-01-15-18:23
|
||||
*/
|
||||
public class LoginActivity extends BaseActivity {
|
||||
|
||||
@Bind(R.id.et_username)
|
||||
EditText et_username;
|
||||
@Bind(R.id.et_password)
|
||||
EditText et_password;
|
||||
@Bind(R.id.btn_login)
|
||||
Button btn_login;
|
||||
@Bind(R.id.tv_register)
|
||||
TextView tv_register;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_login);
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_login)
|
||||
public void onLoginClick(View view){
|
||||
UserModel.getInstance().login(et_username.getText().toString(), et_password.getText().toString(), new LogInListener() {
|
||||
|
||||
@Override
|
||||
public void done(Object o, BmobException e) {
|
||||
if (e == null) {
|
||||
User user =(User)o;
|
||||
BmobIM.getInstance().updateUserInfo(new BmobIMUserInfo(user.getObjectId(), user.getUsername(), user.getAvatar()));
|
||||
startActivity(MainActivity.class, null, true);
|
||||
} else {
|
||||
toast(e.getMessage() + "(" + e.getErrorCode() + ")");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@OnClick(R.id.tv_register)
|
||||
public void onRegisterClick(View view){
|
||||
startActivity(RegisterActivity.class, null, false);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEventMainThread(FinishEvent event){
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
package cn.bmob.imdemo.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.base.BaseActivity;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.db.NewFriendManager;
|
||||
import cn.bmob.imdemo.event.RefreshEvent;
|
||||
import cn.bmob.imdemo.ui.fragment.ContactFragment;
|
||||
import cn.bmob.imdemo.ui.fragment.ConversationFragment;
|
||||
import cn.bmob.imdemo.ui.fragment.SetFragment;
|
||||
import cn.bmob.imdemo.util.IMMLeaks;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.core.ConnectionStatus;
|
||||
import cn.bmob.newim.event.MessageEvent;
|
||||
import cn.bmob.newim.event.OfflineMessageEvent;
|
||||
import cn.bmob.newim.listener.ConnectListener;
|
||||
import cn.bmob.newim.listener.ConnectStatusChangeListener;
|
||||
import cn.bmob.newim.listener.ObseverListener;
|
||||
import cn.bmob.newim.notification.BmobNotificationManager;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:MainActivity
|
||||
* @date :2016-01-15-18:23
|
||||
*/
|
||||
public class MainActivity extends BaseActivity implements ObseverListener{
|
||||
|
||||
/*@Bind(R.id.btn_conversation)
|
||||
Button btn_conversation;*/
|
||||
@Bind(R.id.btn_set)
|
||||
Button btn_set;
|
||||
|
||||
@Bind(R.id.btn_contact)
|
||||
Button btn_contact;
|
||||
|
||||
/* @Bind(R.id.iv_conversation_tips)
|
||||
ImageView iv_conversation_tips;*/
|
||||
|
||||
@Bind(R.id.iv_contact_tips)
|
||||
ImageView iv_contact_tips;
|
||||
|
||||
private Button[] mTabs;
|
||||
private ConversationFragment conversationFragment;
|
||||
private SetFragment setFragment;
|
||||
ContactFragment contactFragment;
|
||||
private Fragment[] fragments;
|
||||
private int index;
|
||||
private int currentTabIndex;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
//connect server
|
||||
User user = BmobUser.getCurrentUser(this,User.class);
|
||||
BmobIM.connect(user.getObjectId(), new ConnectListener() {
|
||||
@Override
|
||||
public void done(String uid, BmobException e) {
|
||||
if (e == null) {
|
||||
Logger.i("connect success");
|
||||
//服务器连接成功就发送一个更新事件,同步更新会话及主页的小红点
|
||||
EventBus.getDefault().post(new RefreshEvent());
|
||||
} else {
|
||||
Logger.e(e.getErrorCode() + "/" + e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
//监听连接状态,也可通过BmobIM.getInstance().getCurrentStatus()来获取当前的长连接状态
|
||||
BmobIM.getInstance().setOnConnectStatusChangeListener(new ConnectStatusChangeListener() {
|
||||
@Override
|
||||
public void onChange(ConnectionStatus status) {
|
||||
toast("" + status.getMsg());
|
||||
}
|
||||
});
|
||||
//解决leancanary提示InputMethodManager内存泄露的问题
|
||||
IMMLeaks.fixFocusedViewLeak(getApplication());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
super.initView();
|
||||
mTabs = new Button[2];
|
||||
/*mTabs[0] = btn_conversation;*/
|
||||
mTabs[0] = btn_contact;
|
||||
mTabs[1] =btn_set;
|
||||
mTabs[0].setSelected(true);
|
||||
initTab();
|
||||
}
|
||||
|
||||
private void initTab(){
|
||||
//conversationFragment = new ConversationFragment();
|
||||
setFragment = new SetFragment();
|
||||
contactFragment=new ContactFragment();
|
||||
fragments = new Fragment[] {contactFragment,setFragment};
|
||||
//.add(R.id.fragment_container, conversationFragment)
|
||||
//
|
||||
//.show(conversationFragment)
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.add(R.id.fragment_container, contactFragment)
|
||||
.add(R.id.fragment_container, setFragment)
|
||||
.hide(setFragment)
|
||||
.show(contactFragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
public void onTabSelect(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.btn_contact:
|
||||
index = 0;
|
||||
break;
|
||||
case R.id.btn_set:
|
||||
index = 1;
|
||||
break;
|
||||
}
|
||||
onTabIndex(index);
|
||||
}
|
||||
|
||||
private void onTabIndex(int index){
|
||||
if (currentTabIndex != index) {
|
||||
FragmentTransaction trx = getSupportFragmentManager().beginTransaction();
|
||||
trx.hide(fragments[currentTabIndex]);
|
||||
if (!fragments[index].isAdded()) {
|
||||
trx.add(R.id.fragment_container, fragments[index]);
|
||||
}
|
||||
trx.show(fragments[index]).commit();
|
||||
}
|
||||
mTabs[currentTabIndex].setSelected(false);
|
||||
mTabs[index].setSelected(true);
|
||||
currentTabIndex = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
//显示小红点
|
||||
checkRedPoint();
|
||||
//进入应用后,通知栏应取消
|
||||
BmobNotificationManager.getInstance(this).cancelNotification();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
//清理导致内存泄露的资源
|
||||
BmobIM.getInstance().clear();
|
||||
}
|
||||
|
||||
/**注册消息接收事件
|
||||
* @param event
|
||||
*/
|
||||
@Subscribe
|
||||
public void onEventMainThread(MessageEvent event){
|
||||
checkRedPoint();
|
||||
}
|
||||
|
||||
/**注册离线消息接收事件
|
||||
* @param event
|
||||
*/
|
||||
@Subscribe
|
||||
public void onEventMainThread(OfflineMessageEvent event){
|
||||
checkRedPoint();
|
||||
}
|
||||
|
||||
/**注册自定义消息接收事件
|
||||
* @param event
|
||||
*/
|
||||
@Subscribe
|
||||
public void onEventMainThread(RefreshEvent event){
|
||||
log("---主页接收到自定义消息---");
|
||||
checkRedPoint();
|
||||
}
|
||||
|
||||
private void checkRedPoint(){
|
||||
int count = (int)BmobIM.getInstance().getAllUnReadCount();
|
||||
/*if(count>0){
|
||||
iv_conversation_tips.setVisibility(View.VISIBLE);
|
||||
}else{
|
||||
iv_conversation_tips.setVisibility(View.GONE);
|
||||
}*/
|
||||
//是否有好友添加的请求
|
||||
if(NewFriendManager.getInstance(this).hasNewFriendInvitation()){
|
||||
iv_contact_tips.setVisibility(View.VISIBLE);
|
||||
}else{
|
||||
iv_contact_tips.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
package cn.bmob.imdemo.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.Bind;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.ConversationAdapter;
|
||||
import cn.bmob.imdemo.adapter.NewFriendAdapter;
|
||||
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
|
||||
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviActivity;
|
||||
import cn.bmob.imdemo.bean.Conversation;
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
import cn.bmob.imdemo.db.NewFriendManager;
|
||||
|
||||
/**新朋友
|
||||
* @author :smile
|
||||
* @project:NewFriendActivity
|
||||
* @date :2016-01-25-18:23
|
||||
*/
|
||||
public class NewFriendActivity extends ParentWithNaviActivity {
|
||||
|
||||
@Bind(R.id.ll_root)
|
||||
LinearLayout ll_root;
|
||||
@Bind(R.id.rc_view)
|
||||
RecyclerView rc_view;
|
||||
@Bind(R.id.sw_refresh)
|
||||
SwipeRefreshLayout sw_refresh;
|
||||
NewFriendAdapter adapter;
|
||||
LinearLayoutManager layoutManager;
|
||||
|
||||
@Override
|
||||
protected String title() {
|
||||
return "新朋友";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object right() {
|
||||
return R.drawable.base_action_bar_add_bg_selector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParentWithNaviActivity.ToolBarListener setToolBarListener() {
|
||||
return new ParentWithNaviActivity.ToolBarListener() {
|
||||
@Override
|
||||
public void clickLeft() {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickRight() {
|
||||
startActivity(SearchUserActivity.class,null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.fragment_conversation);
|
||||
initNaviView();
|
||||
//单一布局
|
||||
IMutlipleItem<NewFriend> mutlipleItem = new IMutlipleItem<NewFriend>() {
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int postion, NewFriend c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemLayoutId(int viewtype) {
|
||||
return R.layout.item_new_friend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(List<NewFriend> list) {
|
||||
return list.size();
|
||||
}
|
||||
};
|
||||
adapter = new NewFriendAdapter(this,mutlipleItem,null);
|
||||
rc_view.setAdapter(adapter);
|
||||
layoutManager = new LinearLayoutManager(this);
|
||||
rc_view.setLayoutManager(layoutManager);
|
||||
sw_refresh.setEnabled(true);
|
||||
//批量更新未读未认证的消息为已读状态
|
||||
NewFriendManager.getInstance(this).updateBatchStatus();
|
||||
setListener();
|
||||
}
|
||||
|
||||
private void setListener(){
|
||||
ll_root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
ll_root.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
sw_refresh.setRefreshing(true);
|
||||
query();
|
||||
}
|
||||
});
|
||||
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
query();
|
||||
}
|
||||
});
|
||||
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
|
||||
@Override
|
||||
public void onItemClick(int position) {
|
||||
log("点击:"+position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(int position) {
|
||||
NewFriendManager.getInstance(NewFriendActivity.this).deleteNewFriend(adapter.getItem(position));
|
||||
adapter.remove(position);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
sw_refresh.setRefreshing(true);
|
||||
query();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
/**
|
||||
查询本地会话
|
||||
*/
|
||||
public void query(){
|
||||
adapter.bindDatas(NewFriendManager.getInstance(this).getAllNewFriend());
|
||||
adapter.notifyDataSetChanged();
|
||||
sw_refresh.setRefreshing(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package cn.bmob.imdemo.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.OnClick;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviActivity;
|
||||
import cn.bmob.imdemo.event.FinishEvent;
|
||||
import cn.bmob.imdemo.model.BaseModel;
|
||||
import cn.bmob.imdemo.model.UserModel;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
import cn.bmob.v3.listener.LogInListener;
|
||||
|
||||
/**注册界面
|
||||
* @author :smile
|
||||
* @project:RegisterActivity
|
||||
* @date :2016-01-15-18:23
|
||||
*/
|
||||
public class RegisterActivity extends ParentWithNaviActivity {
|
||||
|
||||
@Bind(R.id.et_username)
|
||||
EditText et_username;
|
||||
@Bind(R.id.et_password)
|
||||
EditText et_password;
|
||||
@Bind(R.id.btn_register)
|
||||
Button btn_register;
|
||||
|
||||
@Bind(R.id.et_password_again)
|
||||
EditText et_password_again;
|
||||
|
||||
@Override
|
||||
protected String title() {
|
||||
return "注册";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_register);
|
||||
initNaviView();
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_register)
|
||||
public void onRegisterClick(View view){
|
||||
UserModel.getInstance().register(et_username.getText().toString(), et_password.getText().toString(),et_password_again.getText().toString(),new LogInListener() {
|
||||
@Override
|
||||
public void done(Object o, BmobException e) {
|
||||
if(e==null){
|
||||
EventBus.getDefault().post(new FinishEvent());
|
||||
startActivity(MainActivity.class, null, true);
|
||||
}else{
|
||||
if(e.getErrorCode()== BaseModel.CODE_NOT_EQUAL){
|
||||
et_password_again.setText("");
|
||||
}
|
||||
toast(e.getMessage()+"("+e.getErrorCode()+")");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
package cn.bmob.imdemo.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.orhanobut.logger.Logger;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.OnClick;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.adapter.SearchUserAdapter;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviActivity;
|
||||
import cn.bmob.imdemo.model.BaseModel;
|
||||
import cn.bmob.imdemo.model.UserModel;
|
||||
import cn.bmob.v3.listener.FindListener;
|
||||
|
||||
/**搜索好友
|
||||
* @author :smile
|
||||
* @project:SearchUserActivity
|
||||
* @date :2016-01-25-18:23
|
||||
*/
|
||||
public class SearchUserActivity extends ParentWithNaviActivity {
|
||||
|
||||
@Bind(R.id.et_find_name)
|
||||
EditText et_find_name;
|
||||
@Bind(R.id.sw_refresh)
|
||||
SwipeRefreshLayout sw_refresh;
|
||||
@Bind(R.id.btn_search)
|
||||
Button btn_search;
|
||||
@Bind(R.id.rc_view)
|
||||
RecyclerView rc_view;
|
||||
LinearLayoutManager layoutManager;
|
||||
SearchUserAdapter adapter;
|
||||
|
||||
@Override
|
||||
protected String title() {
|
||||
return "搜索好友";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_search_user);
|
||||
initNaviView();
|
||||
adapter =new SearchUserAdapter();
|
||||
layoutManager = new LinearLayoutManager(this);
|
||||
rc_view.setLayoutManager(layoutManager);
|
||||
rc_view.setAdapter(adapter);
|
||||
sw_refresh.setEnabled(true);
|
||||
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
query();
|
||||
}
|
||||
});
|
||||
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
|
||||
@Override
|
||||
public void onItemClick(int position) {
|
||||
Bundle bundle = new Bundle();
|
||||
User user = adapter.getItem(position);
|
||||
bundle.putSerializable("u", user);
|
||||
startActivity(UserInfoActivity.class, bundle, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(int position) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_search)
|
||||
public void onSearchClick(View view){
|
||||
sw_refresh.setRefreshing(true);
|
||||
query();
|
||||
}
|
||||
|
||||
public void query(){
|
||||
String name =et_find_name.getText().toString();
|
||||
if(TextUtils.isEmpty(name)){
|
||||
toast("请填写用户名");
|
||||
sw_refresh.setRefreshing(false);
|
||||
return;
|
||||
}
|
||||
UserModel.getInstance().queryUsers(name, BaseModel.DEFAULT_LIMIT, new FindListener<User>() {
|
||||
@Override
|
||||
public void onSuccess(List<User> list) {
|
||||
sw_refresh.setRefreshing(false);
|
||||
adapter.setDatas(list);
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, String s) {
|
||||
sw_refresh.setRefreshing(false);
|
||||
adapter.setDatas(null);
|
||||
adapter.notifyDataSetChanged();
|
||||
toast(s + "(" + i + ")");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package cn.bmob.imdemo.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.base.BaseActivity;
|
||||
import cn.bmob.imdemo.model.UserModel;
|
||||
|
||||
/**启动界面
|
||||
* @author :smile
|
||||
* @project:SplashActivity
|
||||
* @date :2016-01-15-18:23
|
||||
*/
|
||||
public class SplashActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_splash);
|
||||
Handler handler =new Handler(Looper.getMainLooper());
|
||||
handler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
User user = UserModel.getInstance().getCurrentUser();
|
||||
if (user == null) {
|
||||
startActivity(LoginActivity.class,null,true);
|
||||
}else{
|
||||
startActivity(MainActivity.class,null,true);
|
||||
}
|
||||
}
|
||||
},1000);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package cn.bmob.imdemo.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.OnClick;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.base.ImageLoaderFactory;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviActivity;
|
||||
import cn.bmob.imdemo.bean.AddFriendMessage;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMMessage;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.newim.core.BmobIMClient;
|
||||
import cn.bmob.newim.listener.MessageSendListener;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
import cn.bmob.v3.exception.BmobException;
|
||||
|
||||
/**
|
||||
* 用户资料
|
||||
*/
|
||||
public class UserInfoActivity extends ParentWithNaviActivity {
|
||||
|
||||
@Bind(R.id.iv_avator)
|
||||
ImageView iv_avator;
|
||||
@Bind(R.id.tv_name)
|
||||
TextView tv_name;
|
||||
|
||||
@Bind(R.id.btn_add_friend)
|
||||
Button btn_add_friend;
|
||||
@Bind(R.id.btn_chat)
|
||||
Button btn_chat;
|
||||
|
||||
User user;
|
||||
BmobIMUserInfo info;
|
||||
@Override
|
||||
protected String title() {
|
||||
return "个人资料";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_user_info);
|
||||
initNaviView();
|
||||
user=(User)getBundle().getSerializable("u");
|
||||
if(user.getObjectId().equals(getCurrentUid())){
|
||||
btn_add_friend.setVisibility(View.GONE);
|
||||
btn_chat.setVisibility(View.GONE);
|
||||
}else{
|
||||
btn_add_friend.setVisibility(View.VISIBLE);
|
||||
btn_chat.setVisibility(View.VISIBLE);
|
||||
}
|
||||
//构造聊天方的用户信息:传入用户id、用户名和用户头像三个参数
|
||||
info = new BmobIMUserInfo(user.getObjectId(),user.getUsername(),user.getAvatar());
|
||||
ImageLoaderFactory.getLoader().loadAvator(iv_avator,user.getAvatar(),R.mipmap.head);
|
||||
tv_name.setText(user.getUsername());
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_add_friend)
|
||||
public void onAddClick(View view){
|
||||
sendAddFriendMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送添加好友的请求
|
||||
*/
|
||||
private void sendAddFriendMessage(){
|
||||
//启动一个会话,如果isTransient设置为true,则不会创建在本地会话表中创建记录,
|
||||
//设置isTransient设置为false,则会在本地数据库的会话列表中先创建(如果没有)与该用户的会话信息,且将用户信息存储到本地的用户表中
|
||||
BmobIMConversation c = BmobIM.getInstance().startPrivateConversation(info, true,null);
|
||||
//这个obtain方法才是真正创建一个管理消息发送的会话
|
||||
BmobIMConversation conversation = BmobIMConversation.obtain(BmobIMClient.getInstance(), c);
|
||||
AddFriendMessage msg =new AddFriendMessage();
|
||||
User currentUser = BmobUser.getCurrentUser(this,User.class);
|
||||
msg.setContent("很高兴认识你,可以加个好友吗?");//给对方的一个留言信息
|
||||
Map<String,Object> map =new HashMap<>();
|
||||
map.put("name", currentUser.getUsername());//发送者姓名,这里只是举个例子,其实可以不需要传发送者的信息过去
|
||||
map.put("avatar",currentUser.getAvatar());//发送者的头像
|
||||
map.put("uid",currentUser.getObjectId());//发送者的uid
|
||||
msg.setExtraMap(map);
|
||||
conversation.sendMessage(msg, new MessageSendListener() {
|
||||
@Override
|
||||
public void done(BmobIMMessage msg, BmobException e) {
|
||||
if (e == null) {//发送成功
|
||||
toast("好友请求发送成功,等待验证");
|
||||
} else {//发送失败
|
||||
toast("发送失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_chat)
|
||||
public void onChatClick(View view){
|
||||
//启动一个会话,设置isTransient设置为false,则会在本地数据库的会话列表中先创建(如果没有)与该用户的会话信息,且将用户信息存储到本地的用户表中
|
||||
BmobIMConversation c = BmobIM.getInstance().startPrivateConversation(info,false,null);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("c", c);
|
||||
startActivity(ChatActivity.class, bundle, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
package cn.bmob.imdemo.ui.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.ContactAdapter;
|
||||
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
|
||||
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviActivity;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviFragment;
|
||||
import cn.bmob.imdemo.bean.Friend;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.event.RefreshEvent;
|
||||
import cn.bmob.imdemo.model.UserModel;
|
||||
import cn.bmob.imdemo.ui.ChatActivity;
|
||||
import cn.bmob.imdemo.ui.NewFriendActivity;
|
||||
import cn.bmob.imdemo.ui.SearchUserActivity;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.bean.BmobIMUserInfo;
|
||||
import cn.bmob.v3.listener.DeleteListener;
|
||||
import cn.bmob.v3.listener.FindListener;
|
||||
|
||||
/**联系人界面
|
||||
* @author :smile
|
||||
* @project:ContactFragment
|
||||
* @date :2016-04-27-14:23
|
||||
*/
|
||||
public class ContactFragment extends ParentWithNaviFragment {
|
||||
|
||||
@Bind(R.id.rc_view)
|
||||
RecyclerView rc_view;
|
||||
@Bind(R.id.sw_refresh)
|
||||
SwipeRefreshLayout sw_refresh;
|
||||
ContactAdapter adapter;
|
||||
LinearLayoutManager layoutManager;
|
||||
|
||||
@Override
|
||||
protected String title() {
|
||||
return "联系人";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object right() {
|
||||
return R.drawable.base_action_bar_add_bg_selector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParentWithNaviActivity.ToolBarListener setToolBarListener() {
|
||||
return new ParentWithNaviActivity.ToolBarListener() {
|
||||
@Override
|
||||
public void clickLeft() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickRight() {
|
||||
startActivity(SearchUserActivity.class,null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
rootView =inflater.inflate(R.layout.fragment_conversation, container, false);
|
||||
initNaviView();
|
||||
ButterKnife.bind(this, rootView);
|
||||
IMutlipleItem<Friend> mutlipleItem = new IMutlipleItem<Friend>() {
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int postion, Friend friend) {
|
||||
if(postion==0){
|
||||
return ContactAdapter.TYPE_NEW_FRIEND;
|
||||
}else{
|
||||
return ContactAdapter.TYPE_ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemLayoutId(int viewtype) {
|
||||
if(viewtype== ContactAdapter.TYPE_NEW_FRIEND){
|
||||
return R.layout.header_new_friend;
|
||||
}else{
|
||||
return R.layout.item_contact;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(List<Friend> list) {
|
||||
return list.size()+1;
|
||||
}
|
||||
};
|
||||
adapter = new ContactAdapter(getActivity(),mutlipleItem,null);
|
||||
rc_view.setAdapter(adapter);
|
||||
layoutManager = new LinearLayoutManager(getActivity());
|
||||
rc_view.setLayoutManager(layoutManager);
|
||||
sw_refresh.setEnabled(true);
|
||||
setListener();
|
||||
return rootView;
|
||||
}
|
||||
|
||||
private void setListener(){
|
||||
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
rootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
sw_refresh.setRefreshing(true);
|
||||
query();
|
||||
}
|
||||
});
|
||||
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
query();
|
||||
}
|
||||
});
|
||||
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
|
||||
@Override
|
||||
public void onItemClick(int position) {
|
||||
if (position == 0) {//跳转到新朋友页面
|
||||
startActivity(NewFriendActivity.class, null);
|
||||
} else {
|
||||
Friend friend = adapter.getItem(position);
|
||||
User user = friend.getFriendUser();
|
||||
BmobIMUserInfo info = new BmobIMUserInfo(user.getObjectId(), user.getUsername(), user.getAvatar());
|
||||
//启动一个会话,实际上就是在本地数据库的会话列表中先创建(如果没有)与该用户的会话信息,且将用户信息存储到本地的用户表中
|
||||
BmobIMConversation c = BmobIM.getInstance().startPrivateConversation(info, null);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("c", c);
|
||||
startActivity(ChatActivity.class, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(final int position) {
|
||||
log("长按" + position);
|
||||
if(position==0){
|
||||
return true;
|
||||
}
|
||||
UserModel.getInstance().deleteFriend(adapter.getItem(position), new DeleteListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
toast("好友删除成功");
|
||||
adapter.remove(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int i, String s) {
|
||||
toast("好友删除失败:" + i + ",s =" + s);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
sw_refresh.setRefreshing(true);
|
||||
query();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
/**注册自定义消息接收事件
|
||||
* @param event
|
||||
*/
|
||||
@Subscribe
|
||||
public void onEventMainThread(RefreshEvent event){
|
||||
//重新刷新列表
|
||||
log("---联系人界面接收到自定义消息---");
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
查询本地会话
|
||||
*/
|
||||
public void query(){
|
||||
UserModel.getInstance().queryFriends(new FindListener<Friend>() {
|
||||
@Override
|
||||
public void onSuccess(List<Friend> list) {
|
||||
adapter.bindDatas(list);
|
||||
adapter.notifyDataSetChanged();
|
||||
sw_refresh.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int i, String s) {
|
||||
adapter.bindDatas(null);
|
||||
adapter.notifyDataSetChanged();
|
||||
sw_refresh.setRefreshing(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
package cn.bmob.imdemo.ui.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.adapter.ConversationAdapter;
|
||||
import cn.bmob.imdemo.adapter.OnRecyclerViewListener;
|
||||
import cn.bmob.imdemo.adapter.base.IMutlipleItem;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviActivity;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviFragment;
|
||||
import cn.bmob.imdemo.bean.Conversation;
|
||||
import cn.bmob.imdemo.bean.NewFriendConversation;
|
||||
import cn.bmob.imdemo.bean.PrivateConversation;
|
||||
import cn.bmob.imdemo.db.NewFriend;
|
||||
import cn.bmob.imdemo.db.NewFriendManager;
|
||||
import cn.bmob.imdemo.event.RefreshEvent;
|
||||
import cn.bmob.imdemo.ui.SearchUserActivity;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.newim.bean.BmobIMConversation;
|
||||
import cn.bmob.newim.event.MessageEvent;
|
||||
import cn.bmob.newim.event.OfflineMessageEvent;
|
||||
|
||||
/**会话界面
|
||||
* @author :smile
|
||||
* @project:ConversationFragment
|
||||
* @date :2016-01-25-18:23
|
||||
*/
|
||||
public class ConversationFragment extends ParentWithNaviFragment {
|
||||
|
||||
@Bind(R.id.rc_view)
|
||||
RecyclerView rc_view;
|
||||
@Bind(R.id.sw_refresh)
|
||||
SwipeRefreshLayout sw_refresh;
|
||||
ConversationAdapter adapter;
|
||||
LinearLayoutManager layoutManager;
|
||||
|
||||
@Override
|
||||
protected String title() {
|
||||
return "会话";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object right() {
|
||||
return R.drawable.base_action_bar_add_bg_selector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParentWithNaviActivity.ToolBarListener setToolBarListener() {
|
||||
return new ParentWithNaviActivity.ToolBarListener() {
|
||||
@Override
|
||||
public void clickLeft() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clickRight() {
|
||||
startActivity(SearchUserActivity.class,null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
rootView =inflater.inflate(R.layout.fragment_conversation, container, false);
|
||||
initNaviView();
|
||||
ButterKnife.bind(this, rootView);
|
||||
//单一布局
|
||||
IMutlipleItem<Conversation> mutlipleItem = new IMutlipleItem<Conversation>() {
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int postion, Conversation c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemLayoutId(int viewtype) {
|
||||
return R.layout.item_conversation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(List<Conversation> list) {
|
||||
return list.size();
|
||||
}
|
||||
};
|
||||
adapter = new ConversationAdapter(getActivity(),mutlipleItem,null);
|
||||
rc_view.setAdapter(adapter);
|
||||
layoutManager = new LinearLayoutManager(getActivity());
|
||||
rc_view.setLayoutManager(layoutManager);
|
||||
sw_refresh.setEnabled(true);
|
||||
setListener();
|
||||
return rootView;
|
||||
}
|
||||
|
||||
private void setListener(){
|
||||
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
rootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
sw_refresh.setRefreshing(true);
|
||||
query();
|
||||
}
|
||||
});
|
||||
sw_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
query();
|
||||
}
|
||||
});
|
||||
adapter.setOnRecyclerViewListener(new OnRecyclerViewListener() {
|
||||
@Override
|
||||
public void onItemClick(int position) {
|
||||
adapter.getItem(position).onClick(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(int position) {
|
||||
adapter.getItem(position).onLongClick(getActivity());
|
||||
adapter.remove(position);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
sw_refresh.setRefreshing(true);
|
||||
query();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
/**
|
||||
查询本地会话
|
||||
*/
|
||||
public void query(){
|
||||
// adapter.bindDatas(BmobIM.getInstance().loadAllConversation());
|
||||
adapter.bindDatas(getConversations());
|
||||
adapter.notifyDataSetChanged();
|
||||
sw_refresh.setRefreshing(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会话列表的数据:增加新朋友会话
|
||||
* @return
|
||||
*/
|
||||
private List<Conversation> getConversations(){
|
||||
//添加会话
|
||||
List<Conversation> conversationList = new ArrayList<>();
|
||||
conversationList.clear();
|
||||
List<BmobIMConversation> list =BmobIM.getInstance().loadAllConversation();
|
||||
if(list!=null && list.size()>0){
|
||||
for (BmobIMConversation item:list){
|
||||
switch (item.getConversationType()){
|
||||
case 1://私聊
|
||||
conversationList.add(new PrivateConversation(item));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//添加新朋友会话-获取好友请求表中最新一条记录
|
||||
List<NewFriend> friends = NewFriendManager.getInstance(getActivity()).getAllNewFriend();
|
||||
if(friends!=null && friends.size()>0){
|
||||
conversationList.add(new NewFriendConversation(friends.get(0)));
|
||||
}
|
||||
//重新排序
|
||||
Collections.sort(conversationList);
|
||||
return conversationList;
|
||||
}
|
||||
|
||||
/**注册自定义消息接收事件
|
||||
* @param event
|
||||
*/
|
||||
@Subscribe
|
||||
public void onEventMainThread(RefreshEvent event){
|
||||
log("---会话页接收到自定义消息---");
|
||||
//因为新增`新朋友`这种会话类型
|
||||
adapter.bindDatas(getConversations());
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**注册离线消息接收事件
|
||||
* @param event
|
||||
*/
|
||||
@Subscribe
|
||||
public void onEventMainThread(OfflineMessageEvent event){
|
||||
//重新刷新列表
|
||||
adapter.bindDatas(getConversations());
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**注册消息接收事件
|
||||
* @param event
|
||||
* 1、与用户相关的由开发者自己维护,SDK内部只存储用户信息
|
||||
* 2、开发者获取到信息后,可调用SDK内部提供的方法更新会话
|
||||
*/
|
||||
@Subscribe
|
||||
public void onEventMainThread(MessageEvent event){
|
||||
//重新获取本地消息并刷新列表
|
||||
adapter.bindDatas(getConversations());
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package cn.bmob.imdemo.ui.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import cn.bmob.imdemo.R;
|
||||
import cn.bmob.imdemo.base.ParentWithNaviFragment;
|
||||
import cn.bmob.imdemo.bean.User;
|
||||
import cn.bmob.imdemo.model.UserModel;
|
||||
import cn.bmob.imdemo.ui.LoginActivity;
|
||||
import cn.bmob.imdemo.ui.UserInfoActivity;
|
||||
import cn.bmob.newim.BmobIM;
|
||||
import cn.bmob.v3.BmobUser;
|
||||
|
||||
/**设置
|
||||
* @author :smile
|
||||
* @project:SetFragment
|
||||
* @date :2016-01-25-18:23
|
||||
*/
|
||||
public class SetFragment extends ParentWithNaviFragment {
|
||||
|
||||
@Bind(R.id.tv_set_name)
|
||||
TextView tv_set_name;
|
||||
|
||||
@Bind(R.id.layout_info)
|
||||
RelativeLayout layout_info;
|
||||
|
||||
@Override
|
||||
protected String title() {
|
||||
return "设置";
|
||||
}
|
||||
|
||||
public static SetFragment newInstance() {
|
||||
SetFragment fragment = new SetFragment();
|
||||
Bundle args = new Bundle();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public SetFragment() {}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
rootView= inflater.inflate(R.layout.fragment_set,container, false);
|
||||
initNaviView();
|
||||
ButterKnife.bind(this, rootView);
|
||||
String username = UserModel.getInstance().getCurrentUser().getUsername();
|
||||
tv_set_name.setText(TextUtils.isEmpty(username)?"":username);
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@OnClick(R.id.layout_info)
|
||||
public void onInfoClick(View view){
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable("u", BmobUser.getCurrentUser(getActivity(),User.class));
|
||||
startActivity(UserInfoActivity.class,bundle);
|
||||
}
|
||||
|
||||
@OnClick(R.id.btn_logout)
|
||||
public void onLogoutClick(View view){
|
||||
UserModel.getInstance().logout();
|
||||
//可断开连接
|
||||
BmobIM.getInstance().disConnect();
|
||||
getActivity().finish();
|
||||
startActivity(LoginActivity.class,null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package cn.bmob.imdemo.util;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
||||
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:DisplayConfig
|
||||
* @date :2016-01-25-09:19
|
||||
* 注:由于Picasso圆角处理不够完美,故舍弃
|
||||
*/
|
||||
public class DisplayConfig {
|
||||
|
||||
/**UIL默认的显示配置:圆角
|
||||
* @param defaultRes
|
||||
* @return
|
||||
*/
|
||||
public static DisplayImageOptions getDefaultOptions(boolean hasRounded,int defaultRes){
|
||||
DisplayImageOptions.Builder builder = new DisplayImageOptions.Builder()
|
||||
.cacheInMemory(true)//设置下载的图片是否缓存在内存中
|
||||
.cacheOnDisc(true)//设置下载的图片是否缓存在SD卡中
|
||||
.considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
|
||||
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
|
||||
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型:设置为RGB565比起默认的ARGB_8888要节省大量的内存
|
||||
// .delayBeforeLoading(100)//载入图片前稍做延时可以提高整体滑动的流畅度
|
||||
.resetViewBeforeLoading(true);//设置图片在下载前是否重置,复位
|
||||
if(hasRounded){
|
||||
builder.displayer(new RoundedBitmapDisplayer(12));//是否设置为圆角,弧度为多少
|
||||
}
|
||||
if(defaultRes!=0){
|
||||
builder.showImageForEmptyUri(defaultRes)//设置图片Uri为空或是错误的时候显示的图片
|
||||
// .showImageOnLoading(defaultRes) //设置图片在下载期间显示的图片-->应该去掉-会造成ListView中图片闪烁
|
||||
.showImageOnFail(defaultRes); //设置图片加载/解码过程中错误时候显示的图片
|
||||
}
|
||||
return builder.build();//构建完成
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
package cn.bmob.imdemo.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.MessageQueue;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static android.content.Context.INPUT_METHOD_SERVICE;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.os.Build.VERSION_CODES.KITKAT;
|
||||
|
||||
public class IMMLeaks {
|
||||
|
||||
static class ReferenceCleaner
|
||||
implements MessageQueue.IdleHandler, View.OnAttachStateChangeListener,
|
||||
ViewTreeObserver.OnGlobalFocusChangeListener {
|
||||
|
||||
private final InputMethodManager inputMethodManager;
|
||||
private final Field mHField;
|
||||
private final Field mServedViewField;
|
||||
private final Method finishInputLockedMethod;
|
||||
|
||||
ReferenceCleaner(InputMethodManager inputMethodManager, Field mHField, Field mServedViewField,
|
||||
Method finishInputLockedMethod) {
|
||||
this.inputMethodManager = inputMethodManager;
|
||||
this.mHField = mHField;
|
||||
this.mServedViewField = mServedViewField;
|
||||
this.finishInputLockedMethod = finishInputLockedMethod;
|
||||
}
|
||||
|
||||
@Override public void onGlobalFocusChanged(View oldFocus, View newFocus) {
|
||||
if (newFocus == null) {
|
||||
return;
|
||||
}
|
||||
if (oldFocus != null) {
|
||||
oldFocus.removeOnAttachStateChangeListener(this);
|
||||
}
|
||||
Looper.myQueue().removeIdleHandler(this);
|
||||
newFocus.addOnAttachStateChangeListener(this);
|
||||
}
|
||||
|
||||
@Override public void onViewAttachedToWindow(View v) {
|
||||
}
|
||||
|
||||
@Override public void onViewDetachedFromWindow(View v) {
|
||||
v.removeOnAttachStateChangeListener(this);
|
||||
Looper.myQueue().removeIdleHandler(this);
|
||||
Looper.myQueue().addIdleHandler(this);
|
||||
}
|
||||
|
||||
@Override public boolean queueIdle() {
|
||||
clearInputMethodManagerLeak();
|
||||
return false;
|
||||
}
|
||||
|
||||
private void clearInputMethodManagerLeak() {
|
||||
try {
|
||||
Object lock = mHField.get(inputMethodManager);
|
||||
if(lock==null){
|
||||
return;
|
||||
}
|
||||
// This is highly dependent on the InputMethodManager implementation.
|
||||
synchronized (lock) {
|
||||
View servedView = (View) mServedViewField.get(inputMethodManager);
|
||||
if (servedView != null) {
|
||||
|
||||
boolean servedViewAttached = servedView.getWindowVisibility() != View.GONE;
|
||||
|
||||
if (servedViewAttached) {
|
||||
// The view held by the IMM was replaced without a global focus change. Let's make
|
||||
// sure we get notified when that view detaches.
|
||||
|
||||
// Avoid double registration.
|
||||
servedView.removeOnAttachStateChangeListener(this);
|
||||
servedView.addOnAttachStateChangeListener(this);
|
||||
} else {
|
||||
// servedView is not attached. InputMethodManager is being stupid!
|
||||
Activity activity = extractActivity(servedView.getContext());
|
||||
if (activity == null || activity.getWindow() == null) {
|
||||
// Unlikely case. Let's finish the input anyways.
|
||||
finishInputLockedMethod.invoke(inputMethodManager);
|
||||
} else {
|
||||
View decorView = activity.getWindow().peekDecorView();
|
||||
boolean windowAttached = decorView.getWindowVisibility() != View.GONE;
|
||||
if (!windowAttached) {
|
||||
finishInputLockedMethod.invoke(inputMethodManager);
|
||||
} else {
|
||||
decorView.requestFocusFromTouch();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception unexpected) {
|
||||
Log.e("IMMLeaks", "Unexpected reflection exception", unexpected);
|
||||
}
|
||||
}
|
||||
|
||||
private Activity extractActivity(Context context) {
|
||||
while (true) {
|
||||
if (context instanceof Application) {
|
||||
return null;
|
||||
} else if (context instanceof Activity) {
|
||||
return (Activity) context;
|
||||
} else if (context instanceof ContextWrapper) {
|
||||
Context baseContext = ((ContextWrapper) context).getBaseContext();
|
||||
// Prevent Stack Overflow.
|
||||
if (baseContext == context) {
|
||||
return null;
|
||||
}
|
||||
context = baseContext;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix for https://code.google.com/p/android/issues/detail?id=171190 .
|
||||
*
|
||||
* When a view that has focus gets detached, we wait for the main thread to be idle and then
|
||||
* check if the InputMethodManager is leaking a view. If yes, we tell it that the decor view got
|
||||
* focus, which is what happens if you press home and come back from recent apps. This replaces
|
||||
* the reference to the detached view with a reference to the decor view.
|
||||
*
|
||||
* Should be called from {@link Activity#onCreate(android.os.Bundle)} )}.
|
||||
*/
|
||||
public static void fixFocusedViewLeak(Application application) {
|
||||
|
||||
// Don't know about other versions yet.
|
||||
if (SDK_INT < KITKAT || SDK_INT > 22) {
|
||||
return;
|
||||
}
|
||||
|
||||
final InputMethodManager inputMethodManager =
|
||||
(InputMethodManager) application.getSystemService(INPUT_METHOD_SERVICE);
|
||||
|
||||
final Field mServedViewField;
|
||||
final Field mHField;
|
||||
final Method finishInputLockedMethod;
|
||||
final Method focusInMethod;
|
||||
try {
|
||||
mServedViewField = InputMethodManager.class.getDeclaredField("mServedView");
|
||||
mServedViewField.setAccessible(true);
|
||||
mHField = InputMethodManager.class.getDeclaredField("mServedView");
|
||||
mHField.setAccessible(true);
|
||||
finishInputLockedMethod = InputMethodManager.class.getDeclaredMethod("finishInputLocked");
|
||||
finishInputLockedMethod.setAccessible(true);
|
||||
focusInMethod = InputMethodManager.class.getDeclaredMethod("focusIn", View.class);
|
||||
focusInMethod.setAccessible(true);
|
||||
} catch (Exception unexpected) {
|
||||
Log.e("IMMLeaks", "Unexpected reflection exception", unexpected);
|
||||
return;
|
||||
}
|
||||
|
||||
application.registerActivityLifecycleCallbacks(new LifecycleCallbacksAdapter() {
|
||||
@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
ReferenceCleaner cleaner =
|
||||
new ReferenceCleaner(inputMethodManager, mHField, mServedViewField,
|
||||
finishInputLockedMethod);
|
||||
View rootView = activity.getWindow().getDecorView().getRootView();
|
||||
ViewTreeObserver viewTreeObserver = rootView.getViewTreeObserver();
|
||||
viewTreeObserver.addOnGlobalFocusChangeListener(cleaner);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package cn.bmob.imdemo.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.os.Bundle;
|
||||
|
||||
/** Helper to avoid implementing all lifecycle callback methods. */
|
||||
public class LifecycleCallbacksAdapter implements Application.ActivityLifecycleCallbacks {
|
||||
@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onActivityStarted(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onActivityResumed(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onActivityPaused(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onActivityStopped(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onActivityDestroyed(Activity activity) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package cn.bmob.imdemo.util;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author :smile
|
||||
* @project:TimeUtil
|
||||
* @date :2016-01-26-17:27
|
||||
*/
|
||||
public class TimeUtil {
|
||||
|
||||
public final static String FORMAT_TIME = "HH:mm";
|
||||
public final static String FORMAT_DATE_TIME = "yyyy-MM-dd HH:mm";
|
||||
public final static String FORMAT_DATE_TIME_SECOND = "yyyy-MM-dd HH:mm:ss";
|
||||
public final static String FORMAT_MONTH_DAY_TIME = "MM-dd HH:mm";
|
||||
|
||||
public static String getFormatToday(String dateFormat) {
|
||||
Date currentTime = new Date();
|
||||
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
|
||||
return formatter.format(currentTime);
|
||||
}
|
||||
|
||||
public static Date stringToDate(String dateStr, String dateFormat) {
|
||||
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
|
||||
try {
|
||||
return formatter.parse(dateStr);
|
||||
} catch (ParseException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static String dateToString(Date date, String dateFormat) {
|
||||
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
|
||||
return formatter.format(date);
|
||||
}
|
||||
|
||||
public static String getChatTime(boolean hasYear,long timesamp) {
|
||||
long clearTime = timesamp;
|
||||
String result;
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd");
|
||||
Date today = new Date(System.currentTimeMillis());
|
||||
Date otherDay = new Date(clearTime);
|
||||
int temp = Integer.parseInt(sdf.format(today))
|
||||
- Integer.parseInt(sdf.format(otherDay));
|
||||
switch (temp) {
|
||||
case 0:
|
||||
result = "今天 " + getHourAndMin(clearTime);
|
||||
break;
|
||||
case 1:
|
||||
result = "昨天 " + getHourAndMin(clearTime);
|
||||
break;
|
||||
case 2:
|
||||
result = "前天 " + getHourAndMin(clearTime);
|
||||
break;
|
||||
default:
|
||||
result = getTime(hasYear,clearTime);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getTime(boolean hasYear,long time) {
|
||||
String pattern=FORMAT_DATE_TIME;
|
||||
if(!hasYear){
|
||||
pattern = FORMAT_MONTH_DAY_TIME;
|
||||
}
|
||||
SimpleDateFormat format = new SimpleDateFormat(pattern);
|
||||
return format.format(new Date(time));
|
||||
}
|
||||
|
||||
public static String getHourAndMin(long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat(FORMAT_TIME);
|
||||
return format.format(new Date(time));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package cn.bmob.imdemo.util;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author smile
|
||||
* @project Util
|
||||
* @date 2016-03-01-14:55
|
||||
*/
|
||||
public class Util {
|
||||
public static boolean checkSdCard() {
|
||||
if (android.os.Environment.getExternalStorageState().equals(
|
||||
android.os.Environment.MEDIA_MOUNTED))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package com.baidu.location.service;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.baidu.location.BDLocationListener;
|
||||
import com.baidu.location.LocationClient;
|
||||
import com.baidu.location.LocationClientOption;
|
||||
import com.baidu.location.LocationClientOption.LocationMode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author baidu
|
||||
*
|
||||
*/
|
||||
public class LocationService {
|
||||
private LocationClient client = null;
|
||||
private LocationClientOption mOption,DIYoption;
|
||||
private Object objLock = new Object();
|
||||
|
||||
/***
|
||||
*
|
||||
* @param locationContext
|
||||
*/
|
||||
public LocationService(Context locationContext){
|
||||
synchronized (objLock) {
|
||||
if(client == null){
|
||||
client = new LocationClient(locationContext);
|
||||
client.setLocOption(getDefaultLocationClientOption());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
*
|
||||
* @param listener
|
||||
* @return
|
||||
*/
|
||||
|
||||
public boolean registerListener(BDLocationListener listener){
|
||||
boolean isSuccess = false;
|
||||
if(listener != null){
|
||||
client.registerLocationListener(listener);
|
||||
isSuccess = true;
|
||||
}
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
public void unregisterListener(BDLocationListener listener){
|
||||
if(listener != null){
|
||||
client.unRegisterLocationListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
*
|
||||
* @param option
|
||||
* @return isSuccessSetOption
|
||||
*/
|
||||
public boolean setLocationOption(LocationClientOption option){
|
||||
boolean isSuccess = false;
|
||||
if(option != null){
|
||||
if(client.isStarted())
|
||||
client.stop();
|
||||
DIYoption = option;
|
||||
client.setLocOption(option);
|
||||
isSuccess = true;
|
||||
}
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
public LocationClientOption getOption(){
|
||||
return DIYoption;
|
||||
}
|
||||
/***
|
||||
*
|
||||
* @return DefaultLocationClientOption
|
||||
*/
|
||||
public LocationClientOption getDefaultLocationClientOption(){
|
||||
if(mOption == null){
|
||||
mOption = new LocationClientOption();
|
||||
mOption.setLocationMode(LocationMode.Hight_Accuracy);//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
|
||||
mOption.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系,如果配合百度地图使用,建议设置为bd09ll;
|
||||
mOption.setScanSpan(3000);//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的
|
||||
mOption.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
|
||||
mOption.setIsNeedLocationDescribe(true);//可选,设置是否需要地址描述
|
||||
mOption.setNeedDeviceDirect(false);//可选,设置是否需要设备方向结果
|
||||
mOption.setLocationNotify(false);//可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果
|
||||
mOption.setIgnoreKillProcess(true);//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
|
||||
mOption.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
|
||||
mOption.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
|
||||
mOption.SetIgnoreCacheException(false);//可选,默认false,设置是否收集CRASH信息,默认收集
|
||||
}
|
||||
return mOption;
|
||||
}
|
||||
|
||||
public void start(){
|
||||
synchronized (objLock) {
|
||||
if(client != null && !client.isStarted()){
|
||||
client.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void stop(){
|
||||
synchronized (objLock) {
|
||||
if(client != null && client.isStarted()){
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.baidu.location.service;
|
||||
|
||||
public class Utils {
|
||||
public final static String CoorType_GCJ02 = "gcj02";
|
||||
public final static String CoorType_BD09LL= "bd09ll";
|
||||
public final static String CoorType_BD09MC= "bd09";
|
||||
/***
|
||||
*61 : GPS定位结果,GPS定位成功。
|
||||
*62 : 无法获取有效定位依据,定位失败,请检查运营商网络或者wifi网络是否正常开启,尝试重新请求定位。
|
||||
*63 : 网络异常,没有成功向服务器发起请求,请确认当前测试手机网络是否通畅,尝试重新请求定位。
|
||||
*65 : 定位缓存的结果。
|
||||
*66 : 离线定位结果。通过requestOfflineLocaiton调用时对应的返回结果。
|
||||
*67 : 离线定位失败。通过requestOfflineLocaiton调用时对应的返回结果。
|
||||
*68 : 网络连接失败时,查找本地离线定位时对应的返回结果。
|
||||
*161: 网络定位结果,网络定位定位成功。
|
||||
*162: 请求串密文解析失败。
|
||||
*167: 服务端定位失败,请您检查是否禁用获取位置信息权限,尝试重新请求定位。
|
||||
*502: key参数错误,请按照说明文档重新申请KEY。
|
||||
*505: key不存在或者非法,请按照说明文档重新申请KEY。
|
||||
*601: key服务被开发者自己禁用,请按照说明文档重新申请KEY。
|
||||
*602: key mcode不匹配,您的ak配置过程中安全码设置有问题,请确保:sha1正确,“;”分号是英文状态;且包名是您当前运行应用的包名,请按照说明文档重新申请KEY。
|
||||
*501~700:key验证失败,请按照说明文档重新申请KEY。
|
||||
*/
|
||||
|
||||
public static float[] EARTH_WEIGHT = {0.1f,0.2f,0.4f,0.6f,0.8f}; // 推算计算权重_地球
|
||||
//public static float[] MOON_WEIGHT = {0.0167f,0.033f,0.067f,0.1f,0.133f};
|
||||
//public static float[] MARS_WEIGHT = {0.034f,0.068f,0.152f,0.228f,0.304f};
|
||||
}
|
||||
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.
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