feat: 增加图片查看和音频播放
This commit is contained in:
commit
8e5f216b42
@ -136,9 +136,13 @@ dependencies {
|
|||||||
// 日志工具 https://github.com/elvishew/xLog/blob/master/README_ZH.md
|
// 日志工具 https://github.com/elvishew/xLog/blob/master/README_ZH.md
|
||||||
implementation 'com.elvishew:xlog:1.10.1'
|
implementation 'com.elvishew:xlog:1.10.1'
|
||||||
//加载图片的依赖包
|
//加载图片的依赖包
|
||||||
implementation ("com.github.bumptech.glide:glide:4.11.0") {
|
implementation("com.github.bumptech.glide:glide:4.11.0") {
|
||||||
exclude group: "com.android.support"
|
exclude group: "com.android.support"
|
||||||
}
|
}
|
||||||
|
// 多媒体播放库 https://github.com/JagarYousef/ChatVoicePlayer
|
||||||
|
implementation 'com.github.JagarYousef:ChatVoicePlayer:1.1.0'
|
||||||
|
// 图片查看器 https://github.com/XiaoGe-1996/ImageViewer
|
||||||
|
implementation 'com.github.XiaoGe-1996:ImageViewer:v1.0.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
kapt {
|
kapt {
|
||||||
|
@ -2,19 +2,19 @@ package com.navinfo.volvo.database
|
|||||||
|
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import com.navinfo.volvo.database.dao.MessageDao
|
import com.navinfo.volvo.database.dao.GreetingMessageDao
|
||||||
import com.navinfo.volvo.database.dao.UserDao
|
import com.navinfo.volvo.database.dao.UserDao
|
||||||
import com.navinfo.volvo.model.Attachment
|
import com.navinfo.volvo.database.entity.Attachment
|
||||||
import com.navinfo.volvo.model.Message
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
import com.navinfo.volvo.model.User
|
import com.navinfo.volvo.database.entity.User
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
entities = [Message::class, Attachment::class, User::class],
|
entities = [GreetingMessage::class, Attachment::class, User::class],
|
||||||
version = 1,
|
version = 1,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
)
|
)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
abstract fun getMessageDao(): MessageDao
|
abstract fun getMessageDao(): GreetingMessageDao
|
||||||
|
|
||||||
abstract fun getUserDao(): UserDao
|
abstract fun getUserDao(): UserDao
|
||||||
}
|
}
|
@ -1,191 +1,191 @@
|
|||||||
package com.navinfo.volvo.database;
|
//package com.navinfo.volvo.database;
|
||||||
|
//
|
||||||
|
//
|
||||||
import android.content.Context;
|
//import android.content.Context;
|
||||||
|
//
|
||||||
import androidx.annotation.NonNull;
|
//import androidx.annotation.NonNull;
|
||||||
import androidx.room.Database;
|
//import androidx.room.Database;
|
||||||
import androidx.room.Room;
|
//import androidx.room.Room;
|
||||||
import androidx.room.RoomDatabase;
|
//import androidx.room.RoomDatabase;
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
//import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||||
import androidx.sqlite.db.SupportSQLiteOpenHelper;
|
//import androidx.sqlite.db.SupportSQLiteOpenHelper;
|
||||||
|
//
|
||||||
import com.navinfo.volvo.database.dao.MessageDao;
|
//import com.navinfo.volvo.database.dao.MessageDao;
|
||||||
import com.navinfo.volvo.database.dao.UserDao;
|
//import com.navinfo.volvo.database.dao.UserDao;
|
||||||
import com.navinfo.volvo.model.Message;
|
//import com.navinfo.volvo.database.entity.Message;
|
||||||
import com.navinfo.volvo.model.Attachment;
|
//import com.navinfo.volvo.database.entity.Attachment;
|
||||||
import com.navinfo.volvo.model.User;
|
//import com.navinfo.volvo.database.entity.User;
|
||||||
import com.tencent.wcdb.database.SQLiteCipherSpec;
|
//import com.tencent.wcdb.database.SQLiteCipherSpec;
|
||||||
import com.tencent.wcdb.database.SQLiteDatabase;
|
//import com.tencent.wcdb.database.SQLiteDatabase;
|
||||||
|
//
|
||||||
import com.tencent.wcdb.room.db.WCDBOpenHelperFactory;
|
//import com.tencent.wcdb.room.db.WCDBOpenHelperFactory;
|
||||||
|
//
|
||||||
import android.os.AsyncTask;
|
//import android.os.AsyncTask;
|
||||||
import android.util.Log;
|
//import android.util.Log;
|
||||||
|
//
|
||||||
import com.tencent.wcdb.repair.BackupKit;
|
//import com.tencent.wcdb.repair.BackupKit;
|
||||||
import com.tencent.wcdb.repair.RecoverKit;
|
//import com.tencent.wcdb.repair.RecoverKit;
|
||||||
import com.tencent.wcdb.room.db.WCDBDatabase;
|
//import com.tencent.wcdb.room.db.WCDBDatabase;
|
||||||
|
//
|
||||||
@Database(entities = {Message.class, Attachment.class, User.class}, version = 1, exportSchema = false)
|
//@Database(entities = {Message.class, Attachment.class, User.class}, version = 1, exportSchema = false)
|
||||||
public abstract class MapLifeDataBase extends RoomDatabase {
|
//public abstract class MapLifeDataBase extends RoomDatabase {
|
||||||
// marking the instance as volatile to ensure atomic access to the variable
|
// // marking the instance as volatile to ensure atomic access to the variable
|
||||||
/**
|
// /**
|
||||||
* 数据库单例对象
|
// * 数据库单例对象
|
||||||
*/
|
// */
|
||||||
private static volatile MapLifeDataBase INSTANCE;
|
// private static volatile MapLifeDataBase INSTANCE;
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 要素数据库类
|
// * 要素数据库类
|
||||||
*/
|
// */
|
||||||
public abstract MessageDao getMessageDao();
|
// public abstract MessageDao getMessageDao();
|
||||||
|
//
|
||||||
public abstract UserDao getUserDao();
|
// public abstract UserDao getUserDao();
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 数据库秘钥
|
// * 数据库秘钥
|
||||||
*/
|
// */
|
||||||
private final static String DB_PASSWORD = "123456";
|
// private final static String DB_PASSWORD = "123456";
|
||||||
|
//
|
||||||
public static MapLifeDataBase getDatabase(final Context context, final String name) {
|
// public static MapLifeDataBase getDatabase(final Context context, final String name) {
|
||||||
if (INSTANCE == null) {
|
// if (INSTANCE == null) {
|
||||||
synchronized (MapLifeDataBase.class) {
|
// synchronized (MapLifeDataBase.class) {
|
||||||
if (INSTANCE == null) {
|
// if (INSTANCE == null) {
|
||||||
// [WCDB] To use Room library with WCDB, pass a WCDBOpenHelper factory object
|
// // [WCDB] To use Room library with WCDB, pass a WCDBOpenHelper factory object
|
||||||
// to the database builder with .openHelperFactory(...). In the factory object,
|
// // to the database builder with .openHelperFactory(...). In the factory object,
|
||||||
// you can specify passphrase and cipher options to open or create encrypted
|
// // you can specify passphrase and cipher options to open or create encrypted
|
||||||
// database, as well as optimization options like asynchronous checkpoint.
|
// // database, as well as optimization options like asynchronous checkpoint.
|
||||||
SQLiteCipherSpec cipherSpec = new SQLiteCipherSpec()
|
// SQLiteCipherSpec cipherSpec = new SQLiteCipherSpec()
|
||||||
.setPageSize(1024)
|
// .setPageSize(1024)
|
||||||
.setSQLCipherVersion(3);
|
// .setSQLCipherVersion(3);
|
||||||
WCDBOpenHelperFactory factory = new WCDBOpenHelperFactory()
|
// WCDBOpenHelperFactory factory = new WCDBOpenHelperFactory()
|
||||||
.passphrase(DB_PASSWORD.getBytes()) // passphrase to the database, remove this line for plain-text
|
// .passphrase(DB_PASSWORD.getBytes()) // passphrase to the database, remove this line for plain-text
|
||||||
.cipherSpec(cipherSpec) // cipher to use, remove for default settings
|
// .cipherSpec(cipherSpec) // cipher to use, remove for default settings
|
||||||
.writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed
|
// .writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed
|
||||||
.asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed
|
// .asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed
|
||||||
|
//
|
||||||
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), MapLifeDataBase.class, name)
|
// INSTANCE = Room.databaseBuilder(context.getApplicationContext(), MapLifeDataBase.class, name)
|
||||||
|
//
|
||||||
// [WCDB] Specify open helper to use WCDB database implementation instead
|
// // [WCDB] Specify open helper to use WCDB database implementation instead
|
||||||
// of the Android framework.
|
// // of the Android framework.
|
||||||
.openHelperFactory((SupportSQLiteOpenHelper.Factory) factory)
|
// .openHelperFactory((SupportSQLiteOpenHelper.Factory) factory)
|
||||||
|
//
|
||||||
// Wipes and rebuilds instead of migrating if no Migration object.
|
// // Wipes and rebuilds instead of migrating if no Migration object.
|
||||||
// Migration is not part of this codelab.
|
// // Migration is not part of this codelab.
|
||||||
.fallbackToDestructiveMigration().addCallback(sRoomDatabaseCallback).build();
|
// .fallbackToDestructiveMigration().addCallback(sRoomDatabaseCallback).build();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return INSTANCE;
|
// return INSTANCE;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* Override the onOpen method to populate the database.
|
// * Override the onOpen method to populate the database.
|
||||||
* For this sample, we clear the database every time it is created or opened.
|
// * For this sample, we clear the database every time it is created or opened.
|
||||||
* <p>
|
// * <p>
|
||||||
* If you want to populate the database only when the database is created for the 1st time,
|
// * If you want to populate the database only when the database is created for the 1st time,
|
||||||
* override RoomDatabase.Callback()#onCreate
|
// * override RoomDatabase.Callback()#onCreate
|
||||||
*/
|
// */
|
||||||
private static Callback sRoomDatabaseCallback = new Callback() {
|
// private static Callback sRoomDatabaseCallback = new Callback() {
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void onOpen(@NonNull SupportSQLiteDatabase db) {
|
// public void onOpen(@NonNull SupportSQLiteDatabase db) {
|
||||||
super.onOpen(db);
|
// super.onOpen(db);
|
||||||
// If you want to keep the data through app restarts,
|
// // If you want to keep the data through app restarts,
|
||||||
// comment out the following line.
|
// // comment out the following line.
|
||||||
new PopulateDbAsync(INSTANCE).execute();
|
// new PopulateDbAsync(INSTANCE).execute();
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* Populate the database in the background.
|
// * Populate the database in the background.
|
||||||
* If you want to start with more words, just add them.
|
// * If you want to start with more words, just add them.
|
||||||
*/
|
// */
|
||||||
private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
|
// private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
|
||||||
|
//
|
||||||
private final MessageDao messageDao;
|
// private final MessageDao messageDao;
|
||||||
|
//
|
||||||
PopulateDbAsync(MapLifeDataBase db) {
|
// PopulateDbAsync(MapLifeDataBase db) {
|
||||||
messageDao = db.getMessageDao();
|
// messageDao = db.getMessageDao();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected Void doInBackground(final Void... params) {
|
// protected Void doInBackground(final Void... params) {
|
||||||
// Start the app with a clean database every time.
|
// // Start the app with a clean database every time.
|
||||||
// Not needed if you only populate on creation.
|
// // Not needed if you only populate on creation.
|
||||||
//mDao.deleteAll();
|
// //mDao.deleteAll();
|
||||||
Log.e("qj", "doInBackground");
|
// Log.e("qj", "doInBackground");
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 数据恢复
|
// * 数据恢复
|
||||||
*/
|
// */
|
||||||
protected boolean recoverData() {
|
// protected boolean recoverData() {
|
||||||
if (INSTANCE != null) {
|
// if (INSTANCE != null) {
|
||||||
SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase();
|
// SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase();
|
||||||
RecoverKit recover = new RecoverKit(sqlite, // 要恢复到的目标 DB
|
// RecoverKit recover = new RecoverKit(sqlite, // 要恢复到的目标 DB
|
||||||
sqlite.getPath() + "-backup", // 备份文件
|
// sqlite.getPath() + "-backup", // 备份文件
|
||||||
DB_PASSWORD.getBytes() // 加密备份文件的密钥,非 DB 密钥
|
// DB_PASSWORD.getBytes() // 加密备份文件的密钥,非 DB 密钥
|
||||||
);
|
// );
|
||||||
int result = recover.run(false); // fatal 参数传 false 表示遇到错误忽略并继续,
|
// int result = recover.run(false); // fatal 参数传 false 表示遇到错误忽略并继续,
|
||||||
// 若传 true 遇到错误则中止并返回 FAILED
|
// // 若传 true 遇到错误则中止并返回 FAILED
|
||||||
switch (result) {
|
// switch (result) {
|
||||||
case RecoverKit.RESULT_OK:
|
// case RecoverKit.RESULT_OK:
|
||||||
/* 成功 */
|
// /* 成功 */
|
||||||
Log.e("qj", "sRoomDatabaseCallback==RecoverKit成功");
|
// Log.e("qj", "sRoomDatabaseCallback==RecoverKit成功");
|
||||||
return true;
|
// return true;
|
||||||
case RecoverKit.RESULT_CANCELED: /* 取消操作 */
|
// case RecoverKit.RESULT_CANCELED: /* 取消操作 */
|
||||||
Log.e("qj", "sRoomDatabaseCallback==RecoverKit取消操作");
|
// Log.e("qj", "sRoomDatabaseCallback==RecoverKit取消操作");
|
||||||
break;
|
// break;
|
||||||
case RecoverKit.RESULT_FAILED: /* 失败 */
|
// case RecoverKit.RESULT_FAILED: /* 失败 */
|
||||||
Log.e("qj", "sRoomDatabaseCallback==RecoverKit失败");
|
// Log.e("qj", "sRoomDatabaseCallback==RecoverKit失败");
|
||||||
break;
|
// break;
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
recover.release();
|
// recover.release();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* 备份数据
|
// * 备份数据
|
||||||
*/
|
// */
|
||||||
protected boolean backup() {
|
// protected boolean backup() {
|
||||||
Log.e("qj", "sRoomDatabaseCallback===backup==start");
|
// Log.e("qj", "sRoomDatabaseCallback===backup==start");
|
||||||
if (INSTANCE != null) {
|
// if (INSTANCE != null) {
|
||||||
//备份文件
|
// //备份文件
|
||||||
SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase();
|
// SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase();
|
||||||
BackupKit backup = new BackupKit(sqlite, // 要备份的 DB
|
// BackupKit backup = new BackupKit(sqlite, // 要备份的 DB
|
||||||
sqlite.getPath() + "-backup", // 备份文件
|
// sqlite.getPath() + "-backup", // 备份文件
|
||||||
"123456".getBytes(), // 加密备份文件的密钥,非 DB 密钥
|
// "123456".getBytes(), // 加密备份文件的密钥,非 DB 密钥
|
||||||
0, null);
|
// 0, null);
|
||||||
int result = backup.run();
|
// int result = backup.run();
|
||||||
switch (result) {
|
// switch (result) {
|
||||||
case BackupKit.RESULT_OK:
|
// case BackupKit.RESULT_OK:
|
||||||
/* 成功 */
|
// /* 成功 */
|
||||||
Log.e("qj", "sRoomDatabaseCallback==成功");
|
// Log.e("qj", "sRoomDatabaseCallback==成功");
|
||||||
return true;
|
// return true;
|
||||||
case BackupKit.RESULT_CANCELED:
|
// case BackupKit.RESULT_CANCELED:
|
||||||
/* 取消操作 */
|
// /* 取消操作 */
|
||||||
Log.e("qj", "sRoomDatabaseCallback==取消操作");
|
// Log.e("qj", "sRoomDatabaseCallback==取消操作");
|
||||||
break;
|
// break;
|
||||||
case BackupKit.RESULT_FAILED:
|
// case BackupKit.RESULT_FAILED:
|
||||||
/* 失败 */
|
// /* 失败 */
|
||||||
Log.e("qj", "sRoomDatabaseCallback==失败");
|
// Log.e("qj", "sRoomDatabaseCallback==失败");
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
backup.release();
|
// backup.release();
|
||||||
}
|
// }
|
||||||
Log.e("qj", "sRoomDatabaseCallback===backup==end");
|
// Log.e("qj", "sRoomDatabaseCallback===backup==end");
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
protected void release() {
|
// protected void release() {
|
||||||
INSTANCE = null;
|
// INSTANCE = null;
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.navinfo.volvo.database.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface GreetingMessageDao {
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun insert(vararg check: GreetingMessage)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM GreetingMessage where id =:id")
|
||||||
|
fun findCheckManagerById(id: Long): GreetingMessage?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM GreetingMessage")
|
||||||
|
fun findList(): List<GreetingMessage>
|
||||||
|
}
|
@ -1,19 +0,0 @@
|
|||||||
package com.navinfo.volvo.database.dao
|
|
||||||
|
|
||||||
import androidx.room.Dao
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.OnConflictStrategy
|
|
||||||
import androidx.room.Query
|
|
||||||
import com.navinfo.volvo.model.Message
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
interface MessageDao {
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
fun insert(vararg check: Message)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Message where id =:id")
|
|
||||||
fun findCheckManagerById(id: Long): Message?
|
|
||||||
|
|
||||||
@Query("SELECT * FROM Message")
|
|
||||||
fun findList(): List<Message>
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ package com.navinfo.volvo.database.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import com.navinfo.volvo.model.User
|
import com.navinfo.volvo.database.entity.User
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface UserDao {
|
interface UserDao {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.navinfo.volvo.model
|
package com.navinfo.volvo.database.entity
|
||||||
|
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
@ -8,7 +8,7 @@ import com.navinfo.volvo.tools.GsonUtil
|
|||||||
|
|
||||||
@Entity(tableName = "Attachment")
|
@Entity(tableName = "Attachment")
|
||||||
data class Attachment(
|
data class Attachment(
|
||||||
@PrimaryKey()
|
@PrimaryKey
|
||||||
var id: String,
|
var id: String,
|
||||||
var pathUrl: String,
|
var pathUrl: String,
|
||||||
var attachmentType: AttachmentType
|
var attachmentType: AttachmentType
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.navinfo.volvo.database.entity
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
import androidx.room.TypeConverters
|
||||||
|
import org.jetbrains.annotations.NotNull
|
||||||
|
|
||||||
|
@Entity(tableName = "GreetingMessage")
|
||||||
|
@TypeConverters(AttachmentConverters::class)
|
||||||
|
data class GreetingMessage @JvmOverloads constructor(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var uuid:Long = 0,
|
||||||
|
var id: Long = 0,
|
||||||
|
var searchValue: String? = "",
|
||||||
|
var createBy: String? = "",
|
||||||
|
var createTime: String? = "",
|
||||||
|
var updateBy: String? = "",
|
||||||
|
var updateTime: String? = "",
|
||||||
|
var remark: String? = "",
|
||||||
|
var name: String? = "",
|
||||||
|
var imageUrl: String? = "",
|
||||||
|
var mediaUrl: String? = "",
|
||||||
|
var who: String? = "",
|
||||||
|
var toWho: String? = "",
|
||||||
|
var sendDate: String? = "",
|
||||||
|
var status: String? = "",
|
||||||
|
var isSkip: String? = "",
|
||||||
|
var skipUrl: String? = "",
|
||||||
|
var startTime: String? = "",
|
||||||
|
var endTime: String? = "",
|
||||||
|
var sendVehicle: String? = "",
|
||||||
|
var sendSex: String? = "",
|
||||||
|
var sendAge: String? = "",
|
||||||
|
var sendNum: String? = "",
|
||||||
|
var sendVins: String? = "",
|
||||||
|
var sendType: String? = "",
|
||||||
|
var del: String? = "",
|
||||||
|
var version: String? = "",
|
||||||
|
// /**
|
||||||
|
// * 附件列表
|
||||||
|
// */
|
||||||
|
// var attachment: MutableList<Attachment> = mutableListOf()
|
||||||
|
) {
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.navinfo.volvo.model
|
package com.navinfo.volvo.database.entity
|
||||||
|
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
@ -7,8 +7,6 @@ import androidx.room.TypeConverters
|
|||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.navinfo.volvo.tools.GsonUtil
|
import com.navinfo.volvo.tools.GsonUtil
|
||||||
import org.jetbrains.annotations.NotNull
|
import org.jetbrains.annotations.NotNull
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.LocalTime
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Entity(tableName = "User")
|
@Entity(tableName = "User")
|
@ -3,7 +3,7 @@ package com.navinfo.volvo.di.module
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import com.navinfo.volvo.database.AppDatabase
|
import com.navinfo.volvo.database.AppDatabase
|
||||||
import com.navinfo.volvo.database.dao.MessageDao
|
import com.navinfo.volvo.database.dao.GreetingMessageDao
|
||||||
import com.navinfo.volvo.database.dao.UserDao
|
import com.navinfo.volvo.database.dao.UserDao
|
||||||
import com.tencent.wcdb.database.SQLiteCipherSpec
|
import com.tencent.wcdb.database.SQLiteCipherSpec
|
||||||
import com.tencent.wcdb.room.db.WCDBOpenHelperFactory
|
import com.tencent.wcdb.room.db.WCDBOpenHelperFactory
|
||||||
@ -45,7 +45,7 @@ class DatabaseModule {
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideMessageDao(database: AppDatabase): MessageDao {
|
fun provideMessageDao(database: AppDatabase): GreetingMessageDao {
|
||||||
return database.getMessageDao()
|
return database.getMessageDao()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
86
app/src/main/java/com/navinfo/volvo/http/DownloadManager.kt
Normal file
86
app/src/main/java/com/navinfo/volvo/http/DownloadManager.kt
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package com.navinfo.volvo.http
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import okhttp3.ResponseBody
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
object DownloadManager {
|
||||||
|
suspend fun download(url: String, file: File): Flow<DownloadState> {
|
||||||
|
return flow {
|
||||||
|
val retrofit = Retrofit.Builder()
|
||||||
|
.baseUrl(UrlUtils.getBaseUrl(url))
|
||||||
|
.build()
|
||||||
|
val response = retrofit.create(NavinfoVolvoService::class.java).downloadFile(url).execute()
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
saveToFile(response.body()!!, file) {
|
||||||
|
emit(DownloadState.InProgress(it))
|
||||||
|
}
|
||||||
|
emit(DownloadState.Success(file))
|
||||||
|
} else {
|
||||||
|
emit(DownloadState.Error(IOException(response.toString())))
|
||||||
|
}
|
||||||
|
}.catch {
|
||||||
|
emit(DownloadState.Error(it))
|
||||||
|
}.flowOn(Dispatchers.IO)
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun saveToFile(responseBody: ResponseBody, file: File, progressListener: (Int) -> Unit) {
|
||||||
|
val total = responseBody.contentLength()
|
||||||
|
var bytesCopied = 0
|
||||||
|
var emittedProgress = 0
|
||||||
|
file.outputStream().use { output ->
|
||||||
|
val input = responseBody.byteStream()
|
||||||
|
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
|
||||||
|
var bytes = input.read(buffer)
|
||||||
|
while (bytes >= 0) {
|
||||||
|
output.write(buffer, 0, bytes)
|
||||||
|
bytesCopied += bytes
|
||||||
|
bytes = input.read(buffer)
|
||||||
|
val progress = (bytesCopied * 100 / total).toInt()
|
||||||
|
if (progress - emittedProgress > 0) {
|
||||||
|
progressListener(progress)
|
||||||
|
emittedProgress = progress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class DownloadState {
|
||||||
|
data class InProgress(val progress: Int) : DownloadState()
|
||||||
|
data class Success(val file: File) : DownloadState()
|
||||||
|
data class Error(val throwable: Throwable) : DownloadState()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DownloadCallback {
|
||||||
|
fun progress(progress: Int)
|
||||||
|
fun error(throwable: Throwable)
|
||||||
|
fun success(file: File)
|
||||||
|
}
|
||||||
|
|
||||||
|
object UrlUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从url分割出BaseUrl
|
||||||
|
*/
|
||||||
|
fun getBaseUrl(url: String): String {
|
||||||
|
var mutableUrl = url
|
||||||
|
var head = ""
|
||||||
|
var index = mutableUrl.indexOf("://")
|
||||||
|
if (index != -1) {
|
||||||
|
head = mutableUrl.substring(0, index + 3)
|
||||||
|
mutableUrl = mutableUrl.substring(index + 3)
|
||||||
|
}
|
||||||
|
index = mutableUrl.indexOf("/")
|
||||||
|
if (index != -1) {
|
||||||
|
mutableUrl = mutableUrl.substring(0, index + 1)
|
||||||
|
}
|
||||||
|
return head + mutableUrl
|
||||||
|
}
|
||||||
|
}
|
@ -2,11 +2,9 @@ package com.navinfo.volvo.http
|
|||||||
|
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.ResponseBody
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.*
|
||||||
import retrofit2.http.Multipart
|
|
||||||
import retrofit2.http.POST
|
|
||||||
import retrofit2.http.Part
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
interface NavinfoVolvoService {
|
interface NavinfoVolvoService {
|
||||||
@ -23,4 +21,7 @@ interface NavinfoVolvoService {
|
|||||||
suspend fun uploadAttachment(@Part attachmentFile: MultipartBody.Part):DefaultResponse<MutableMap<String, String>>
|
suspend fun uploadAttachment(@Part attachmentFile: MultipartBody.Part):DefaultResponse<MutableMap<String, String>>
|
||||||
@POST("/img/download")
|
@POST("/img/download")
|
||||||
suspend fun downLoadAttachment(@Body downloadData: Map<String, String>):DefaultResponse<String>
|
suspend fun downLoadAttachment(@Body downloadData: Map<String, String>):DefaultResponse<String>
|
||||||
|
@Streaming
|
||||||
|
@GET
|
||||||
|
fun downloadFile(@Url url: String): Call<ResponseBody>
|
||||||
}
|
}
|
@ -1,46 +0,0 @@
|
|||||||
package com.navinfo.volvo.model
|
|
||||||
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
import androidx.room.TypeConverters
|
|
||||||
|
|
||||||
@Entity(tableName = "message")
|
|
||||||
@TypeConverters(AttachmentConverters::class)
|
|
||||||
data class Message @JvmOverloads constructor(
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
|
||||||
var id: Long = 0,
|
|
||||||
|
|
||||||
var netId: String = "",
|
|
||||||
/**
|
|
||||||
*标题
|
|
||||||
*/
|
|
||||||
var title: String = "",
|
|
||||||
/**
|
|
||||||
* 信息内容
|
|
||||||
*/
|
|
||||||
var message: String = "",
|
|
||||||
/**
|
|
||||||
* 操作时间
|
|
||||||
*/
|
|
||||||
var optionDate: String = "",
|
|
||||||
/**
|
|
||||||
* 发送时间
|
|
||||||
*/
|
|
||||||
var sendDate: String = "",
|
|
||||||
/**
|
|
||||||
* 信息状态
|
|
||||||
*/
|
|
||||||
var status: Int = 1,
|
|
||||||
/**
|
|
||||||
* 发送者ID
|
|
||||||
*/
|
|
||||||
var fromId: String = "",
|
|
||||||
/**
|
|
||||||
* 接收者ID
|
|
||||||
*/
|
|
||||||
var toId: String = "",
|
|
||||||
/**
|
|
||||||
* 附件列表
|
|
||||||
*/
|
|
||||||
var attachment: MutableList<Attachment> = mutableListOf()
|
|
||||||
)
|
|
@ -1,6 +1,6 @@
|
|||||||
package com.navinfo.volvo.model.network
|
package com.navinfo.volvo.model.messagelist
|
||||||
|
|
||||||
data class NetworkPostMessage(
|
data class NetworkMessageListPost(
|
||||||
val name: String,//问候名称,非必填项
|
val name: String,//问候名称,非必填项
|
||||||
val who: String, //我是谁
|
val who: String, //我是谁
|
||||||
val toWho: String, //发送给谁
|
val toWho: String, //发送给谁
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.navinfo.volvo.model.messagelist
|
||||||
|
|
||||||
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
|
|
||||||
|
data class NetworkMessageListResponse(
|
||||||
|
val total: Int,
|
||||||
|
val rows: List<GreetingMessage>
|
||||||
|
)
|
@ -1,9 +1,10 @@
|
|||||||
package com.navinfo.volvo.repository
|
package com.navinfo.volvo.repository
|
||||||
|
|
||||||
import com.navinfo.volvo.model.Message
|
import com.navinfo.volvo.http.DefaultResponse
|
||||||
import com.navinfo.volvo.model.network.NetworkPostMessage
|
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
|
||||||
|
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
|
||||||
import com.navinfo.volvo.util.NetResult
|
import com.navinfo.volvo.util.NetResult
|
||||||
|
|
||||||
interface NetworkDataSource {
|
interface NetworkDataSource {
|
||||||
suspend fun getCardList(message: NetworkPostMessage): NetResult<List<Message>>
|
suspend fun getCardList(message: NetworkMessageListPost): NetResult<DefaultResponse<NetworkMessageListResponse>>
|
||||||
}
|
}
|
@ -1,15 +1,17 @@
|
|||||||
package com.navinfo.volvo.repository
|
package com.navinfo.volvo.repository
|
||||||
|
|
||||||
|
import com.navinfo.volvo.database.AppDatabase
|
||||||
|
import com.navinfo.volvo.database.dao.GreetingMessageDao
|
||||||
import com.navinfo.volvo.di.scope.IoDispatcher
|
import com.navinfo.volvo.di.scope.IoDispatcher
|
||||||
import com.navinfo.volvo.model.Message
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
import com.navinfo.volvo.model.network.NetworkPostMessage
|
import com.navinfo.volvo.http.DefaultResponse
|
||||||
|
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
|
||||||
|
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
|
||||||
import com.navinfo.volvo.repository.service.NetworkService
|
import com.navinfo.volvo.repository.service.NetworkService
|
||||||
import com.navinfo.volvo.tools.GsonUtil
|
import com.navinfo.volvo.tools.GsonUtil
|
||||||
import com.navinfo.volvo.util.NetResult
|
import com.navinfo.volvo.util.NetResult
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.FormBody
|
|
||||||
import okhttp3.MediaType
|
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -17,17 +19,22 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class NetworkDataSourceImp @Inject constructor(
|
class NetworkDataSourceImp @Inject constructor(
|
||||||
private val netWorkService: NetworkService,
|
private val netWorkService: NetworkService,
|
||||||
|
private val messageDao: GreetingMessageDao,
|
||||||
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
||||||
) : NetworkDataSource {
|
) : NetworkDataSource {
|
||||||
|
|
||||||
override suspend fun getCardList(message: NetworkPostMessage): NetResult<List<Message>> =
|
override suspend fun getCardList(message: NetworkMessageListPost): NetResult<DefaultResponse<NetworkMessageListResponse>> =
|
||||||
withContext(ioDispatcher) {
|
withContext(ioDispatcher) {
|
||||||
return@withContext try {
|
return@withContext try {
|
||||||
val stringBody = GsonUtil.getInstance().toJson(message).toRequestBody("application/json;charset=utf-8".toMediaType())
|
val stringBody = GsonUtil.getInstance().toJson(message)
|
||||||
|
.toRequestBody("application/json;charset=utf-8".toMediaType())
|
||||||
val result = netWorkService.queryCardListByApp(stringBody)
|
val result = netWorkService.queryCardListByApp(stringBody)
|
||||||
if (result.isSuccessful) {
|
if (result.isSuccessful) {
|
||||||
val list = result.body()
|
val body = result.body()
|
||||||
NetResult.Success(list)
|
val list: MutableList<GreetingMessage> =
|
||||||
|
listOf(body!!.data!!.rows) as MutableList<GreetingMessage>
|
||||||
|
messageDao.insert(*list.map { it }.toTypedArray())
|
||||||
|
NetResult.Success(body)
|
||||||
} else {
|
} else {
|
||||||
NetResult.Success(null)
|
NetResult.Success(null)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.navinfo.volvo.repository.service
|
package com.navinfo.volvo.repository.service
|
||||||
|
|
||||||
import com.navinfo.volvo.model.Message
|
import com.navinfo.volvo.http.DefaultResponse
|
||||||
|
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
@ -8,5 +9,5 @@ import retrofit2.http.POST
|
|||||||
|
|
||||||
interface NetworkService {
|
interface NetworkService {
|
||||||
@POST("/navi/cardDelivery/queryCardListByApp")
|
@POST("/navi/cardDelivery/queryCardListByApp")
|
||||||
suspend fun queryCardListByApp(@Body body: RequestBody): Response<List<Message>>
|
suspend fun queryCardListByApp(@Body body: RequestBody): Response<DefaultResponse<NetworkMessageListResponse>>
|
||||||
}
|
}
|
@ -10,6 +10,7 @@ import androidx.navigation.ui.AppBarConfiguration
|
|||||||
import androidx.navigation.ui.setupActionBarWithNavController
|
import androidx.navigation.ui.setupActionBarWithNavController
|
||||||
import androidx.navigation.ui.setupWithNavController
|
import androidx.navigation.ui.setupWithNavController
|
||||||
import com.easytools.tools.FileUtils
|
import com.easytools.tools.FileUtils
|
||||||
|
import com.elvishew.xlog.BuildConfig
|
||||||
import com.elvishew.xlog.LogConfiguration
|
import com.elvishew.xlog.LogConfiguration
|
||||||
import com.elvishew.xlog.LogLevel
|
import com.elvishew.xlog.LogLevel
|
||||||
import com.elvishew.xlog.XLog
|
import com.elvishew.xlog.XLog
|
||||||
@ -25,7 +26,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||||||
import com.hjq.permissions.OnPermissionCallback
|
import com.hjq.permissions.OnPermissionCallback
|
||||||
import com.hjq.permissions.Permission
|
import com.hjq.permissions.Permission
|
||||||
import com.hjq.permissions.XXPermissions
|
import com.hjq.permissions.XXPermissions
|
||||||
import com.navinfo.volvo.BuildConfig
|
|
||||||
import com.navinfo.volvo.R
|
import com.navinfo.volvo.R
|
||||||
import com.navinfo.volvo.databinding.ActivityMainBinding
|
import com.navinfo.volvo.databinding.ActivityMainBinding
|
||||||
import com.navinfo.volvo.utils.SystemConstant
|
import com.navinfo.volvo.utils.SystemConstant
|
||||||
@ -55,7 +55,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onGranted(permissions: MutableList<String>, all: Boolean) {
|
override fun onGranted(permissions: MutableList<String>, all: Boolean) {
|
||||||
if (!all) {
|
if (!all) {
|
||||||
Toast.makeText(this@MainActivity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@MainActivity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 在SD卡创建项目目录
|
// 在SD卡创建项目目录
|
||||||
@ -64,7 +65,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onDenied(permissions: MutableList<String>, never: Boolean) {
|
override fun onDenied(permissions: MutableList<String>, never: Boolean) {
|
||||||
if (never) {
|
if (never) {
|
||||||
Toast.makeText(this@MainActivity, "永久拒绝授权,请手动授权文件读写权限", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@MainActivity, "永久拒绝授权,请手动授权文件读写权限", Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
// 如果是被永久拒绝就跳转到应用权限系统设置页面
|
// 如果是被永久拒绝就跳转到应用权限系统设置页面
|
||||||
XXPermissions.startPermissionActivity(this@MainActivity, permissions)
|
XXPermissions.startPermissionActivity(this@MainActivity, permissions)
|
||||||
} else {
|
} else {
|
||||||
@ -146,10 +148,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
val consolePrinter: Printer = ConsolePrinter() // 通过 System.out 打印日志到控制台的打印器
|
val consolePrinter: Printer = ConsolePrinter() // 通过 System.out 打印日志到控制台的打印器
|
||||||
|
|
||||||
val filePrinter: Printer = FilePrinter.Builder("${SystemConstant.ROOT_PATH}/Logs") // 指定保存日志文件的路径
|
val filePrinter: Printer =
|
||||||
.fileNameGenerator(DateFileNameGenerator()) // 指定日志文件名生成器,默认为 ChangelessFileNameGenerator("log")
|
FilePrinter.Builder("${SystemConstant.ROOT_PATH}/Logs") // 指定保存日志文件的路径
|
||||||
.backupStrategy(NeverBackupStrategy()) // 指定日志文件备份策略,默认为 FileSizeBackupStrategy(1024 * 1024)
|
.fileNameGenerator(DateFileNameGenerator()) // 指定日志文件名生成器,默认为 ChangelessFileNameGenerator("log")
|
||||||
.build()
|
.backupStrategy(NeverBackupStrategy()) // 指定日志文件备份策略,默认为 FileSizeBackupStrategy(1024 * 1024)
|
||||||
|
.build()
|
||||||
|
|
||||||
XLog.init( // 初始化 XLog
|
XLog.init( // 初始化 XLog
|
||||||
config, // 指定日志配置,如果不指定,会默认使用 new LogConfiguration.Builder().build()
|
config, // 指定日志配置,如果不指定,会默认使用 new LogConfiguration.Builder().build()
|
||||||
|
@ -7,18 +7,18 @@ import android.widget.ImageView
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.navinfo.volvo.R
|
import com.navinfo.volvo.R
|
||||||
import com.navinfo.volvo.model.Message
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
|
|
||||||
class MessageAdapter : RecyclerView.Adapter<MessageAdapter.MyViewHolder>() {
|
class MessageAdapter : RecyclerView.Adapter<MessageAdapter.MyViewHolder>() {
|
||||||
|
|
||||||
var itemList: MutableList<Message> = mutableListOf()
|
var itemList: MutableList<GreetingMessage> = mutableListOf()
|
||||||
|
|
||||||
fun addItem(message: Message) {
|
fun addItem(message: GreetingMessage) {
|
||||||
itemList.add(message)
|
itemList.add(message)
|
||||||
notifyItemInserted(itemList.size - 1)
|
notifyItemInserted(itemList.size - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setItem(messageList: MutableList<Message>){
|
fun setItem(messageList: MutableList<GreetingMessage>){
|
||||||
itemList = messageList
|
itemList = messageList
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
@ -35,8 +35,8 @@ class MessageAdapter : RecyclerView.Adapter<MessageAdapter.MyViewHolder>() {
|
|||||||
|
|
||||||
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
|
||||||
val message = itemList[position]
|
val message = itemList[position]
|
||||||
holder.toName.text = message.fromId
|
holder.toName.text = message.toWho
|
||||||
holder.messageText.text = message.message
|
holder.messageText.text = message.name
|
||||||
holder.sendTime.text = message.sendDate
|
holder.sendTime.text = message.sendDate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,9 @@ package com.navinfo.volvo.ui.fragments.home
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.navinfo.volvo.model.Message
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
import com.navinfo.volvo.model.network.NetworkPostMessage
|
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
|
||||||
|
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
|
||||||
import com.navinfo.volvo.repository.NetworkDataSource
|
import com.navinfo.volvo.repository.NetworkDataSource
|
||||||
import com.navinfo.volvo.util.NetResult
|
import com.navinfo.volvo.util.NetResult
|
||||||
import com.navinfo.volvo.util.asLiveData
|
import com.navinfo.volvo.util.asLiveData
|
||||||
@ -18,18 +19,18 @@ class MessageViewModel @Inject constructor(
|
|||||||
private val _isLoading = MutableLiveData<Boolean>()
|
private val _isLoading = MutableLiveData<Boolean>()
|
||||||
val isLoading = _isLoading.asLiveData()
|
val isLoading = _isLoading.asLiveData()
|
||||||
|
|
||||||
private val _messageList = MutableLiveData<List<Message>>()
|
private val _messageList = MutableLiveData<List<GreetingMessage>>()
|
||||||
val messageList = _messageList.asLiveData()
|
val messageList = _messageList.asLiveData()
|
||||||
|
|
||||||
fun getMessageList() {
|
fun getMessageList() {
|
||||||
_isLoading.postValue(true)
|
_isLoading.postValue(true)
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val messagePost = NetworkPostMessage(who = "北京测试", toWho = "volvo测试")
|
val messagePost = NetworkMessageListPost(who = "北京测试", toWho = "volvo测试")
|
||||||
when (val result = repository.getCardList(messagePost)) {
|
when (val result = repository.getCardList(messagePost)) {
|
||||||
is NetResult.Success -> {
|
is NetResult.Success -> {
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
if (result.data != null) {
|
if (result.data != null) {
|
||||||
val list = result.data
|
val list = (result.data.data as NetworkMessageListResponse).rows
|
||||||
_messageList.value = list
|
_messageList.value = list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import androidx.lifecycle.LiveData
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.navinfo.volvo.database.AppDatabase
|
import com.navinfo.volvo.database.AppDatabase
|
||||||
import com.navinfo.volvo.model.User
|
import com.navinfo.volvo.database.entity.User
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LoginViewModel @Inject constructor(private val dataBase: AppDatabase) : ViewModel() {
|
class LoginViewModel @Inject constructor(private val dataBase: AppDatabase) : ViewModel() {
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package com.navinfo.volvo.ui.fragments.message
|
package com.navinfo.volvo.ui.fragments.message
|
||||||
|
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
|
import android.graphics.Paint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.*
|
import android.view.View.*
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -13,12 +15,17 @@ import android.widget.ArrayAdapter
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.Navigation
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import com.easytools.tools.DateUtils
|
import com.easytools.tools.DateUtils
|
||||||
|
import com.easytools.tools.DeviceUtils
|
||||||
|
import com.easytools.tools.DisplayUtils
|
||||||
|
import com.easytools.tools.FileUtils
|
||||||
|
import com.easytools.tools.ResourceUtils
|
||||||
import com.easytools.tools.ToastUtils
|
import com.easytools.tools.ToastUtils
|
||||||
import com.elvishew.xlog.XLog
|
import com.elvishew.xlog.XLog
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
@ -28,15 +35,18 @@ import com.hjq.permissions.Permission
|
|||||||
import com.hjq.permissions.XXPermissions
|
import com.hjq.permissions.XXPermissions
|
||||||
import com.navinfo.volvo.R
|
import com.navinfo.volvo.R
|
||||||
import com.navinfo.volvo.RecorderLifecycleObserver
|
import com.navinfo.volvo.RecorderLifecycleObserver
|
||||||
|
import com.navinfo.volvo.database.entity.Attachment
|
||||||
|
import com.navinfo.volvo.database.entity.AttachmentType
|
||||||
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
import com.navinfo.volvo.databinding.FragmentObtainMessageBinding
|
import com.navinfo.volvo.databinding.FragmentObtainMessageBinding
|
||||||
import com.navinfo.volvo.http.NavinfoVolvoCall
|
import com.navinfo.volvo.http.DownloadCallback
|
||||||
import com.navinfo.volvo.model.Attachment
|
|
||||||
import com.navinfo.volvo.model.AttachmentType
|
|
||||||
import com.navinfo.volvo.model.Message
|
|
||||||
import com.navinfo.volvo.ui.markRequiredInRed
|
import com.navinfo.volvo.ui.markRequiredInRed
|
||||||
|
import com.navinfo.volvo.util.PhotoLoader
|
||||||
import com.navinfo.volvo.utils.EasyMediaFile
|
import com.navinfo.volvo.utils.EasyMediaFile
|
||||||
import com.navinfo.volvo.utils.SystemConstant
|
import com.navinfo.volvo.utils.SystemConstant
|
||||||
import com.nhaarman.supertooltips.ToolTip
|
import com.nhaarman.supertooltips.ToolTip
|
||||||
|
import indi.liyi.viewer.Utils
|
||||||
|
import indi.liyi.viewer.ViewData
|
||||||
import top.zibin.luban.Luban
|
import top.zibin.luban.Luban
|
||||||
import top.zibin.luban.OnCompressListener
|
import top.zibin.luban.OnCompressListener
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -56,6 +66,9 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
RecorderLifecycleObserver()
|
RecorderLifecycleObserver()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val dateSendFormat = "yyyy-MM-dd HH:mm:ss"
|
||||||
|
private val dateShowFormat = "yyyy-MM-dd HH:mm"
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and
|
||||||
// onDestroyView.
|
// onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
@ -68,67 +81,71 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
_binding = FragmentObtainMessageBinding.inflate(inflater, container, false)
|
_binding = FragmentObtainMessageBinding.inflate(inflater, container, false)
|
||||||
val root: View = binding.root
|
val root: View = binding.root
|
||||||
|
|
||||||
obtainMessageViewModel.setCurrentMessage(Message())
|
obtainMessageViewModel.setCurrentMessage(GreetingMessage())
|
||||||
|
|
||||||
obtainMessageViewModel?.getMessageLiveData()?.observe(
|
obtainMessageViewModel?.getMessageLiveData()?.observe(
|
||||||
viewLifecycleOwner, Observer {
|
viewLifecycleOwner, Observer {
|
||||||
// 初始化界面显示内容
|
// 初始化界面显示内容
|
||||||
if(it.title?.isNotEmpty() == true)
|
if(it.name?.isNotEmpty() == true)
|
||||||
binding.tvMessageTitle?.setText(it.title)
|
binding.tvMessageTitle?.setText(it.name)
|
||||||
if (it.sendDate?.isNotEmpty() == true) {
|
if (it.sendDate?.isNotEmpty() == true) {
|
||||||
// 获取当前发送时间,如果早于当前时间,则显示现在
|
// 获取当前发送时间,如果早于当前时间,则显示现在
|
||||||
val sendDate = DateUtils.str2Date(it.sendDate, "yyyy-MM-dd HH:mm:ss")
|
val sendDate = DateUtils.str2Date(it.sendDate, dateSendFormat)
|
||||||
if (sendDate<=Date()) {
|
if (sendDate<=Date()) {
|
||||||
binding.btnSendTime.text = "现在"
|
binding.btnSendTime.text = "现在"
|
||||||
} else {
|
} else {
|
||||||
binding.btnSendTime.text = it.sendDate
|
binding.btnSendTime.text = it.sendDate
|
||||||
}
|
}
|
||||||
|
} else { // 如果发送时间此时为空,自动设置发送时间为当前时间
|
||||||
|
it.sendDate = DateUtils.date2Str(Date(), dateSendFormat)
|
||||||
}
|
}
|
||||||
var hasPhoto = false
|
var hasPhoto = false
|
||||||
var hasAudio = false
|
var hasAudio = false
|
||||||
if (it.attachment.isNotEmpty()) {
|
if (it.imageUrl!=null&&it.imageUrl?.isNotEmpty() == true) {
|
||||||
// 展示照片文件或录音文件
|
hasPhoto = true
|
||||||
for (attachment in it.attachment) {
|
// Glide.with(this@ObtainMessageFragment)
|
||||||
if (attachment.attachmentType == AttachmentType.PIC) {
|
// .asBitmap().fitCenter()
|
||||||
Glide.with(context!!)
|
// .load(it.imageUrl)
|
||||||
.asBitmap().fitCenter()
|
// .diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
.load(attachment.pathUrl)
|
// .into(binding.imgMessageAttachment)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
// 如果当前attachment文件是本地文件,开始尝试网络上传
|
||||||
.into(binding.imgMessageAttachment)
|
val str = it.imageUrl?.replace("\\", "/")
|
||||||
// 显示名称
|
binding.tvPhotoName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG )
|
||||||
hasPhoto = true
|
if (!str!!.startsWith("http")) {
|
||||||
|
obtainMessageViewModel.uploadAttachment(File(it.imageUrl), AttachmentType.PIC)
|
||||||
// 如果当前attachment文件是本地文件,开始尝试网络上传
|
binding.tvPhotoName.text = str.substringAfterLast("/", "picture.jpg")
|
||||||
val str = attachment.pathUrl.replace("\\", "/")
|
} else {
|
||||||
if (!str.startsWith("http")) {
|
if (str.contains("?")) {
|
||||||
obtainMessageViewModel.uploadAttachment(File(attachment.pathUrl), attachment.attachmentType)
|
binding.tvPhotoName.text = str.substring(str.lastIndexOf("/")+1, str.indexOf("?"))
|
||||||
binding.tvPhotoName.text = str.substringAfterLast("/", "picture.jpg")
|
} else {
|
||||||
} else {
|
binding.tvPhotoName.text = str.substringAfterLast("/")
|
||||||
binding.tvPhotoName.text = str.substring(str.lastIndexOf("/"), str.indexOf("?"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (attachment.attachmentType == AttachmentType.AUDIO) {
|
|
||||||
hasAudio = true
|
|
||||||
|
|
||||||
// 如果当前attachment文件是本地文件,开始尝试网络上传
|
|
||||||
val str = attachment.pathUrl.replace("\\", "/")
|
|
||||||
if (!str.startsWith("http")) {
|
|
||||||
obtainMessageViewModel.uploadAttachment(File(attachment.pathUrl), attachment.attachmentType)
|
|
||||||
binding.tvAudioName.text = str.substringAfterLast("/", "audio.m4a")
|
|
||||||
} else {
|
|
||||||
val str = attachment.pathUrl.replace("\\", "/")
|
|
||||||
binding.tvAudioName.text = str.substring(str.lastIndexOf("/"), str.indexOf("?"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 如果当前attachment不为空,可以显示预览按钮
|
if (it.mediaUrl!=null&&it.mediaUrl?.isNotEmpty() == true) {
|
||||||
|
hasAudio = true
|
||||||
|
binding.tvAudioName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG )
|
||||||
|
// 如果当前attachment文件是本地文件,开始尝试网络上传
|
||||||
|
val str = it.mediaUrl?.replace("\\", "/")
|
||||||
|
if (!str!!.startsWith("http")) {
|
||||||
|
obtainMessageViewModel.uploadAttachment(File(it.mediaUrl),AttachmentType.AUDIO)
|
||||||
|
binding.tvAudioName.text = str.substringAfterLast("/", "audio.m4a")
|
||||||
|
} else {
|
||||||
|
if (str.contains("?")) {
|
||||||
|
binding.tvAudioName.text = str.substring(str.lastIndexOf("/")+1, str.indexOf("?"))
|
||||||
|
} else {
|
||||||
|
binding.tvAudioName.text = str.substringAfterLast("/")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
binding.layerPhotoResult.visibility = if (hasPhoto) VISIBLE else GONE
|
binding.layerPhotoResult.visibility = if (hasPhoto) VISIBLE else GONE
|
||||||
binding.layerGetPhoto.visibility = if (hasPhoto) GONE else VISIBLE
|
binding.layerGetPhoto.visibility = if (hasPhoto) GONE else VISIBLE
|
||||||
binding.imgMessageAttachment.visibility = if (hasPhoto) VISIBLE else GONE
|
// binding.imgMessageAttachment.visibility = if (hasPhoto) VISIBLE else GONE
|
||||||
|
|
||||||
binding.layerAudioResult.visibility = if (hasAudio) VISIBLE else GONE
|
binding.layerAudioResult.visibility = if (hasAudio) VISIBLE else GONE
|
||||||
binding.layerGetAudio.visibility = if (hasAudio) GONE else VISIBLE
|
binding.layerGetAudio.visibility = if (hasAudio) GONE else VISIBLE
|
||||||
|
binding.llAudioPlay.visibility = if (hasAudio) VISIBLE else GONE
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
lifecycle.addObserver(recorderLifecycleObserver)
|
lifecycle.addObserver(recorderLifecycleObserver)
|
||||||
@ -138,27 +155,21 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
|
|
||||||
fun initView() {
|
fun initView() {
|
||||||
// 设置问候信息提示的红色星号
|
// 设置问候信息提示的红色星号
|
||||||
// binding.tiLayoutTitle.markRequiredInRed()
|
binding.tiLayoutTitle.markRequiredInRed()
|
||||||
// binding.tvMessageTitle.addTextChangedListener(afterTextChanged = {
|
binding.tvMessageTitle.addTextChangedListener(afterTextChanged = {
|
||||||
// obtainMessageViewModel.updateMessageTitle(it.toString())
|
obtainMessageViewModel.getMessageLiveData().value?.name = it.toString()
|
||||||
// })
|
})
|
||||||
|
|
||||||
binding.tvMessageTitle.setOnFocusChangeListener { view, b ->
|
|
||||||
if (!b) {
|
|
||||||
obtainMessageViewModel.updateMessageTitle(binding.tvMessageTitle.text.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.edtSendFrom.addTextChangedListener (afterTextChanged = {
|
binding.edtSendFrom.addTextChangedListener (afterTextChanged = {
|
||||||
obtainMessageViewModel.updateMessageSendFrom(it.toString())
|
obtainMessageViewModel.getMessageLiveData().value?.who = it.toString()
|
||||||
})
|
})
|
||||||
|
|
||||||
binding.imgPhotoDelete.setOnClickListener {
|
binding.imgPhotoDelete.setOnClickListener {
|
||||||
obtainMessageViewModel.updateMessagePic(null)
|
obtainMessageViewModel.updateMessagePic("")
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.imgAudioDelete.setOnClickListener {
|
binding.imgAudioDelete.setOnClickListener {
|
||||||
obtainMessageViewModel.updateMessageAudio(null)
|
obtainMessageViewModel.updateMessageAudio("")
|
||||||
}
|
}
|
||||||
|
|
||||||
val sendToArray = mutableListOf<String>("绑定车辆1(LYVXFEFEXNL754427)")
|
val sendToArray = mutableListOf<String>("绑定车辆1(LYVXFEFEXNL754427)")
|
||||||
@ -166,7 +177,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
android.R.layout.simple_dropdown_item_1line, android.R.id.text1, sendToArray)
|
android.R.layout.simple_dropdown_item_1line, android.R.id.text1, sendToArray)
|
||||||
binding.edtSendTo.onItemSelectedListener = object: OnItemSelectedListener {
|
binding.edtSendTo.onItemSelectedListener = object: OnItemSelectedListener {
|
||||||
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
|
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
|
||||||
obtainMessageViewModel.getMessageLiveData().value?.toId = sendToArray[p2]
|
obtainMessageViewModel.getMessageLiveData().value?.toWho = sendToArray[p2]
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNothingSelected(p0: AdapterView<*>?) {
|
override fun onNothingSelected(p0: AdapterView<*>?) {
|
||||||
@ -179,11 +190,11 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
val dialog = DateTimePickerFragment.newInstance().mode(0)
|
val dialog = DateTimePickerFragment.newInstance().mode(0)
|
||||||
dialog.listener = object : DateTimePickerFragment.OnClickListener {
|
dialog.listener = object : DateTimePickerFragment.OnClickListener {
|
||||||
override fun onClickListener(selectTime: String) {
|
override fun onClickListener(selectTime: String) {
|
||||||
val sendDate = DateUtils.str2Date(selectTime, "yyyy-MM-dd HH:mm")
|
val sendDate = DateUtils.str2Date(selectTime, dateShowFormat)
|
||||||
if (sendDate <= Date()) {
|
if (sendDate <= Date()) {
|
||||||
obtainMessageViewModel.updateMessageSendTime(DateUtils.date2Str(Date(), "yyyy-MM-dd HH:mm:ss"))
|
obtainMessageViewModel.updateMessageSendTime(DateUtils.date2Str(Date(), dateSendFormat))
|
||||||
} else {
|
} else {
|
||||||
obtainMessageViewModel.updateMessageSendTime(DateUtils.date2Str(sendDate, "yyyy-MM-dd HH:mm:ss"))
|
obtainMessageViewModel.updateMessageSendTime(DateUtils.date2Str(sendDate, dateSendFormat))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,10 +242,9 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
photoHelper.setCrop(false).selectAudio(activity!!)
|
photoHelper.setCrop(false).selectAudio(activity!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始录音
|
binding.btnStartRecord.setOnTouchListener { view, motionEvent ->
|
||||||
binding.btnStartRecord.setOnClickListener {
|
|
||||||
// 申请权限
|
// 申请权限
|
||||||
XXPermissions.with(this)
|
XXPermissions.with(this@ObtainMessageFragment)
|
||||||
// 申请单个权限
|
// 申请单个权限
|
||||||
.permission(Permission.RECORD_AUDIO)
|
.permission(Permission.RECORD_AUDIO)
|
||||||
.request(object : OnPermissionCallback {
|
.request(object : OnPermissionCallback {
|
||||||
@ -243,17 +253,23 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT).show()
|
Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT).show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
when(motionEvent.action) {
|
||||||
if (it.isSelected) {
|
MotionEvent.ACTION_DOWN-> {
|
||||||
it.isSelected = false
|
// 申请权限
|
||||||
val recorderAudioPath = recorderLifecycleObserver.stopAndReleaseRecorder()
|
recorderLifecycleObserver.initAndStartRecorder()
|
||||||
if (File(recorderAudioPath).exists()) {
|
ToastUtils.showToast("开始录音!")
|
||||||
obtainMessageViewModel.updateMessageAudio(recorderAudioPath)
|
false
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_UP -> {
|
||||||
|
val recorderAudioPath = recorderLifecycleObserver.stopAndReleaseRecorder()
|
||||||
|
if (File(recorderAudioPath).exists()) {
|
||||||
|
obtainMessageViewModel.updateMessageAudio(recorderAudioPath)
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
} else{
|
|
||||||
it.isSelected = true
|
|
||||||
|
|
||||||
recorderLifecycleObserver.initAndStartRecorder()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,6 +284,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取照片文件和音频文件
|
// 获取照片文件和音频文件
|
||||||
@ -296,8 +313,15 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
if (!it.absolutePath.equals(file?.absolutePath)) {
|
if (!it.absolutePath.equals(file?.absolutePath)) {
|
||||||
it?.delete()
|
it?.delete()
|
||||||
}
|
}
|
||||||
// 跳转回原Fragment,展示拍摄的照片
|
// 如果当前文件不在camera缓存文件夹下,则移动该文件
|
||||||
ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java).updateMessagePic(file!!.absolutePath)
|
if (!file!!.parentFile.absolutePath.equals(SystemConstant.CameraFolder)) {
|
||||||
|
FileUtils.renameFile(file.absolutePath, File(SystemConstant.CameraFolder, fileName).absolutePath)
|
||||||
|
// 跳转回原Fragment,展示拍摄的照片
|
||||||
|
ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java).updateMessagePic(File(SystemConstant.CameraFolder, fileName).absolutePath)
|
||||||
|
} else {
|
||||||
|
// 跳转回原Fragment,展示拍摄的照片
|
||||||
|
ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java).updateMessagePic(file!!.absolutePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
@ -306,7 +330,12 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
}).launch()
|
}).launch()
|
||||||
} else if (fileName.endsWith(".mp3")||fileName.endsWith(".wav")||fileName.endsWith(".amr")||fileName.endsWith(".m4a")) {
|
} else if (fileName.endsWith(".mp3")||fileName.endsWith(".wav")||fileName.endsWith(".amr")||fileName.endsWith(".m4a")) {
|
||||||
ToastUtils.showToast(it.absolutePath)
|
ToastUtils.showToast(it.absolutePath)
|
||||||
obtainMessageViewModel.updateMessageAudio(it.absolutePath)
|
if (!it.parentFile.parentFile.absolutePath.equals(SystemConstant.SoundFolder)) {
|
||||||
|
FileUtils.renameFile(it.absolutePath, File(SystemConstant.SoundFolder, fileName).absolutePath)
|
||||||
|
obtainMessageViewModel.updateMessageAudio(File(SystemConstant.SoundFolder, fileName).absolutePath)
|
||||||
|
} else {
|
||||||
|
obtainMessageViewModel.updateMessageAudio(it.absolutePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,76 +344,108 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
ToastUtils.showToast(it.message)
|
ToastUtils.showToast(it.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.voicePlayerView.setOnClickListener {
|
||||||
|
// 判断当前播放的文件是否在缓存文件夹内,如果不在首先下载该文件
|
||||||
|
val fileUrl = obtainMessageViewModel.getMessageLiveData().value!!.mediaUrl!!
|
||||||
|
val localFile = obtainMessageViewModel.getLocalFileFromNetUrl(fileUrl, AttachmentType.AUDIO)
|
||||||
|
if (!localFile.exists()) {
|
||||||
|
obtainMessageViewModel.downLoadFile(fileUrl, localFile, object: DownloadCallback {
|
||||||
|
override fun progress(progress: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun error(throwable: Throwable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun success(file: File) {
|
||||||
|
binding.voicePlayerView.setAudio(localFile.absolutePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
binding.voicePlayerView.setAudio(localFile.absolutePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
binding.btnObtainMessageBack.setOnClickListener {
|
binding.btnObtainMessageBack.setOnClickListener {
|
||||||
Navigation.findNavController(it).popBackStack()
|
Navigation.findNavController(it).popBackStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.btnObtainMessageConfirm.setOnClickListener {
|
binding.btnObtainMessageConfirm.setOnClickListener {
|
||||||
var checkResult = true
|
var checkResult = true
|
||||||
|
val toolTipBackColor = ResourceUtils.getColor(R.color.teal_200)
|
||||||
|
val toolTipTextColor = ResourceUtils.getColor(R.color.black)
|
||||||
// 检查当前输入数据
|
// 检查当前输入数据
|
||||||
val messageData = obtainMessageViewModel.getMessageLiveData().value
|
val messageData = obtainMessageViewModel.getMessageLiveData().value
|
||||||
if (messageData?.title?.isEmpty() == true) {
|
if (messageData?.name?.isEmpty() == true) {
|
||||||
val toolTipRelativeLayout =
|
val toolTipRelativeLayout =
|
||||||
binding.ttTitle
|
binding.ttTitle
|
||||||
val toolTip = ToolTip()
|
val toolTip = ToolTip()
|
||||||
.withText("请输入问候信息")
|
.withText("请输入问候信息")
|
||||||
.withColor(R.color.white)
|
.withColor(toolTipBackColor)
|
||||||
.withTextColor(R.color.black)
|
.withTextColor(toolTipTextColor)
|
||||||
|
.withoutShadow()
|
||||||
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
||||||
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tiLayoutTitle)
|
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tiLayoutTitle)
|
||||||
checkResult = false
|
checkResult = false
|
||||||
}
|
} else {
|
||||||
var hasPic = false
|
if (messageData?.name!!.length>10) {
|
||||||
var hasAudio = false
|
val toolTipRelativeLayout =
|
||||||
for (attachment in messageData?.attachment!!) {
|
binding.ttTitle
|
||||||
if (attachment.attachmentType == AttachmentType.PIC) {
|
val toolTip = ToolTip()
|
||||||
hasPic = true
|
.withText("问候信息长度不能超过10")
|
||||||
}
|
.withColor(toolTipBackColor)
|
||||||
if (attachment.attachmentType == AttachmentType.AUDIO) {
|
.withTextColor(toolTipTextColor)
|
||||||
hasAudio = true
|
.withoutShadow()
|
||||||
|
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
||||||
|
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tiLayoutTitle)
|
||||||
|
checkResult = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hasPic) {
|
if (messageData?.imageUrl?.isEmpty() == true) {
|
||||||
val toolTipRelativeLayout =
|
val toolTipRelativeLayout =
|
||||||
binding.ttPic
|
binding.ttPic
|
||||||
val toolTip = ToolTip()
|
val toolTip = ToolTip()
|
||||||
.withText("需要提供照片文件")
|
.withText("需要提供照片文件")
|
||||||
.withColor(R.color.white)
|
.withColor(toolTipBackColor)
|
||||||
.withTextColor(R.color.black)
|
.withTextColor(toolTipTextColor)
|
||||||
|
.withoutShadow()
|
||||||
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
||||||
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tvUploadPic)
|
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tvUploadPic)
|
||||||
checkResult = false
|
checkResult = false
|
||||||
}
|
}
|
||||||
if (!hasAudio) {
|
if (messageData?.mediaUrl?.isEmpty() == true) {
|
||||||
val toolTipRelativeLayout =
|
val toolTipRelativeLayout =
|
||||||
binding.ttAudio
|
binding.ttAudio
|
||||||
val toolTip = ToolTip()
|
val toolTip = ToolTip()
|
||||||
.withText("需要提供音频文件")
|
.withText("需要提供音频文件")
|
||||||
.withColor(R.color.white)
|
.withColor(toolTipBackColor)
|
||||||
.withTextColor(R.color.black)
|
.withTextColor(toolTipTextColor)
|
||||||
|
.withoutShadow()
|
||||||
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
||||||
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tvUploadPic)
|
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tvUploadPic)
|
||||||
checkResult = false
|
checkResult = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageData?.fromId?.isEmpty()==true) {
|
if (messageData?.who?.isEmpty()==true) {
|
||||||
val toolTipRelativeLayout =
|
val toolTipRelativeLayout =
|
||||||
binding.ttSendFrom
|
binding.ttSendFrom
|
||||||
val toolTip = ToolTip()
|
val toolTip = ToolTip()
|
||||||
.withText("请输入您的名称")
|
.withText("请输入您的名称")
|
||||||
.withColor(R.color.white)
|
.withColor(toolTipBackColor)
|
||||||
.withTextColor(R.color.black)
|
.withTextColor(toolTipTextColor)
|
||||||
|
.withoutShadow()
|
||||||
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
||||||
toolTipRelativeLayout.showToolTipForView(toolTip, binding.edtSendFrom)
|
toolTipRelativeLayout.showToolTipForView(toolTip, binding.edtSendFrom)
|
||||||
checkResult = false
|
checkResult = false
|
||||||
}
|
}
|
||||||
if (messageData?.toId?.isEmpty()==true) {
|
if (messageData?.toWho?.isEmpty()==true) {
|
||||||
val toolTipRelativeLayout =
|
val toolTipRelativeLayout =
|
||||||
binding.ttSendTo
|
binding.ttSendTo
|
||||||
val toolTip = ToolTip()
|
val toolTip = ToolTip()
|
||||||
.withText("请选择要发送的车辆")
|
.withText("请选择要发送的车辆")
|
||||||
.withColor(R.color.white)
|
.withColor(toolTipBackColor)
|
||||||
.withTextColor(R.color.black)
|
.withTextColor(toolTipTextColor)
|
||||||
|
.withoutShadow()
|
||||||
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
.withAnimationType(ToolTip.AnimationType.FROM_MASTER_VIEW)
|
||||||
toolTipRelativeLayout.showToolTipForView(toolTip, binding.edtSendTo)
|
toolTipRelativeLayout.showToolTipForView(toolTip, binding.edtSendTo)
|
||||||
checkResult = false
|
checkResult = false
|
||||||
@ -393,10 +454,13 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
if (checkResult) { // 检查通过
|
if (checkResult) { // 检查通过
|
||||||
// 检查attachment是否为本地数据,如果是本地则弹出对话框尝试上传
|
// 检查attachment是否为本地数据,如果是本地则弹出对话框尝试上传
|
||||||
val localAttachmentList = mutableListOf<Attachment>()
|
val localAttachmentList = mutableListOf<Attachment>()
|
||||||
for (attachment in messageData?.attachment!!) {
|
if (messageData?.imageUrl?.startsWith("http") == false) {
|
||||||
if (!attachment.pathUrl.startsWith("http")) {
|
val imageAttachment = Attachment("", messageData.imageUrl!!, AttachmentType.PIC)
|
||||||
localAttachmentList.add(attachment)
|
localAttachmentList.add(imageAttachment)
|
||||||
}
|
}
|
||||||
|
if (messageData?.mediaUrl?.startsWith("http") == false) {
|
||||||
|
val audioAttachment = Attachment("", messageData.mediaUrl!!, AttachmentType.AUDIO)
|
||||||
|
localAttachmentList.add(audioAttachment)
|
||||||
}
|
}
|
||||||
if (localAttachmentList.isNotEmpty()) {
|
if (localAttachmentList.isNotEmpty()) {
|
||||||
MaterialAlertDialogBuilder(context!!)
|
MaterialAlertDialogBuilder(context!!)
|
||||||
@ -408,21 +472,50 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
obtainMessageViewModel.uploadAttachment(File(attachment.pathUrl), attachment.attachmentType)
|
obtainMessageViewModel.uploadAttachment(File(attachment.pathUrl), attachment.attachmentType)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.setNegativeButton("取消", DialogInterface.OnClickListener {
|
||||||
|
dialogInterface, i -> dialogInterface.dismiss()
|
||||||
|
})
|
||||||
.show()
|
.show()
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查发送时间
|
// 检查发送时间
|
||||||
|
val sendDate = DateUtils.str2Date(messageData?.sendDate, dateSendFormat)
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.time = Date()
|
||||||
|
cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE)+1)
|
||||||
|
if (cal.time.time < sendDate.time) { // 发送时间设置小于当前时间1分钟前,Toast提示用户并自动设置发送时间
|
||||||
|
messageData?.sendDate = DateUtils.date2Str(cal.time, dateSendFormat)
|
||||||
|
ToastUtils.showToast("自动调整发送时间为1分钟后发送")
|
||||||
|
}
|
||||||
|
|
||||||
// 开始网络提交数据
|
// 开始网络提交数据
|
||||||
if (obtainMessageViewModel.getMessageLiveData().value?.netId!!.isEmpty()) { // 如果网络id为空,则调用更新操作
|
if (obtainMessageViewModel.getMessageLiveData().value?.id==0L) { // 如果网络id为空,则调用更新操作
|
||||||
obtainMessageViewModel.insertCardByApp()
|
obtainMessageViewModel.insertCardByApp()
|
||||||
} else {
|
} else {
|
||||||
obtainMessageViewModel.updateCardByApp()
|
obtainMessageViewModel.updateCardByApp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 点击照片名称
|
||||||
|
binding.tvPhotoName.setOnClickListener {
|
||||||
|
val viewData = ViewData()
|
||||||
|
viewData.imageSrc = obtainMessageViewModel.getMessageLiveData().value!!.imageUrl
|
||||||
|
viewData.targetX = Utils.dp2px(context, 10F).toFloat()
|
||||||
|
viewData.targetWidth = DisplayUtils.getScreenWidthPixels(activity) - Utils.dp2px(context, 20F)
|
||||||
|
viewData.targetHeight = Utils.dp2px(context, 200F)
|
||||||
|
val viewDataList = listOf(viewData)
|
||||||
|
binding.imageViewer.overlayStatusBar(true) // ImageViewer 是否会占据 StatusBar 的空间
|
||||||
|
.viewData(viewDataList) // 图片数据
|
||||||
|
.imageLoader(PhotoLoader()) // 设置图片加载方式
|
||||||
|
.showIndex(true) // 是否显示图片索引,默认为true
|
||||||
|
.watch(0) // 开启浏览
|
||||||
|
|
||||||
|
}
|
||||||
|
// 点击音频名称
|
||||||
|
binding.tvAudioName.setOnClickListener {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
package com.navinfo.volvo.ui.fragments.message
|
package com.navinfo.volvo.ui.fragments.message
|
||||||
|
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
|
import com.easytools.tools.FileUtils
|
||||||
import com.easytools.tools.ToastUtils
|
import com.easytools.tools.ToastUtils
|
||||||
import com.elvishew.xlog.XLog
|
import com.elvishew.xlog.XLog
|
||||||
|
import com.navinfo.volvo.database.entity.Attachment
|
||||||
|
import com.navinfo.volvo.database.entity.AttachmentType
|
||||||
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
|
import com.navinfo.volvo.http.DownloadCallback
|
||||||
|
import com.navinfo.volvo.http.DownloadManager
|
||||||
|
import com.navinfo.volvo.http.DownloadState
|
||||||
import com.navinfo.volvo.http.NavinfoVolvoCall
|
import com.navinfo.volvo.http.NavinfoVolvoCall
|
||||||
import com.navinfo.volvo.model.Attachment
|
import com.navinfo.volvo.utils.SystemConstant
|
||||||
import com.navinfo.volvo.model.AttachmentType
|
import kotlinx.coroutines.flow.Flow
|
||||||
import com.navinfo.volvo.model.Message
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
@ -17,72 +23,74 @@ import java.util.*
|
|||||||
|
|
||||||
|
|
||||||
class ObtainMessageViewModel: ViewModel() {
|
class ObtainMessageViewModel: ViewModel() {
|
||||||
private val msgLiveData: MutableLiveData<Message> by lazy {
|
private val msgLiveData: MutableLiveData<GreetingMessage> by lazy {
|
||||||
MutableLiveData<Message>()
|
MutableLiveData<GreetingMessage>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setCurrentMessage(msg: Message) {
|
fun setCurrentMessage(msg: GreetingMessage) {
|
||||||
msgLiveData.postValue(msg)
|
msgLiveData.postValue(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMessageLiveData(): MutableLiveData<Message> {
|
fun getMessageLiveData(): MutableLiveData<GreetingMessage> {
|
||||||
return msgLiveData
|
return msgLiveData
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新消息标题
|
// 更新消息标题
|
||||||
fun updateMessageTitle(title: String) {
|
fun updateMessageTitle(title: String) {
|
||||||
this.msgLiveData.value?.title = title
|
this.msgLiveData.value?.name = title
|
||||||
this.msgLiveData.postValue(this.msgLiveData.value)
|
this.msgLiveData.postValue(this.msgLiveData.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新消息附件中的照片文件
|
// 更新消息附件中的照片文件
|
||||||
fun updateMessagePic(picUrl: String?) {
|
fun updateMessagePic(picUrl: String?) {
|
||||||
var hasPic = false
|
// var hasPic = false
|
||||||
|
|
||||||
for (attachment in this.msgLiveData.value!!.attachment) {
|
this.msgLiveData.value?.imageUrl = picUrl
|
||||||
if (attachment.attachmentType == AttachmentType.PIC) {
|
// for (attachment in this.msgLiveData.value!!.attachment) {
|
||||||
if (picUrl==null||picUrl.isEmpty()) {
|
// if (attachment.attachmentType == AttachmentType.PIC) {
|
||||||
this.msgLiveData.value!!.attachment.remove(attachment)
|
// if (picUrl==null||picUrl.isEmpty()) {
|
||||||
} else {
|
// this.msgLiveData.value!!.attachment.remove(attachment)
|
||||||
attachment.pathUrl = picUrl
|
// } else {
|
||||||
}
|
// attachment.pathUrl = picUrl
|
||||||
hasPic = true
|
// }
|
||||||
}
|
// hasPic = true
|
||||||
}
|
// }
|
||||||
if (!hasPic&&picUrl!=null) {
|
// }
|
||||||
this.msgLiveData.value!!.attachment.add(Attachment(UUID.randomUUID().toString(), picUrl, AttachmentType.PIC))
|
// if (!hasPic&&picUrl!=null) {
|
||||||
}
|
// this.msgLiveData.value!!.attachment.add(Attachment(UUID.randomUUID().toString(), picUrl, AttachmentType.PIC))
|
||||||
|
// }
|
||||||
this.msgLiveData.postValue(this.msgLiveData.value)
|
this.msgLiveData.postValue(this.msgLiveData.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新消息附件中的录音文件
|
// 更新消息附件中的录音文件
|
||||||
fun updateMessageAudio(audioUrl: String?) {
|
fun updateMessageAudio(audioUrl: String?) {
|
||||||
var hasAudio = false
|
// var hasAudio = false
|
||||||
for (attachment in this.msgLiveData.value!!.attachment) {
|
// for (attachment in this.msgLiveData.value!!.attachment) {
|
||||||
if (attachment.attachmentType == AttachmentType.AUDIO) {
|
// if (attachment.attachmentType == AttachmentType.AUDIO) {
|
||||||
if (audioUrl==null||audioUrl.isEmpty()) {
|
// if (audioUrl==null||audioUrl.isEmpty()) {
|
||||||
this.msgLiveData.value!!.attachment.remove(attachment)
|
// this.msgLiveData.value!!.attachment.remove(attachment)
|
||||||
} else {
|
// } else {
|
||||||
attachment.pathUrl = audioUrl
|
// attachment.pathUrl = audioUrl
|
||||||
}
|
// }
|
||||||
hasAudio = true
|
// hasAudio = true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (!hasAudio&&audioUrl!=null) {
|
// if (!hasAudio&&audioUrl!=null) {
|
||||||
this.msgLiveData.value!!.attachment.add(Attachment(UUID.randomUUID().toString(), audioUrl, AttachmentType.AUDIO))
|
// this.msgLiveData.value!!.attachment.add(Attachment(UUID.randomUUID().toString(), audioUrl, AttachmentType.AUDIO))
|
||||||
}
|
// }
|
||||||
|
this.msgLiveData.value?.mediaUrl = audioUrl
|
||||||
this.msgLiveData.postValue(this.msgLiveData.value)
|
this.msgLiveData.postValue(this.msgLiveData.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新发送人
|
// 更新发送人
|
||||||
fun updateMessageSendFrom(sendFrom: String) {
|
fun updateMessageSendFrom(sendFrom: String) {
|
||||||
this.msgLiveData.value?.fromId = sendFrom
|
this.msgLiveData.value?.who = sendFrom
|
||||||
this.msgLiveData.postValue(this.msgLiveData.value)
|
this.msgLiveData.postValue(this.msgLiveData.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新接收人
|
// 更新接收人
|
||||||
fun updateMessageSendTo(sendTo: String) {
|
fun updateMessageSendTo(sendTo: String) {
|
||||||
this.msgLiveData.value?.toId = sendTo
|
this.msgLiveData.value?.toWho = sendTo
|
||||||
this.msgLiveData.postValue(this.msgLiveData.value)
|
this.msgLiveData.postValue(this.msgLiveData.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,30 +100,25 @@ class ObtainMessageViewModel: ViewModel() {
|
|||||||
this.msgLiveData.postValue(this.msgLiveData.value)
|
this.msgLiveData.postValue(this.msgLiveData.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取照片url
|
// // 获取照片url
|
||||||
fun getImageAttachment(attachementList: List<Attachment>): Attachment? {
|
// fun getImageAttachment(attachementList: List<Attachment>): Attachment? {
|
||||||
for (attachment in attachementList) {
|
// for (attachment in attachementList) {
|
||||||
if (attachment.attachmentType == AttachmentType.PIC) {
|
// if (attachment.attachmentType == AttachmentType.PIC) {
|
||||||
return attachment
|
// return attachment
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return null
|
// return null
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 获取音频url
|
// // 获取音频url
|
||||||
fun getAudioAttachment(attachementList: List<Attachment>): Attachment? {
|
// fun getAudioAttachment(attachementList: List<Attachment>): Attachment? {
|
||||||
for (attachment in attachementList) {
|
// for (attachment in attachementList) {
|
||||||
if (attachment.attachmentType == AttachmentType.AUDIO) {
|
// if (attachment.attachmentType == AttachmentType.AUDIO) {
|
||||||
return attachment
|
// return attachment
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return null
|
// return null
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 获取发送时间
|
|
||||||
fun getSendDate(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传附件文件
|
// 上传附件文件
|
||||||
fun uploadAttachment(attachmentFile: File, attachmentType: AttachmentType) {
|
fun uploadAttachment(attachmentFile: File, attachmentType: AttachmentType) {
|
||||||
@ -130,6 +133,21 @@ class ObtainMessageViewModel: ViewModel() {
|
|||||||
if (result.code == 200) { // 请求成功
|
if (result.code == 200) { // 请求成功
|
||||||
// 获取上传后的结果
|
// 获取上传后的结果
|
||||||
val fileKey = result.data?.get("fileKey")
|
val fileKey = result.data?.get("fileKey")
|
||||||
|
val newFileName = fileKey!!.substringAfterLast("/")
|
||||||
|
// 修改缓存文件名
|
||||||
|
if (attachmentType == AttachmentType.PIC) { // 修改当前文件在缓存文件夹的名称
|
||||||
|
val destFile = File(SystemConstant.CameraFolder, newFileName)
|
||||||
|
if (destFile.exists()) {
|
||||||
|
FileUtils.deleteFile(destFile)
|
||||||
|
}
|
||||||
|
FileUtils.renameFile(attachmentFile.absolutePath, destFile.absolutePath)
|
||||||
|
} else {
|
||||||
|
val destFile = File(SystemConstant.SoundFolder, newFileName)
|
||||||
|
if (destFile.exists()) {
|
||||||
|
FileUtils.deleteFile(destFile)
|
||||||
|
}
|
||||||
|
FileUtils.renameFile(attachmentFile.absolutePath, destFile.absolutePath)
|
||||||
|
}
|
||||||
if (fileKey!=null) {
|
if (fileKey!=null) {
|
||||||
downloadAttachment(fileKey, attachmentType)
|
downloadAttachment(fileKey, attachmentType)
|
||||||
}
|
}
|
||||||
@ -173,16 +191,41 @@ class ObtainMessageViewModel: ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun downLoadFile(url: String, destFile: File, downloadCallback: DownloadCallback){
|
||||||
|
viewModelScope.launch {
|
||||||
|
DownloadManager.download(
|
||||||
|
url,
|
||||||
|
destFile
|
||||||
|
).collect {
|
||||||
|
when (it) {
|
||||||
|
is DownloadState.InProgress -> {
|
||||||
|
XLog.d("~~~", "download in progress: ${it.progress}.")
|
||||||
|
downloadCallback.progress(it.progress)
|
||||||
|
}
|
||||||
|
is DownloadState.Success -> {
|
||||||
|
XLog.d("~~~", "download finished.")
|
||||||
|
downloadCallback.success(it.file)
|
||||||
|
}
|
||||||
|
is DownloadState.Error -> {
|
||||||
|
XLog.d("~~~", "download error: ${it.throwable}.")
|
||||||
|
downloadCallback.error(it.throwable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun insertCardByApp() {
|
fun insertCardByApp() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
|
// TODO 首先保存数据到本地
|
||||||
val message = msgLiveData.value
|
val message = msgLiveData.value
|
||||||
val insertData = mapOf(
|
val insertData = mapOf(
|
||||||
"name" to message?.title,
|
"name" to message?.name,
|
||||||
"imageUrl" to getImageAttachment(message?.attachment!!)?.pathUrl,
|
"imageUrl" to message?.imageUrl,
|
||||||
"mediaUrl" to getAudioAttachment(message?.attachment!!)?.pathUrl,
|
"mediaUrl" to message?.mediaUrl,
|
||||||
"who" to message?.fromId,
|
"who" to message?.who,
|
||||||
"toWho" to message?.toId,
|
"toWho" to message?.toWho,
|
||||||
"sendDate" to message?.sendDate
|
"sendDate" to message?.sendDate
|
||||||
)
|
)
|
||||||
val result = NavinfoVolvoCall.getApi().insertCardByApp(insertData as Map<String, String>)
|
val result = NavinfoVolvoCall.getApi().insertCardByApp(insertData as Map<String, String>)
|
||||||
@ -190,8 +233,9 @@ class ObtainMessageViewModel: ViewModel() {
|
|||||||
if (result.code == 200) { // 请求成功
|
if (result.code == 200) { // 请求成功
|
||||||
// 获取上传后的结果
|
// 获取上传后的结果
|
||||||
val netId = result.data
|
val netId = result.data
|
||||||
message.netId = netId!!
|
message?.id = netId!!.toLong()
|
||||||
// 尝试保存数据到本地
|
// TODO 尝试更新本地数据
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ToastUtils.showToast(result.msg)
|
ToastUtils.showToast(result.msg)
|
||||||
}
|
}
|
||||||
@ -206,21 +250,21 @@ class ObtainMessageViewModel: ViewModel() {
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
val message = msgLiveData.value
|
val message = msgLiveData.value
|
||||||
val insertData = mapOf(
|
val updateData = mapOf(
|
||||||
"id" to message?.netId,
|
"id" to message?.id,
|
||||||
"name" to message?.title,
|
"name" to message?.name,
|
||||||
"imageUrl" to getImageAttachment(message?.attachment!!)?.pathUrl,
|
"imageUrl" to message?.imageUrl,
|
||||||
"mediaUrl" to getAudioAttachment(message?.attachment!!)?.pathUrl,
|
"mediaUrl" to message?.mediaUrl,
|
||||||
"who" to message?.fromId,
|
"who" to message?.who,
|
||||||
"toWho" to message?.toId,
|
"toWho" to message?.toWho,
|
||||||
"sendDate" to message?.sendDate
|
"sendDate" to message?.sendDate
|
||||||
)
|
)
|
||||||
val result = NavinfoVolvoCall.getApi().updateCardByApp(insertData as Map<String, String>)
|
val result = NavinfoVolvoCall.getApi().updateCardByApp(updateData as Map<String, String>)
|
||||||
XLog.d("updateCardByApp:${result.code}")
|
XLog.d("updateCardByApp:${result.code}")
|
||||||
if (result.code == 200) { // 请求成功
|
if (result.code == 200) { // 请求成功
|
||||||
// 获取上传后的结果
|
// 获取上传后的结果
|
||||||
val netId = result.data
|
val netId = result.data
|
||||||
message.netId = netId!!
|
message?.id = netId!!.toLong()
|
||||||
// 尝试保存数据到本地
|
// 尝试保存数据到本地
|
||||||
} else {
|
} else {
|
||||||
ToastUtils.showToast(result.msg)
|
ToastUtils.showToast(result.msg)
|
||||||
@ -231,4 +275,20 @@ class ObtainMessageViewModel: ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据网络地址获取本地的缓存文件路径
|
||||||
|
* */
|
||||||
|
fun getLocalFileFromNetUrl(url: String, attachmentType: AttachmentType):File {
|
||||||
|
val folder = when(attachmentType) {
|
||||||
|
AttachmentType.PIC-> SystemConstant.CameraFolder
|
||||||
|
else -> SystemConstant.SoundFolder
|
||||||
|
}
|
||||||
|
var name = if (url.contains("?")) {
|
||||||
|
url.substring(url.lastIndexOf("/")+1, url.indexOf("?"))
|
||||||
|
} else {
|
||||||
|
url.substringAfterLast("/")
|
||||||
|
}
|
||||||
|
return File(folder, name)
|
||||||
|
}
|
||||||
}
|
}
|
50
app/src/main/java/com/navinfo/volvo/util/PhotoLoader.java
Normal file
50
app/src/main/java/com/navinfo/volvo/util/PhotoLoader.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package com.navinfo.volvo.util;
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.request.target.CustomViewTarget;
|
||||||
|
import com.bumptech.glide.request.transition.Transition;
|
||||||
|
|
||||||
|
import indi.liyi.viewer.ImageLoader;
|
||||||
|
|
||||||
|
public class PhotoLoader extends ImageLoader {
|
||||||
|
@Override
|
||||||
|
public void displayImage(final Object src, ImageView imageView, final LoadCallback callback) {
|
||||||
|
Glide.with(imageView.getContext())
|
||||||
|
.load(src)
|
||||||
|
.into(new CustomViewTarget<ImageView, Drawable>(imageView) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResourceLoading(@Nullable Drawable placeholder) {
|
||||||
|
super.onResourceLoading(placeholder);
|
||||||
|
if(callback!=null){
|
||||||
|
callback.onLoadStarted(placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
|
||||||
|
if(callback!=null) {
|
||||||
|
callback.onLoadSucceed(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFailed(@Nullable Drawable errorDrawable) {
|
||||||
|
if(callback!=null) {
|
||||||
|
callback.onLoadFailed(errorDrawable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResourceCleared(@Nullable Drawable placeholder) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -131,7 +131,7 @@ class EasyMediaFile {
|
|||||||
* 选择文件
|
* 选择文件
|
||||||
*/
|
*/
|
||||||
private fun selectFileInternal(intent: Intent, activity: Activity, type: Int) {
|
private fun selectFileInternal(intent: Intent, activity: Activity, type: Int) {
|
||||||
val resolveInfoList = activity.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
|
var resolveInfoList = activity.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
|
||||||
if (resolveInfoList.isEmpty()) {
|
if (resolveInfoList.isEmpty()) {
|
||||||
error?.invoke(IllegalStateException("No Activity found to handle Intent "))
|
error?.invoke(IllegalStateException("No Activity found to handle Intent "))
|
||||||
} else {
|
} else {
|
||||||
|
@ -121,9 +121,10 @@
|
|||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/tv_photo_name"
|
android:id="@+id/tv_photo_name"
|
||||||
android:layout_width="wrap_content"
|
android:textColor="@android:color/holo_blue_dark"
|
||||||
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text=""></com.google.android.material.textview.MaterialTextView>
|
android:layout_weight="1"></com.google.android.material.textview.MaterialTextView>
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="@dimen/default_widget_padding"
|
android:layout_width="@dimen/default_widget_padding"
|
||||||
android:layout_height="wrap_content"></Space>
|
android:layout_height="wrap_content"></Space>
|
||||||
@ -147,7 +148,6 @@
|
|||||||
|
|
||||||
<com.nhaarman.supertooltips.ToolTipRelativeLayout
|
<com.nhaarman.supertooltips.ToolTipRelativeLayout
|
||||||
android:id="@+id/tt_pic"
|
android:id="@+id/tt_pic"
|
||||||
app:layout_constraintTop_toBottomOf="@id/ti_layout_title"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
@ -156,6 +156,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginVertical="@dimen/default_widget_padding"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -180,7 +181,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||||
app:icon="@drawable/ic_baseline_fiber_manual_record_24"
|
app:icon="@drawable/ic_baseline_fiber_manual_record_24"
|
||||||
android:text="录制音频"
|
android:text="长按录音"
|
||||||
android:padding="@dimen/default_widget_padding"></com.google.android.material.button.MaterialButton>
|
android:padding="@dimen/default_widget_padding"></com.google.android.material.button.MaterialButton>
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="@dimen/default_widget_padding"
|
android:layout_width="@dimen/default_widget_padding"
|
||||||
@ -204,8 +205,10 @@
|
|||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/tv_audio_name"
|
android:id="@+id/tv_audio_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@android:color/holo_blue_dark"
|
||||||
|
android:layout_weight="1"
|
||||||
android:text=""></com.google.android.material.textview.MaterialTextView>
|
android:text=""></com.google.android.material.textview.MaterialTextView>
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="@dimen/default_widget_padding"
|
android:layout_width="@dimen/default_widget_padding"
|
||||||
@ -219,16 +222,36 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.imageview.ShapeableImageView
|
<!--增加音频播放按钮-->
|
||||||
android:id="@+id/img_sound_play"
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/ll_audio_play"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:src="@drawable/ic_baseline_volume_up_24"
|
android:layout_gravity="center"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_gravity="center"></com.google.android.material.imageview.ShapeableImageView>
|
android:orientation="horizontal">
|
||||||
|
<me.jagar.chatvoiceplayerlibrary.VoicePlayerView
|
||||||
|
android:id="@+id/voicePlayerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:enableVisualizer="true"
|
||||||
|
app:visualizationPlayedColor="@color/teal_200"
|
||||||
|
app:visualizationNotPlayedColor="@color/teal_700"
|
||||||
|
app:playPauseBackgroundColor="@color/teal_700"
|
||||||
|
app:timingBackgroundColor="@color/purple_200"
|
||||||
|
app:seekBarProgressColor="@color/purple_500"
|
||||||
|
app:showShareButton="false"
|
||||||
|
app:shareCornerRadius="100"
|
||||||
|
app:playPauseCornerRadius="100"
|
||||||
|
app:showTiming="true"
|
||||||
|
app:viewCornerRadius="100"
|
||||||
|
app:viewBackground="@android:color/transparent"
|
||||||
|
app:progressTimeColor="@color/purple_500"
|
||||||
|
app:seekBarThumbColor="@color/teal_200"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<com.nhaarman.supertooltips.ToolTipRelativeLayout
|
<com.nhaarman.supertooltips.ToolTipRelativeLayout
|
||||||
android:id="@+id/tt_audio"
|
android:id="@+id/tt_audio"
|
||||||
app:layout_constraintTop_toBottomOf="@id/ti_layout_title"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@ -283,7 +306,6 @@
|
|||||||
|
|
||||||
<com.nhaarman.supertooltips.ToolTipRelativeLayout
|
<com.nhaarman.supertooltips.ToolTipRelativeLayout
|
||||||
android:id="@+id/tt_send_from"
|
android:id="@+id/tt_send_from"
|
||||||
app:layout_constraintTop_toBottomOf="@id/ti_layout_title"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
@ -379,4 +401,11 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:text="确认提交"></com.google.android.material.button.MaterialButton>
|
android:text="确认提交"></com.google.android.material.button.MaterialButton>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<indi.liyi.viewer.ImageViewer
|
||||||
|
android:id="@+id/imageViewer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
app:ivr_dragMode="agile" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
x
Reference in New Issue
Block a user