优化
This commit is contained in:
parent
8b706266a4
commit
cf5d2c41b6
@ -1,6 +1,7 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JetCodeStyleSettings>
|
||||
<option name="WRAP_ELVIS_EXPRESSIONS" value="2" />
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
|
7
.idea/copyright/profiles_settings.xml
Normal file
7
.idea/copyright/profiles_settings.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings>
|
||||
<LanguageOptions name="Kotlin">
|
||||
<option name="prefixLines" value="false" />
|
||||
</LanguageOptions>
|
||||
</settings>
|
||||
</component>
|
@ -21,18 +21,21 @@
|
||||
android:networkSecurityConfig="@xml/network_config"
|
||||
android:roundIcon="@drawable/app_logo"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Anim_fade"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".page.activity.ApplyContactActivity"
|
||||
android:exported="false" />
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop" />
|
||||
<activity
|
||||
android:name=".page.activity.SearchContactActivity"
|
||||
android:exported="false" />
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop" />
|
||||
<activity
|
||||
android:name=".page.activity.SplashActivity"
|
||||
android:exported="true">
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@ -41,22 +44,36 @@
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".page.activity.LoginActivity"
|
||||
android:exported="false" />
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop" />
|
||||
<activity
|
||||
android:name=".page.activity.ChatActivity"
|
||||
android:exported="false" />
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop" />
|
||||
<activity
|
||||
android:name=".page.activity.MainActivity"
|
||||
android:exported="false"
|
||||
android:launchMode="singleInstance" />
|
||||
android:launchMode="singleTop" />
|
||||
<activity
|
||||
android:name=".page.activity.ManageReplyActivity"
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden" />
|
||||
|
||||
<service
|
||||
android:name=".services.SocketService"
|
||||
android:exported="false" />
|
||||
android:exported="false"
|
||||
android:process=":tenlion_socket" />
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -34,7 +34,9 @@ object ConvertBeanUtils {
|
||||
msgType = type,
|
||||
timestamp = sBean.timestamp,
|
||||
status = sBean.status,
|
||||
customMessageType = ""
|
||||
customMessageType = "",
|
||||
userNickName = "",
|
||||
userAvatar = ""
|
||||
)
|
||||
)
|
||||
} else {
|
||||
@ -62,7 +64,9 @@ object ConvertBeanUtils {
|
||||
msgType = type,
|
||||
timestamp = cBean.timestamp,
|
||||
status = cBean.status,
|
||||
customMessageType = ""
|
||||
customMessageType = "",
|
||||
userNickName = "",
|
||||
userAvatar = ""
|
||||
)
|
||||
}
|
||||
|
||||
@ -78,7 +82,8 @@ object ConvertBeanUtils {
|
||||
status = msgBean.status,
|
||||
timestamp = msgBean.timestamp,
|
||||
msgType = msgBean.msgType,
|
||||
body = msgBean.body
|
||||
body = msgBean.body,
|
||||
userNickName = ""
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package com.tenlionsoft.aimz_k.adapter
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.lxj.xpopup.XPopup
|
||||
import com.tenlionsoft.aimz_k.databinding.ItemContactBinding
|
||||
import com.tenlionsoft.aimz_k.model.ContactListBean
|
||||
import com.tenlionsoft.aimz_k.viewmodel.ContactViewModel
|
||||
@ -29,8 +30,17 @@ class ContactAdapter(datas: List<ContactListBean>, val viewModel: BaseViewModel)
|
||||
holder.binding.root.setOnClickListener {
|
||||
viewModel.itemClickListener?.onItemClick(list[position])
|
||||
}
|
||||
val xPopup = XPopup.Builder(holder.binding.root.context).watchView(holder.binding.root)
|
||||
holder.binding.root.setOnLongClickListener {
|
||||
viewModel.itemLongClickListener?.onItemLongClick(2, list[position])
|
||||
xPopup.asAttachList(
|
||||
arrayOf("删除该联系人"),
|
||||
intArrayOf(com.tenlionsoft.baselib.R.drawable.ic_del),
|
||||
{ p, _ ->
|
||||
viewModel.itemLongClickListener?.onItemLongClick(2, list[position])
|
||||
},
|
||||
0,
|
||||
0
|
||||
).show()
|
||||
true
|
||||
}
|
||||
} else {
|
||||
|
@ -22,7 +22,7 @@ interface MsgCategoryDao {
|
||||
/**
|
||||
* 根据发送人ID获取
|
||||
*/
|
||||
@Query("SELECT * FROM db_category WHERE senderId=:senderId")
|
||||
@Query("SELECT * FROM db_category WHERE senderId=:senderId OR receiverId=:senderId")
|
||||
suspend fun getCategoryBySenderId(senderId: String): MsgCategoryBean?
|
||||
|
||||
/**
|
||||
@ -98,7 +98,7 @@ interface MsgCategoryDao {
|
||||
*/
|
||||
suspend fun updateOrInsert(senderId: String, msgBean: MsgBean) {
|
||||
val bean = getCategoryBySenderId(senderId)
|
||||
if (bean == null) {
|
||||
if (bean==null) {
|
||||
//需要转换成MsgCategoryBean
|
||||
insertMsg(ConvertBeanUtils.convertCategoryBean(msgBean))
|
||||
} else {
|
||||
@ -107,13 +107,19 @@ interface MsgCategoryDao {
|
||||
}
|
||||
|
||||
//更新
|
||||
@Query("UPDATE db_category SET status=:status WHERE senderId=:senderId")
|
||||
@Query("UPDATE db_category SET status=:status WHERE senderId=:senderId OR receiverId=:senderId")
|
||||
suspend fun updateStatus(senderId: String, status: String)
|
||||
|
||||
/**
|
||||
* 更新 消息体 时间戳 状态
|
||||
* @Query("UPDATE db_msg SET status = :status WHERE messageId = :messageId")
|
||||
*/
|
||||
@Query("UPDATE db_category SET status= :status , body=:body , timestamp=:time WHERE senderId=:senderId")
|
||||
@Query("UPDATE db_category SET status= :status , body=:body , timestamp=:time WHERE senderId=:senderId OR receiverId=:senderId")
|
||||
suspend fun updateCategory(senderId: String, status: String?, body: String, time: Long)
|
||||
|
||||
/**
|
||||
* 更新 头像和名称
|
||||
*/
|
||||
@Query("UPDATE db_category SET userNickName=:nickName,avatar=:avatar WHERE receiverId=:userId OR senderId=:userId")
|
||||
suspend fun updateUserInfoById(nickName: String, avatar: String, userId: String)
|
||||
}
|
@ -119,4 +119,10 @@ interface MsgDao {
|
||||
*/
|
||||
@Query("DELETE FROM db_msg")
|
||||
suspend fun delAllMsg()
|
||||
|
||||
/**
|
||||
* 更新 头像和名称
|
||||
*/
|
||||
@Query("UPDATE db_msg SET userNickName=:nickName,avatar=:avatar WHERE receiverId=:toId AND senderId=:fromId")
|
||||
suspend fun updateUserInfoById(nickName: String, avatar: String, fromId: String, toId: String)
|
||||
}
|
@ -20,7 +20,7 @@ interface ReplyDao {
|
||||
* @return
|
||||
*/
|
||||
@Query("SELECT * FROM db_reply")
|
||||
suspend fun getAllReply(): List<ReplyBean>?
|
||||
suspend fun getAllReply(): MutableList<ReplyBean>
|
||||
|
||||
/**
|
||||
* 添加多个
|
||||
|
@ -6,40 +6,6 @@ import androidx.room.PrimaryKey
|
||||
import java.io.Serializable
|
||||
|
||||
|
||||
//{
|
||||
// "body": "{\"msg\":\"\",\"statusType\":\"SUCCESS_SEND\"}",
|
||||
// "customMessageType": "",
|
||||
// "messageId": "1730344667596",
|
||||
// "messageType": "STATUS",
|
||||
// "metadata": "",
|
||||
// "receiver": {
|
||||
// "receiverId": "1",
|
||||
// "receiverType": "SINGLE_USER"
|
||||
//},
|
||||
// "sender": {
|
||||
// "senderId": "system",
|
||||
// "senderType": "SYSTEM"
|
||||
//},
|
||||
// "timestamp": 1730344666322
|
||||
//}
|
||||
|
||||
//发送格式
|
||||
//messageId: `${datetime}`,
|
||||
//timestamp: datetime,
|
||||
//messageType: 'MSG_TEXT',
|
||||
//body: JSON.stringify({content: chat.send.value}),
|
||||
//sender: {
|
||||
// senderId: chat.senderId,
|
||||
// senderType: 'ANONYMOUS'
|
||||
//},
|
||||
//receiver: {
|
||||
// receiverId: chat.receiverId,
|
||||
// receiverType: 'SINGLE_USER'
|
||||
//},
|
||||
//metadata: '',
|
||||
//status: 'PENDING',
|
||||
|
||||
|
||||
@Entity(tableName = "db_msg")
|
||||
data class MsgBean(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ -65,10 +31,13 @@ data class MsgBean(
|
||||
@ColumnInfo(name = "body")
|
||||
var body: String?, //消息体
|
||||
@ColumnInfo(name = "msgType")
|
||||
var msgType: Int?,
|
||||
var msgType: Int?, //标识是发送的消息类型和接收还是发送
|
||||
@ColumnInfo(name = "status")
|
||||
var status: String? //发送状态 11发送中 12发送失败 13发送成功
|
||||
|
||||
var status: String?, //发送状态 11发送中 12发送失败 13发送成功
|
||||
@ColumnInfo(name = "userNickName")
|
||||
var userNickName: String?, //用户昵称
|
||||
@ColumnInfo(name = "avatar")
|
||||
var userAvatar: String? //用户头像
|
||||
/**
|
||||
* 信息类型
|
||||
* <p>
|
||||
|
@ -36,6 +36,8 @@ data class MsgCategoryBean(
|
||||
var id: Long = 0,
|
||||
@ColumnInfo(name = "avatar")
|
||||
var avatar: String,
|
||||
@ColumnInfo(name = "userNickName")
|
||||
var userNickName: String,
|
||||
@ColumnInfo(name = "messageId")
|
||||
var messageId: String?, //消息ID
|
||||
@ColumnInfo(name = "messageType")
|
||||
|
@ -0,0 +1,37 @@
|
||||
package com.tenlionsoft.aimz_k.model
|
||||
|
||||
data class UserInfoBean(
|
||||
val accountType: String,
|
||||
val avatar: String,
|
||||
val creator: String,
|
||||
val deleter: String,
|
||||
val deptIds: String,
|
||||
val deptNames: String,
|
||||
val email: String,
|
||||
val gmtAccountExpired: String,
|
||||
val gmtCreate: String,
|
||||
val gmtLastLogin: String,
|
||||
val gmtLocked: String,
|
||||
val gmtModified: String,
|
||||
val gmtPasswordExpired: String,
|
||||
val isAccountExpired: Int,
|
||||
val isAccountLocked: Int,
|
||||
val isEnable: Int,
|
||||
val isPasswordExpired: Int,
|
||||
val lastLoginIp: String,
|
||||
val lastLoginLat: String,
|
||||
val lastLoginLng: String,
|
||||
val lastLoginType: String,
|
||||
val modifier: String,
|
||||
val nickname: String,
|
||||
val password: String,
|
||||
val phone: String,
|
||||
val posIds: String,
|
||||
val posNames: String,
|
||||
val remarks: String,
|
||||
val roleIds: String,
|
||||
val roleNames: String,
|
||||
val tenantId: String,
|
||||
val userId: String,
|
||||
val username: String
|
||||
)
|
@ -5,10 +5,12 @@ import com.tenlionsoft.aimz_k.model.BaseResponseBean
|
||||
import com.tenlionsoft.aimz_k.model.ContactListBean
|
||||
import com.tenlionsoft.aimz_k.model.FileUploadStateBean
|
||||
import com.tenlionsoft.aimz_k.model.PageListBean
|
||||
import com.tenlionsoft.aimz_k.model.UserInfoBean
|
||||
import com.tenlionsoft.baselib.model.VersionBean
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Headers
|
||||
import retrofit2.http.Multipart
|
||||
@ -19,7 +21,7 @@ import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
|
||||
|
||||
interface UserApi {
|
||||
interface BaseApi {
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
@ -28,16 +30,30 @@ interface UserApi {
|
||||
*/
|
||||
@Headers("Content-Type: application/json", "Accept: application/json", "projectName:usercenter")
|
||||
@POST("api/jwt/login")
|
||||
suspend fun doLogin(@Body user: RequestBody): BaseResponseBean
|
||||
suspend fun doLogin(
|
||||
@Body
|
||||
user: RequestBody
|
||||
): BaseResponseBean
|
||||
|
||||
/**
|
||||
* 根据ID获取用户信息
|
||||
*/
|
||||
@Headers("token:need", "Content-Type: application/json", "Accept: application/json")
|
||||
@GET("/api/user/get/uuid/{uuid}")
|
||||
suspend fun getUserInfo(
|
||||
@Path("uuid")
|
||||
uId: String
|
||||
): UserInfoBean
|
||||
|
||||
/**
|
||||
* 登陆Socket系统
|
||||
* http://192.168.0.26:8888/system/api/anonymous/login
|
||||
*
|
||||
*/
|
||||
@Headers("Content-Type: application/json", "Accept: application/json", "projectName:usercenter")
|
||||
@Headers("Content-Type: application/json", "Accept: application/json")
|
||||
@POST("api/anonymous/login")
|
||||
suspend fun doLoginSocket(@Body user: RequestBody): BaseResponseBean
|
||||
suspend fun doLoginSocket(
|
||||
@Body
|
||||
user: RequestBody
|
||||
): BaseResponseBean
|
||||
|
||||
/**
|
||||
* 获取App版本
|
||||
@ -46,7 +62,10 @@ interface UserApi {
|
||||
*/
|
||||
@Headers("token:need", "Content-Type: application/json", "Accept: application/json")
|
||||
@GET("app/appversion/get-number/{appVersionId}")
|
||||
suspend fun doCheckAppVersion(@Path("appVersionId") appId: String): VersionBean
|
||||
suspend fun doCheckAppVersion(
|
||||
@Path("appVersionId")
|
||||
appId: String
|
||||
): VersionBean
|
||||
|
||||
|
||||
/**
|
||||
@ -60,7 +79,10 @@ interface UserApi {
|
||||
@Headers("token:need")
|
||||
@Multipart
|
||||
@POST("api/file/upload/image")
|
||||
suspend fun doUploadImage(@Part file: MultipartBody.Part): FileUploadStateBean
|
||||
suspend fun doUploadImage(
|
||||
@Part
|
||||
file: MultipartBody.Part
|
||||
): FileUploadStateBean
|
||||
|
||||
|
||||
/**
|
||||
@ -74,7 +96,10 @@ interface UserApi {
|
||||
@Headers("token:need")
|
||||
@Multipart
|
||||
@POST("api/file/upload/video")
|
||||
suspend fun doUploadVideo(@Part file: MultipartBody.Part): FileUploadStateBean
|
||||
suspend fun doUploadVideo(
|
||||
@Part
|
||||
file: MultipartBody.Part
|
||||
): FileUploadStateBean
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
@ -82,7 +107,10 @@ interface UserApi {
|
||||
@Headers("token:need")
|
||||
@Multipart
|
||||
@POST("api/file/upload/file")
|
||||
suspend fun doUploadFile(@Part file: MultipartBody.Part): FileUploadStateBean
|
||||
suspend fun doUploadFile(
|
||||
@Part
|
||||
file: MultipartBody.Part
|
||||
): FileUploadStateBean
|
||||
|
||||
/**
|
||||
* 上传音频
|
||||
@ -90,7 +118,10 @@ interface UserApi {
|
||||
@Headers("token:need")
|
||||
@Multipart
|
||||
@POST("api/file/upload/audio")
|
||||
suspend fun doUploadAudio(@Part file: MultipartBody.Part): FileUploadStateBean
|
||||
suspend fun doUploadAudio(
|
||||
@Part
|
||||
file: MultipartBody.Part
|
||||
): FileUploadStateBean
|
||||
|
||||
/**
|
||||
* 获取我的联系人列表
|
||||
@ -104,7 +135,10 @@ interface UserApi {
|
||||
*/
|
||||
@Headers("Content-Type: application/json", "Accept: application/json", "token:need")
|
||||
@GET("api/user/listpage")
|
||||
suspend fun doSearchContact(@Query("keyword") keyword: String): PageListBean<ContactListBean>
|
||||
suspend fun doSearchContact(
|
||||
@Query("keyword")
|
||||
keyword: String
|
||||
): PageListBean<ContactListBean>
|
||||
|
||||
/**
|
||||
* 新增联系人
|
||||
@ -113,7 +147,10 @@ interface UserApi {
|
||||
*/
|
||||
@Headers("Content-Type: application/json", "Accept: application/json", "token:need")
|
||||
@POST("api/contact/user/apply/save")
|
||||
suspend fun doAddContact(@Body body: RequestBody): BaseResponseBean
|
||||
suspend fun doAddContact(
|
||||
@Body
|
||||
body: RequestBody
|
||||
): BaseResponseBean
|
||||
|
||||
/**
|
||||
* 获取好友申请人列表
|
||||
@ -130,6 +167,20 @@ interface UserApi {
|
||||
@Headers("Content-Type: application/json", "Accept: application/json", "token:need")
|
||||
@PUT("api/contact/user/apply/update-status/self/uuid/{uuid}/status/{status}")
|
||||
suspend fun doPassApplyContact(
|
||||
@Path("uuid") id: String, @Path("status") status: String
|
||||
@Path("uuid")
|
||||
id: String,
|
||||
@Path("status")
|
||||
status: String
|
||||
): BaseResponseBean
|
||||
|
||||
/**
|
||||
* 删除联系人
|
||||
* /
|
||||
*/
|
||||
@Headers("Content-Type: application/json", "Accept: application/json", "token:need")
|
||||
@DELETE("api/contact/user/remove/uuids/{uuids}")
|
||||
suspend fun doDelContact(
|
||||
@Path("uuids")
|
||||
id: String
|
||||
): BaseResponseBean
|
||||
}
|
@ -25,14 +25,20 @@ import com.tenlionsoft.aimz_k.viewmodel.ChatPageViewModel
|
||||
import com.tenlionsoft.baselib.base.BaseActivity
|
||||
import com.tenlionsoft.baselib.contacts.NetConfig
|
||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||
import com.tenlionsoft.baselib.net.DownloadResponseHandler
|
||||
import com.tenlionsoft.baselib.net.FileDownloadUtils
|
||||
import com.tenlionsoft.baselib.utils.DensityUtils
|
||||
import com.tenlionsoft.baselib.utils.FileUtils
|
||||
import com.tenlionsoft.baselib.utils.SpUtils
|
||||
import com.tenlionsoft.baselib.utils.StorageUtils
|
||||
import com.tenlionsoft.baselib.utils.ToastUtils
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||
import com.tenlionsoft.baselib.widget.LoadingDialog
|
||||
import com.tenlionsoft.baselib.widget.SoftKeyBoardListener
|
||||
import com.tenlionsoft.baselib.widget.wheel.WheelView
|
||||
import com.tenlionsoft.medialib.base.SimplePhotoActivity
|
||||
import com.tenlionsoft.medialib.base.SimpleVideoActivity
|
||||
import java.io.File
|
||||
|
||||
|
||||
/**
|
||||
@ -46,6 +52,7 @@ class ChatActivity : BaseActivity(), AdapterItemClickListener<MsgBean> {
|
||||
private var mContentHeight: Int = 0
|
||||
private var mLoading: LoadingDialog? = null;
|
||||
private var bottomHeight = -1
|
||||
val replyList = arrayListOf<String>()
|
||||
override fun bindView() {
|
||||
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_chat);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
||||
@ -54,7 +61,7 @@ class ChatActivity : BaseActivity(), AdapterItemClickListener<MsgBean> {
|
||||
|
||||
val fromId = intent.getStringExtra("fromId") //传递过来的接收人
|
||||
val name = intent.getStringExtra("name")
|
||||
mBinding.tvTitle.text = if (name.isNullOrEmpty()) "临时客户" else name
|
||||
mBinding.tvTitle.text = if (name.isNullOrEmpty()) "临时聊天" else name
|
||||
|
||||
chatPageViewModel = ViewModelProvider(this, object : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
@ -120,7 +127,7 @@ class ChatActivity : BaseActivity(), AdapterItemClickListener<MsgBean> {
|
||||
mLoading = null
|
||||
}
|
||||
}
|
||||
mBinding.wvView.setTextSize(14F, isSp = true)
|
||||
mBinding.wvView.setTextSize(16F, isSp = true)
|
||||
mBinding.wvView.setAutoFitTextSize(true)
|
||||
mBinding.wvView.setOnItemSelectedListener(object : WheelView.OnItemSelectedListener {
|
||||
override fun onItemSelected(wheelView: WheelView, data: Any, position: Int) {
|
||||
@ -165,9 +172,7 @@ class ChatActivity : BaseActivity(), AdapterItemClickListener<MsgBean> {
|
||||
//滚动到底部
|
||||
|
||||
mBinding.rlvChats.postDelayed({
|
||||
layoutManager.scrollToPositionWithOffset(
|
||||
itemCount - 1, 0
|
||||
)
|
||||
layoutManager.scrollToPositionWithOffset(itemCount - 1, 0)
|
||||
}, 50)
|
||||
chatPageViewModel!!.scrollListToBottom.value = false
|
||||
}
|
||||
@ -198,9 +203,7 @@ class ChatActivity : BaseActivity(), AdapterItemClickListener<MsgBean> {
|
||||
val itemCount = layoutManager.itemCount
|
||||
//滚动到底部
|
||||
mBinding.rlvChats.postDelayed({
|
||||
layoutManager.scrollToPositionWithOffset(
|
||||
itemCount - 1, 0
|
||||
)
|
||||
layoutManager.scrollToPositionWithOffset(itemCount - 1, 0)
|
||||
}, 100)
|
||||
}, { _ ->
|
||||
Log.e("ChatActivity", "软键盘: 隐藏")
|
||||
@ -213,9 +216,24 @@ class ChatActivity : BaseActivity(), AdapterItemClickListener<MsgBean> {
|
||||
mBinding.rlBottom.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
|
||||
chatPageViewModel!!._replyList.observe(this) { it ->
|
||||
if (it.isNotEmpty()) {
|
||||
replyList.clear()
|
||||
it.forEach {
|
||||
replyList.add(it.content)
|
||||
}
|
||||
mBinding.wvView.setDataItems(replyList)
|
||||
}
|
||||
}
|
||||
registerLocalReceiver()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
chatPageViewModel!!.getReplyData()
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
||||
private fun registerLocalReceiver() {
|
||||
@ -240,9 +258,7 @@ class ChatActivity : BaseActivity(), AdapterItemClickListener<MsgBean> {
|
||||
val itemCount = layoutManager.itemCount
|
||||
//滚动到底部
|
||||
mBinding.rlvChats.postDelayed({
|
||||
layoutManager.scrollToPositionWithOffset(
|
||||
itemCount - 1, 0
|
||||
)
|
||||
layoutManager.scrollToPositionWithOffset(itemCount - 1, 0)
|
||||
}, 100)
|
||||
}
|
||||
|
||||
@ -286,8 +302,34 @@ class ChatActivity : BaseActivity(), AdapterItemClickListener<MsgBean> {
|
||||
}
|
||||
|
||||
ProjectConfig.MSG_FILE -> {
|
||||
//TODO 下载文集,调用系统打开
|
||||
val gson = Gson()
|
||||
val body = gson.fromJson(data.body, BodyContent::class.java)
|
||||
val fileDataBean = gson.fromJson(body.content, FileDataBean::class.java)
|
||||
val dir: File = StorageUtils.getExternalCacheCustomDir(this)!!
|
||||
chatPageViewModel?.showLoadDialog?.value = true
|
||||
FileDownloadUtils.getInstance().download(this@ChatActivity,
|
||||
NetConfig.MAIN_URL + fileDataBean.fileUrl,
|
||||
dir.absolutePath,
|
||||
fileDataBean.fileName!!,
|
||||
object : DownloadResponseHandler() {
|
||||
override fun onFinish(download_file: File?) {
|
||||
chatPageViewModel?.showLoadDialog?.value = false
|
||||
Log.e("ChatActivity", "onFinish:${download_file}");
|
||||
FileUtils.openFile(this@ChatActivity, download_file)
|
||||
}
|
||||
|
||||
override fun onProgress(currentBytes: Long, totalBytes: Long) {
|
||||
|
||||
}
|
||||
|
||||
override fun onFailure(error_msg: String?) {
|
||||
chatPageViewModel?.showLoadDialog?.value = false
|
||||
ToastUtils.error(
|
||||
error_msg
|
||||
?: "下载失败,请稍后重试"
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ProjectConfig.MSG_VIDEO -> {
|
||||
|
@ -37,12 +37,6 @@ class MainActivity : BaseActivity() {
|
||||
private lateinit var mFragments: ArrayList<Fragment>
|
||||
private var exitTime: Long = 0
|
||||
private var mCurPosition: Int = 0
|
||||
private val mActions = arrayOf(
|
||||
ProjectConfig.ACTION_UPDATE_SUCCESS,
|
||||
ProjectConfig.ACTION_UPDATE_ERROR,
|
||||
ProjectConfig.ACTION_UPDATE_START,
|
||||
ProjectConfig.ACTION_UPDATE_PROGRESS
|
||||
)
|
||||
private lateinit var mLocalReceiver: MainBroadcastReceiver
|
||||
private var mUpdateView: CenterProgressUpdateView? = null
|
||||
private var mApkFile: File? = null
|
||||
@ -52,42 +46,42 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
override fun bindView() {
|
||||
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
|
||||
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
|
||||
mBinding.mainModel = mainPageViewModel
|
||||
initView();
|
||||
initView()
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化页面
|
||||
*/
|
||||
private fun initView() {
|
||||
mFragments = ArrayList();
|
||||
mFragments.add(MsgFragment.newInstance());
|
||||
mFragments.add(ContactFragment.newInstance());
|
||||
mFragments.add(MineFragment.newInstance());
|
||||
mBinding.vpContent.adapter = VpAdapter(this, mFragments);
|
||||
mBinding.bnvTab.itemTextColor = resources.getColorStateList(R.color.col_tabs, theme);
|
||||
mBinding.bnvTab.itemIconSize = DensityUtils.dp2px(this, 24F);
|
||||
mBinding.vpContent.isUserInputEnabled = false;
|
||||
mFragments = ArrayList()
|
||||
mFragments.add(MsgFragment.newInstance())
|
||||
mFragments.add(ContactFragment.newInstance())
|
||||
mFragments.add(MineFragment.newInstance())
|
||||
mBinding.vpContent.adapter = VpAdapter(this, mFragments)
|
||||
mBinding.bnvTab.itemTextColor = resources.getColorStateList(R.color.col_tabs, theme)
|
||||
mBinding.bnvTab.itemIconSize = DensityUtils.dp2px(this, 24F)
|
||||
mBinding.vpContent.isUserInputEnabled = false
|
||||
mBinding.bnvTab.setOnItemSelectedListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.menu_item_msg -> {
|
||||
setStatusBarColor(true);
|
||||
mBinding.vpContent.setCurrentItem(0, false);
|
||||
mCurPosition = 0;
|
||||
return@setOnItemSelectedListener true;
|
||||
setStatusBarColor(true)
|
||||
mBinding.vpContent.setCurrentItem(0, false)
|
||||
mCurPosition = 0
|
||||
return@setOnItemSelectedListener true
|
||||
}//首页
|
||||
R.id.menu_item_center -> {
|
||||
setStatusBarColor(true);
|
||||
mBinding.vpContent.setCurrentItem(1, false);
|
||||
mCurPosition = 1;
|
||||
return@setOnItemSelectedListener true;
|
||||
setStatusBarColor(true)
|
||||
mBinding.vpContent.setCurrentItem(1, false)
|
||||
mCurPosition = 1
|
||||
return@setOnItemSelectedListener true
|
||||
}//统计
|
||||
R.id.menu_item_mine -> {
|
||||
setStatusBarColor(false);
|
||||
mBinding.vpContent.setCurrentItem(2, false);
|
||||
mCurPosition = 2;
|
||||
return@setOnItemSelectedListener true;
|
||||
setStatusBarColor(false)
|
||||
mBinding.vpContent.setCurrentItem(2, false)
|
||||
mCurPosition = 2
|
||||
return@setOnItemSelectedListener true
|
||||
}//我的
|
||||
}
|
||||
false
|
||||
@ -98,9 +92,9 @@ class MainActivity : BaseActivity() {
|
||||
if (mCurPosition == 0) {
|
||||
if ((System.currentTimeMillis() - exitTime) > 2000) {
|
||||
ToastUtils.normal("再按一次退出程序")
|
||||
exitTime = System.currentTimeMillis();
|
||||
exitTime = System.currentTimeMillis()
|
||||
} else {
|
||||
exitApp();
|
||||
exitApp()
|
||||
}
|
||||
} else {
|
||||
mBinding.bnvTab.selectedItemId = R.id.menu_item_msg
|
||||
@ -162,7 +156,7 @@ class MainActivity : BaseActivity() {
|
||||
} else {
|
||||
//申请权限
|
||||
mApkFile = file
|
||||
val packageURI = Uri.parse("package:" + this@MainActivity.getPackageName())
|
||||
val packageURI = Uri.parse("package:" + this@MainActivity.packageName)
|
||||
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI)
|
||||
startActivityForResult(intent, 298)
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.tenlionsoft.aimz_k.page.fragments
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
@ -21,23 +22,22 @@ import com.tenlionsoft.aimz_k.page.activity.SearchContactActivity
|
||||
import com.tenlionsoft.aimz_k.viewmodel.ContactViewModel
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemLongClickListener
|
||||
import com.tenlionsoft.baselib.widget.LoadingDialog
|
||||
import com.tenlionsoft.baselib.widget.StackedImageDecoration
|
||||
|
||||
class ContactFragment : Fragment(), AdapterItemLongClickListener<ContactListBean>,
|
||||
class ContactFragment : Fragment(),
|
||||
AdapterItemLongClickListener<ContactListBean>,
|
||||
AdapterItemClickListener<ContactListBean> {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = ContactFragment()
|
||||
fun newInstance() =
|
||||
ContactFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: ContactViewModel
|
||||
private lateinit var mBind: FragmentContactBinding
|
||||
private lateinit var mActivity: MainActivity
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
}
|
||||
private var mLoading: LoadingDialog? = null
|
||||
|
||||
private val launcher =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
@ -62,12 +62,27 @@ class ContactFragment : Fragment(), AdapterItemLongClickListener<ContactListBean
|
||||
viewModel.itemLongClickListener = this
|
||||
mBind.llTitle.llLoad.visibility = View.GONE
|
||||
mBind.llTitle.llSearchLayout.setOnClickListener {
|
||||
launcher.launch(Intent(mActivity, SearchContactActivity::class.java))
|
||||
launcher.launch(
|
||||
Intent(
|
||||
mActivity, SearchContactActivity::class.java
|
||||
)
|
||||
)
|
||||
}
|
||||
mBind.llNewContact.setOnClickListener {
|
||||
//判断是否存在好友申请
|
||||
if (viewModel.isHasApply.value!!) {
|
||||
launcher.launch(Intent(mActivity, ApplyContactActivity::class.java))
|
||||
launcher.launch(
|
||||
Intent(
|
||||
mActivity, ApplyContactActivity::class.java
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
viewModel.isHasApply.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
mBind.llNewContact.visibility = View.VISIBLE
|
||||
} else {
|
||||
mBind.llNewContact.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
mBind.srlContent.setEnableLoadMore(false)
|
||||
@ -79,6 +94,22 @@ class ContactFragment : Fragment(), AdapterItemLongClickListener<ContactListBean
|
||||
mBind.srlContent.finishRefresh()
|
||||
}
|
||||
}
|
||||
viewModel.showLoadDialog.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
//显示loading
|
||||
mLoading =
|
||||
LoadingDialog.Builder(mActivity)
|
||||
.setCancelOutside(false)
|
||||
.setCancelable(false)
|
||||
.setMessage("删除中...")
|
||||
.create()
|
||||
mLoading!!.show()
|
||||
} else {
|
||||
//隐藏loading
|
||||
mLoading?.dismiss()
|
||||
mLoading = null
|
||||
}
|
||||
}
|
||||
mBind.rlvContent.addItemDecoration(StackedImageDecoration())
|
||||
|
||||
return mBind.root
|
||||
@ -97,14 +128,20 @@ class ContactFragment : Fragment(), AdapterItemLongClickListener<ContactListBean
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemLongClick(type: Int, d: ContactListBean) {
|
||||
|
||||
override fun onItemLongClick(
|
||||
type: Int, d: ContactListBean
|
||||
) {
|
||||
AlertDialog.Builder(mActivity).setTitle("警告")
|
||||
.setMessage("确定要删除该联系人吗?这样会删除与该联系人的所有聊天内容!")
|
||||
.setPositiveButton("确定") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
viewModel.delContact(d)
|
||||
}.setNegativeButton("取消") { dialog, _ -> dialog.dismiss() }.create().show()
|
||||
}
|
||||
|
||||
override fun onItemClick(data: ContactListBean) {
|
||||
mActivity.startActivity(
|
||||
Intent(mActivity, ChatActivity::class.java)
|
||||
.putExtra("fromId", data.contactUserId)
|
||||
Intent(mActivity, ChatActivity::class.java).putExtra("fromId", data.contactUserId)
|
||||
.putExtra("name", data.userIdNickname)
|
||||
)
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.atwa.filepicker.core.FilePicker
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
@ -19,45 +20,44 @@ import com.tenlionsoft.aimz_k.page.activity.MainActivity
|
||||
import com.tenlionsoft.aimz_k.page.activity.ManageReplyActivity
|
||||
import com.tenlionsoft.aimz_k.viewmodel.MineViewModel
|
||||
import com.tenlionsoft.baselib.utils.SpUtils
|
||||
import com.tenlionsoft.baselib.widget.LoadingDialog
|
||||
|
||||
class MineFragment : Fragment() {
|
||||
private lateinit var mBind: FragmentMineBinding
|
||||
private lateinit var mActivity: MainActivity
|
||||
|
||||
companion object {
|
||||
fun newInstance() = MineFragment()
|
||||
}
|
||||
|
||||
private val filePicker = FilePicker.getInstance(this)
|
||||
private var mLoading: LoadingDialog? = null
|
||||
private lateinit var viewModel: MineViewModel
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
mBind = DataBindingUtil.inflate(
|
||||
layoutInflater,
|
||||
R.layout.fragment_mine,
|
||||
container,
|
||||
false
|
||||
)
|
||||
mBind = DataBindingUtil.inflate(layoutInflater, R.layout.fragment_mine, container, false)
|
||||
viewModel = ViewModelProvider(this, object : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return MineViewModel() as T
|
||||
return MineViewModel(mActivity) as T
|
||||
}
|
||||
})[MineViewModel::class.java]
|
||||
mBind.model = viewModel
|
||||
mBind.lifecycleOwner = this
|
||||
|
||||
mBind.ivUserIcon.setOnClickListener {
|
||||
filePicker.pickImage { meta ->
|
||||
if (meta != null) {
|
||||
viewModel.doUploadImg(meta)
|
||||
}
|
||||
}
|
||||
}
|
||||
initView()
|
||||
return mBind.root
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
mBind.tvName.text = SpUtils.getNickName()
|
||||
mBind.tvAccount.text = SpUtils.getUserName()
|
||||
val requestOptions = RequestOptions()
|
||||
.error(R.drawable.ic_user_default)
|
||||
mBind.tvAccount.text = SpUtils.getPhone()
|
||||
val requestOptions = RequestOptions().error(R.drawable.ic_user_default)
|
||||
.placeholder(R.drawable.ic_user_default)
|
||||
.skipMemoryCache(false)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
@ -70,7 +70,30 @@ class MineFragment : Fragment() {
|
||||
startActivity(Intent(mActivity, ManageReplyActivity::class.java))
|
||||
}
|
||||
mBind.llExit.setOnClickListener {
|
||||
mActivity.exitApp()
|
||||
mActivity.reStartApp()
|
||||
}
|
||||
viewModel.showLoadDialog.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
//显示loading
|
||||
mLoading = LoadingDialog.Builder(mActivity)
|
||||
.setCancelOutside(false)
|
||||
.setCancelable(false)
|
||||
.setMessage("上传中...")
|
||||
.create()
|
||||
mLoading!!.show()
|
||||
} else {
|
||||
//隐藏loading
|
||||
mLoading?.dismiss()
|
||||
mLoading = null
|
||||
}
|
||||
}
|
||||
viewModel.isUploadIconSuccess.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
Glide.with(mActivity)
|
||||
.load(SpUtils.getAvatar())
|
||||
.apply(requestOptions)
|
||||
.into(mBind.ivUserIcon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,4 +104,9 @@ class MineFragment : Fragment() {
|
||||
mActivity = context
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
fun newInstance() = MineFragment()
|
||||
}
|
||||
}
|
@ -14,11 +14,13 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import com.tenlionsoft.aimz_k.R
|
||||
import com.tenlionsoft.aimz_k.databinding.FragmentMsgBinding
|
||||
import com.tenlionsoft.aimz_k.model.MsgCategoryBean
|
||||
import com.tenlionsoft.aimz_k.model.MsgTypeStateEnum
|
||||
import com.tenlionsoft.aimz_k.page.activity.ChatActivity
|
||||
import com.tenlionsoft.aimz_k.page.activity.MainActivity
|
||||
import com.tenlionsoft.aimz_k.services.SocketService
|
||||
import com.tenlionsoft.aimz_k.viewmodel.MsgViewModel
|
||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||
import com.tenlionsoft.baselib.utils.AppUtils
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemLongClickListener
|
||||
import com.tenlionsoft.baselib.widget.LoadingDialog
|
||||
@ -37,17 +39,13 @@ class MsgFragment : Fragment(), AdapterItemClickListener<MsgCategoryBean>,
|
||||
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View {
|
||||
mMsgBinding = DataBindingUtil.inflate(
|
||||
layoutInflater,
|
||||
R.layout.fragment_msg,
|
||||
container,
|
||||
false
|
||||
)
|
||||
layoutInflater, R.layout.fragment_msg, container, false
|
||||
)
|
||||
mMsgBinding.llSearchLayout.llSearchLayout.setOnClickListener {
|
||||
startActivity(Intent(this@MsgFragment.context, ChatActivity::class.java))
|
||||
mActivity?.startActivity(Intent(mActivity, ChatActivity::class.java))
|
||||
}
|
||||
viewModel = ViewModelProvider(this, object : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
@ -87,9 +85,11 @@ class MsgFragment : Fragment(), AdapterItemClickListener<MsgCategoryBean>,
|
||||
viewModel.showLoadDialog.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
//显示loading
|
||||
mLoading = LoadingDialog.Builder(mActivity as Activity).setCancelOutside(false)
|
||||
mLoading = LoadingDialog.Builder(mActivity as Activity)
|
||||
.setCancelOutside(false)
|
||||
.setCancelable(false)
|
||||
.setMessage("删除中...").create()
|
||||
.setMessage("删除中...")
|
||||
.create()
|
||||
mLoading!!.show()
|
||||
} else {
|
||||
//隐藏loading
|
||||
@ -111,7 +111,13 @@ class MsgFragment : Fragment(), AdapterItemClickListener<MsgCategoryBean>,
|
||||
|
||||
//开启service
|
||||
private fun toStartService() {
|
||||
mActivity?.startService(Intent(mActivity!!, SocketService::class.java))
|
||||
//判断是否允许
|
||||
|
||||
val isRunning =
|
||||
AppUtils.isRunningService(mActivity!!, mActivity!!.packageName + ":tenlion_socket")
|
||||
if (!isRunning) {
|
||||
mActivity?.startService(Intent(mActivity!!, SocketService::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@ -123,12 +129,17 @@ class MsgFragment : Fragment(), AdapterItemClickListener<MsgCategoryBean>,
|
||||
* 条目点击
|
||||
*/
|
||||
override fun onItemClick(data: MsgCategoryBean) {
|
||||
startActivity(
|
||||
Intent(mActivity, ChatActivity::class.java).putExtra(
|
||||
"fromId",
|
||||
data.senderId
|
||||
)
|
||||
)
|
||||
val intent = Intent(mActivity, ChatActivity::class.java)
|
||||
when (data.msgType) {
|
||||
MsgTypeStateEnum.MSG_TO_OTHER_TXT, MsgTypeStateEnum.MSG_TO_OTHER_IMG, MsgTypeStateEnum.MSG_TO_OTHER_FILE, MsgTypeStateEnum.MSG_TO_OTHER_VOICE, MsgTypeStateEnum.MSG_TO_OTHER_MOVIE -> {
|
||||
intent.putExtra("fromId", data.receiverId)
|
||||
}
|
||||
|
||||
MsgTypeStateEnum.MSG_FROM_OTHER_IMG, MsgTypeStateEnum.MSG_FROM_OTHER_TXT, MsgTypeStateEnum.MSG_FROM_OTHER_VOICE, MsgTypeStateEnum.MSG_FROM_OTHER_MOVIE, MsgTypeStateEnum.MSG_FROM_OTHER_FILE -> {
|
||||
intent.putExtra("fromId", data.senderId)
|
||||
}
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
//监听socket连接状态
|
||||
|
@ -67,6 +67,8 @@ class SocketService : Service(), WsManager.MsgCallBack {
|
||||
val intentFilter = IntentFilter()
|
||||
mLocalReceiver = LocalReceiver()
|
||||
intentFilter.addAction(ProjectConfig.A_S_MSG_SEND)//发送消息
|
||||
intentFilter.addAction(ProjectConfig.A_S_LOGOUT) //断开socket
|
||||
intentFilter.addAction(ProjectConfig.A_S_RE_LOGIN)//重新连接socket
|
||||
registerReceiver(mLocalReceiver, intentFilter)
|
||||
}
|
||||
|
||||
@ -111,11 +113,21 @@ class SocketService : Service(), WsManager.MsgCallBack {
|
||||
val isConnect = mWsManager?.isNetworkConnected(context)
|
||||
if (true == isConnect) {
|
||||
when (intent?.action) {
|
||||
//发送消息
|
||||
ProjectConfig.A_S_MSG_SEND -> {
|
||||
val msgConvertBean = intent.getSerializableExtra("msgBean")
|
||||
val msg = gson.toJson(msgConvertBean)
|
||||
mWsManager?.sendMessage(msg)
|
||||
}//发送消息
|
||||
}
|
||||
//断开连接
|
||||
ProjectConfig.A_S_LOGOUT -> {
|
||||
stopSocket()
|
||||
}
|
||||
//重新连接
|
||||
ProjectConfig.A_S_RE_LOGIN -> {
|
||||
stopSocket()
|
||||
startSocket()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ToastUtils.error("请检查网络")
|
||||
|
@ -5,7 +5,7 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.tenlionsoft.aimz_k.adapter.ApplyContactAdapter
|
||||
import com.tenlionsoft.aimz_k.model.ApplyContactBean
|
||||
import com.tenlionsoft.aimz_k.net.UserApi
|
||||
import com.tenlionsoft.aimz_k.net.BaseApi
|
||||
import com.tenlionsoft.baselib.base.BaseViewModel
|
||||
import com.tenlionsoft.baselib.net.ExParse
|
||||
import com.tenlionsoft.baselib.net.RetrofitClient
|
||||
@ -16,7 +16,7 @@ class ApplyContactViewModel(private val context: Context) : BaseViewModel() {
|
||||
val _applyList = MutableLiveData<List<ApplyContactBean>>()
|
||||
val adapter = ApplyContactAdapter(_applyList.value ?: emptyList(), this)
|
||||
val retrofit = RetrofitClient.getInstance(context)
|
||||
val userApi = retrofit.create(UserApi::class.java)
|
||||
val userApi = retrofit.create(BaseApi::class.java)
|
||||
|
||||
init {
|
||||
doGetApplyList()
|
||||
|
@ -15,9 +15,9 @@ import com.atwa.filepicker.result.VideoMeta
|
||||
import com.google.gson.Gson
|
||||
import com.tenlionsoft.aimz_k.ConvertBeanUtils
|
||||
import com.tenlionsoft.aimz_k.adapter.ChatMsgAdapter
|
||||
import com.tenlionsoft.aimz_k.dao.DbManager
|
||||
import com.tenlionsoft.aimz_k.model.BodyContent
|
||||
import com.tenlionsoft.aimz_k.model.CoverSealedBean
|
||||
import com.tenlionsoft.aimz_k.dao.DbManager
|
||||
import com.tenlionsoft.aimz_k.model.FileDataBean
|
||||
import com.tenlionsoft.aimz_k.model.MsgBean
|
||||
import com.tenlionsoft.aimz_k.model.MsgConvertBean
|
||||
@ -25,9 +25,11 @@ import com.tenlionsoft.aimz_k.model.PickerType
|
||||
import com.tenlionsoft.aimz_k.model.Receiver
|
||||
import com.tenlionsoft.aimz_k.model.ReplyBean
|
||||
import com.tenlionsoft.aimz_k.model.Sender
|
||||
import com.tenlionsoft.aimz_k.net.UserApi
|
||||
import com.tenlionsoft.aimz_k.model.UserInfoBean
|
||||
import com.tenlionsoft.aimz_k.net.BaseApi
|
||||
import com.tenlionsoft.baselib.base.BaseViewModel
|
||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||
import com.tenlionsoft.baselib.contacts.toFileBody
|
||||
import com.tenlionsoft.baselib.net.ExParse
|
||||
import com.tenlionsoft.baselib.net.RetrofitClient
|
||||
import com.tenlionsoft.baselib.utils.SpUtils
|
||||
@ -36,15 +38,9 @@ import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.asRequestBody
|
||||
|
||||
class ChatPageViewModel(
|
||||
private val fromId: String,
|
||||
private val toId: String,
|
||||
private var context: Context
|
||||
private val fromId: String, private val toId: String, private var context: Context
|
||||
) : BaseViewModel() {
|
||||
val txtMsg = MutableLiveData<String>("")
|
||||
val showSendBtn = MutableLiveData(false)//显示/隐藏发送按钮
|
||||
@ -55,12 +51,16 @@ class ChatPageViewModel(
|
||||
val scrollListToBottom = MutableLiveData<Boolean>(false)
|
||||
private val _msgList = MutableLiveData<List<MsgBean>>()
|
||||
private val retrofitClient = RetrofitClient.getInstance(context)
|
||||
private val netApi = retrofitClient.create(UserApi::class.java)
|
||||
var adapter: ChatMsgAdapter = ChatMsgAdapter(_msgList.value ?: emptyList(), this)
|
||||
private val netApi = retrofitClient.create(BaseApi::class.java)
|
||||
var adapter: ChatMsgAdapter = ChatMsgAdapter(
|
||||
_msgList.value
|
||||
?: emptyList(), this
|
||||
)
|
||||
var onItemClickListener: AdapterItemClickListener<MsgBean>? = null
|
||||
private val mGson: Gson = Gson()
|
||||
private var msgHandlerList: ArrayList<MsgConvertBean> = arrayListOf()
|
||||
private val _replyList = MutableLiveData<List<ReplyBean>?>()
|
||||
val _replyList = MutableLiveData<MutableList<ReplyBean>>()
|
||||
|
||||
private val handler = object : Handler(Looper.getMainLooper()) {
|
||||
override fun handleMessage(msg: Message) {
|
||||
super.handleMessage(msg)
|
||||
@ -92,10 +92,10 @@ class ChatPageViewModel(
|
||||
val list = getList()
|
||||
val rList = getReplyList()
|
||||
Log.e("ChatPageViewModel", "Init:${list} ")
|
||||
if (rList != null) {
|
||||
if (rList.isNotEmpty()) {
|
||||
_replyList.value = rList
|
||||
} else {
|
||||
_replyList.value = emptyList()
|
||||
_replyList.value = arrayListOf()
|
||||
}
|
||||
_msgList.value = list
|
||||
adapter.setData(list)
|
||||
@ -103,7 +103,7 @@ class ChatPageViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getReplyList(): List<ReplyBean>? {
|
||||
private suspend fun getReplyList(): MutableList<ReplyBean> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val rDao = DbManager.db.replayDao()
|
||||
return@withContext rDao.getAllReply()
|
||||
@ -112,6 +112,7 @@ class ChatPageViewModel(
|
||||
|
||||
//获取列表
|
||||
private suspend fun getList(): List<MsgBean> {
|
||||
Log.e("ChatPageViewModel", "getList:${fromId}\n${toId}");
|
||||
return withContext(Dispatchers.IO) {
|
||||
val msgDao = DbManager.db.msgDao()
|
||||
return@withContext msgDao.getMsgByFromOrToPage(fromId, toId)
|
||||
@ -205,15 +206,7 @@ class ChatPageViewModel(
|
||||
|
||||
private suspend fun doUploadVideo(meta: VideoMeta) {
|
||||
try {
|
||||
val requestFile: RequestBody =
|
||||
meta.file!!.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||
val body: MultipartBody.Part =
|
||||
MultipartBody.Part.createFormData(
|
||||
"video",
|
||||
meta.file!!.getName(),
|
||||
requestFile
|
||||
)
|
||||
|
||||
val body = meta.file!!.toFileBody("video")
|
||||
val bean = retrofitClient.makeApiCall {
|
||||
netApi.doUploadVideo(body)
|
||||
}
|
||||
@ -230,14 +223,7 @@ class ChatPageViewModel(
|
||||
|
||||
private suspend fun doUploadFile(meta: FileMeta) {
|
||||
try {
|
||||
val requestFile: RequestBody =
|
||||
meta.file!!.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||
val body: MultipartBody.Part =
|
||||
MultipartBody.Part.createFormData(
|
||||
"file",
|
||||
meta.file!!.getName(),
|
||||
requestFile
|
||||
)
|
||||
val body = meta.file!!.toFileBody("file")
|
||||
val bean = retrofitClient.makeApiCall {
|
||||
netApi.doUploadFile(body)
|
||||
}
|
||||
@ -257,17 +243,9 @@ class ChatPageViewModel(
|
||||
try {
|
||||
for (item in list) {
|
||||
if (item != null) {
|
||||
val requestFile: RequestBody =
|
||||
item.file!!.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||
val body: MultipartBody.Part =
|
||||
MultipartBody.Part.createFormData(
|
||||
"image",
|
||||
item.file!!.getName(),
|
||||
requestFile
|
||||
)
|
||||
|
||||
val toFileBody = item.file!!.toFileBody("image")
|
||||
val bean = retrofitClient.makeApiCall {
|
||||
netApi.doUploadImage(body)
|
||||
netApi.doUploadImage(toFileBody)
|
||||
}
|
||||
Log.e("ChatPageViewModel", "doUploadImgs: $bean")
|
||||
if (bean.code == 200) {
|
||||
@ -348,7 +326,7 @@ class ChatPageViewModel(
|
||||
val dao = DbManager.db.msgDao()
|
||||
val cDao = DbManager.db.categoryDao()
|
||||
val msgBean = ConvertBeanUtils.convertBeanToMsgBean(b)
|
||||
cDao.updateCategory(b.receiver.receiverId!!, b.status, b.body, b.timestamp)
|
||||
cDao.updateOrInsert(b.receiver.receiverId!!, msgBean)
|
||||
dao.insertMsg(msgBean)
|
||||
return@withContext msgBean
|
||||
}
|
||||
@ -370,10 +348,11 @@ class ChatPageViewModel(
|
||||
is CoverSealedBean.StateBean -> {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
//更新状态
|
||||
val dao = DbManager.db.msgDao()
|
||||
val cDao = DbManager.db.categoryDao()
|
||||
val statusType =
|
||||
mGson.fromJson(bean.data.body, BodyContent::class.java).statusType!!
|
||||
mGson.fromJson(bean.data.body, BodyContent::class.java).statusType!!
|
||||
dao.updateStatus(bean.data.messageId, statusType)
|
||||
cDao.updateStatus(bean.data.sender.senderId!!, statusType)
|
||||
}
|
||||
@ -416,72 +395,87 @@ class ChatPageViewModel(
|
||||
val bodyBean = BodyContent(content = txtMsg.value, null, null)
|
||||
val body = mGson.toJson(bodyBean)
|
||||
return MsgConvertBean(
|
||||
body = body,
|
||||
customMessageType = "",
|
||||
messageId = TimeUtils.getNowDateMillis().toString(),
|
||||
messageType = type,
|
||||
metadata = "",
|
||||
timestamp = TimeUtils.getNowDateMillis(),
|
||||
sender = Sender(
|
||||
senderId = SpUtils.getId(),
|
||||
senderType = ""
|
||||
),
|
||||
receiver = Receiver(
|
||||
receiverId = fromId,
|
||||
receiverType = "SINGLE_USER"
|
||||
),
|
||||
status = ProjectConfig.MSG_SEND_ING,
|
||||
body = body,
|
||||
customMessageType = "",
|
||||
messageId = TimeUtils.getNowDateMillis()
|
||||
.toString(),
|
||||
messageType = type,
|
||||
metadata = "",
|
||||
timestamp = TimeUtils.getNowDateMillis(),
|
||||
sender = Sender(senderId = SpUtils.getId(), senderType = ""),
|
||||
receiver = Receiver(receiverId = fromId, receiverType = "SINGLE_USER"),
|
||||
status = ProjectConfig.MSG_SEND_ING,
|
||||
)
|
||||
}
|
||||
|
||||
var userInfo: UserInfoBean? = null
|
||||
|
||||
//获取用户头像和名称
|
||||
private fun doGetUserInfo() {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val userInfoBean = retrofitClient.makeApiCall {
|
||||
netApi.getUserInfo(fromId)
|
||||
}
|
||||
userInfo = userInfoBean
|
||||
withContext(Dispatchers.IO) {
|
||||
//更新数据
|
||||
val cDao = DbManager.db.categoryDao()
|
||||
val mDao = DbManager.db.msgDao()
|
||||
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//构建 图片/视频/文件发送实体
|
||||
private fun buildSendMediaBean(type: String, fileBean: FileDataBean): MsgConvertBean {
|
||||
val bodyBean = BodyContent(content = mGson.toJson(fileBean), null, null)
|
||||
val body = mGson.toJson(bodyBean)
|
||||
return MsgConvertBean(
|
||||
body = body,
|
||||
customMessageType = "",
|
||||
messageId = TimeUtils.getNowDateMillis().toString(),
|
||||
messageType = type,
|
||||
metadata = "",
|
||||
timestamp = TimeUtils.getNowDateMillis(),
|
||||
sender = Sender(
|
||||
senderId = SpUtils.getId(),
|
||||
senderType = ""
|
||||
),
|
||||
receiver = Receiver(
|
||||
receiverId = fromId,
|
||||
receiverType = "SINGLE_USER"
|
||||
),
|
||||
status = ProjectConfig.MSG_SEND_ING,
|
||||
body = body,
|
||||
customMessageType = "",
|
||||
messageId = TimeUtils.getNowDateMillis()
|
||||
.toString(),
|
||||
messageType = type,
|
||||
metadata = "",
|
||||
timestamp = TimeUtils.getNowDateMillis(),
|
||||
sender = Sender(senderId = SpUtils.getId(), senderType = ""),
|
||||
receiver = Receiver(receiverId = fromId, receiverType = "SINGLE_USER"),
|
||||
status = ProjectConfig.MSG_SEND_ING,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
//构建状态信息
|
||||
private fun buildStatusBean(messageId: String): MsgConvertBean {
|
||||
val bodyBean = BodyContent(content = null, msg = "", statusType = "SUCCESS_RECEIVED")
|
||||
val body = mGson.toJson(bodyBean)
|
||||
return MsgConvertBean(
|
||||
body = body,
|
||||
customMessageType = "",
|
||||
messageId = messageId,
|
||||
messageType = ProjectConfig.MSG_STATUS,
|
||||
metadata = "",
|
||||
timestamp = TimeUtils.getNowDateMillis(),
|
||||
sender = Sender(
|
||||
senderId = SpUtils.getId(),
|
||||
senderType = ""
|
||||
),
|
||||
receiver = Receiver(
|
||||
receiverId = fromId,
|
||||
receiverType = "SINGLE_USER"
|
||||
),
|
||||
status = "",
|
||||
body = body,
|
||||
customMessageType = "",
|
||||
messageId = messageId,
|
||||
messageType = ProjectConfig.MSG_STATUS,
|
||||
metadata = "",
|
||||
timestamp = TimeUtils.getNowDateMillis(),
|
||||
sender = Sender(senderId = SpUtils.getId(), senderType = ""),
|
||||
receiver = Receiver(receiverId = fromId, receiverType = "SINGLE_USER"),
|
||||
status = "",
|
||||
)
|
||||
}
|
||||
|
||||
//获取回复短语
|
||||
fun getReplyData() {
|
||||
viewModelScope.launch {
|
||||
val list = getReplyList()
|
||||
if (list.isNotEmpty()) {
|
||||
_replyList.value = list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -5,15 +5,20 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.tenlionsoft.aimz_k.adapter.ApplyContactUserIconAdapter
|
||||
import com.tenlionsoft.aimz_k.adapter.ContactAdapter
|
||||
import com.tenlionsoft.aimz_k.dao.DbManager
|
||||
import com.tenlionsoft.aimz_k.model.ApplyContactBean
|
||||
import com.tenlionsoft.aimz_k.model.ContactListBean
|
||||
import com.tenlionsoft.aimz_k.net.UserApi
|
||||
import com.tenlionsoft.aimz_k.net.BaseApi
|
||||
import com.tenlionsoft.baselib.base.BaseViewModel
|
||||
import com.tenlionsoft.baselib.net.ExParse
|
||||
import com.tenlionsoft.baselib.net.RetrofitClient
|
||||
import com.tenlionsoft.baselib.utils.SpUtils
|
||||
import com.tenlionsoft.baselib.utils.ToastUtils
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemClickListener
|
||||
import com.tenlionsoft.baselib.widget.AdapterItemLongClickListener
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ContactViewModel(private val context: Context) : BaseViewModel() {
|
||||
private val _contactList = MutableLiveData<List<ContactListBean>?>()
|
||||
@ -25,7 +30,7 @@ class ContactViewModel(private val context: Context) : BaseViewModel() {
|
||||
val isHasApply = MutableLiveData<Boolean>(false)
|
||||
val isRefreshing = MutableLiveData<Boolean>(false)
|
||||
private val retrofit = RetrofitClient.getInstance(context)
|
||||
private val userApi = retrofit.create(UserApi::class.java)
|
||||
private val userApi = retrofit.create(BaseApi::class.java)
|
||||
|
||||
init {
|
||||
getContactList()
|
||||
@ -89,5 +94,35 @@ class ContactViewModel(private val context: Context) : BaseViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
//删除联系人
|
||||
fun delContact(d: ContactListBean) {
|
||||
viewModelScope.launch {
|
||||
showLoadDialog.value = true
|
||||
try {
|
||||
val responseBean = retrofit.makeApiCall {
|
||||
userApi.doDelContact(d.contactUserId)
|
||||
}
|
||||
withContext(Dispatchers.IO) {
|
||||
val cDao = DbManager.db.categoryDao()
|
||||
val mDao = DbManager.db.msgDao()
|
||||
cDao.delChatBySenderId(d.userId)
|
||||
mDao.delChatHistory(SpUtils.getId(), d.userId)
|
||||
}
|
||||
if (responseBean.code == 200) {
|
||||
ToastUtils.success("删除成功")
|
||||
doRefresh()
|
||||
} else {
|
||||
ToastUtils.error(responseBean.msg ?: "删除失败,请稍后重试")
|
||||
}
|
||||
showLoadDialog.value = false
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
ExParse.parse(e)
|
||||
showLoadDialog.value = false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -6,7 +6,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.google.gson.Gson
|
||||
import com.tenlionsoft.aimz_k.model.AppTokenUser
|
||||
import com.tenlionsoft.aimz_k.model.LoginUser
|
||||
import com.tenlionsoft.aimz_k.net.UserApi
|
||||
import com.tenlionsoft.aimz_k.net.BaseApi
|
||||
import com.tenlionsoft.baselib.base.App
|
||||
import com.tenlionsoft.baselib.base.BaseViewModel
|
||||
import com.tenlionsoft.baselib.net.ExParse
|
||||
@ -25,7 +25,7 @@ class LoginPageViewModel : BaseViewModel() {
|
||||
val isLoginSuccess = MutableLiveData<Boolean>()
|
||||
private val gson = Gson()
|
||||
private val retrofitClient = RetrofitClient.getInstance(App.context)
|
||||
private val userApi = retrofitClient.create(UserApi::class.java)
|
||||
private val userApi = retrofitClient.create(BaseApi::class.java)
|
||||
|
||||
|
||||
fun onUserNameChange(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
|
@ -3,7 +3,7 @@ package com.tenlionsoft.aimz_k.viewmodel
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.tenlionsoft.aimz_k.net.UserApi
|
||||
import com.tenlionsoft.aimz_k.net.BaseApi
|
||||
import com.tenlionsoft.baselib.base.BaseViewModel
|
||||
import com.tenlionsoft.baselib.contacts.ProjectConfig
|
||||
import com.tenlionsoft.baselib.net.ExParse
|
||||
@ -24,7 +24,7 @@ class MainPageViewModel : BaseViewModel() {
|
||||
private suspend fun getAppVersion(context: Context) {
|
||||
try {
|
||||
val appVersion = RetrofitClient.getInstance(context)
|
||||
.create(UserApi::class.java)
|
||||
.create(BaseApi::class.java)
|
||||
.doCheckAppVersion(ProjectConfig.APP_VERSION_ID)
|
||||
if (appVersion.versioncode.isNotEmpty()) {
|
||||
val isNeedUpdate = AppUtils.checkcode(appVersion.versioncode)
|
||||
|
@ -16,8 +16,8 @@ import kotlinx.coroutines.withContext
|
||||
class ManageReplyViewModel : BaseViewModel(), AdapterItemLongClickListener<ReplyBean> {
|
||||
|
||||
val txtMsg = MutableLiveData("")
|
||||
val _replyList = MutableLiveData<List<ReplyBean>?>()
|
||||
var adapter: ReplyAdapter = ReplyAdapter(_replyList.value ?: emptyList(), this)
|
||||
val _replyList = MutableLiveData<MutableList<ReplyBean>>()
|
||||
var adapter: ReplyAdapter = ReplyAdapter(_replyList.value ?: arrayListOf(), this)
|
||||
var onItemLongClickListener: AdapterItemLongClickListener<ReplyBean> = this
|
||||
val curBean = MutableLiveData<ReplyBean?>()
|
||||
|
||||
@ -27,15 +27,15 @@ class ManageReplyViewModel : BaseViewModel(), AdapterItemLongClickListener<Reply
|
||||
|
||||
private fun getList() {
|
||||
viewModelScope.launch {
|
||||
val list: List<ReplyBean>? = withContext(Dispatchers.IO) {
|
||||
val list: MutableList<ReplyBean> = withContext(Dispatchers.IO) {
|
||||
val rDao = DbManager.db.replayDao()
|
||||
val list = rDao.getAllReply()
|
||||
list
|
||||
}
|
||||
if (!list.isNullOrEmpty()) {
|
||||
if (list.isNotEmpty()) {
|
||||
_replyList.value = list
|
||||
} else {
|
||||
_replyList.value = emptyList()
|
||||
_replyList.value = arrayListOf()
|
||||
}
|
||||
Log.e("ManageReplyViewModel", "init:${adapter} ${Thread.currentThread().name}");
|
||||
adapter.setData(_replyList.value!!)
|
||||
|
@ -1,7 +1,45 @@
|
||||
package com.tenlionsoft.aimz_k.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.atwa.filepicker.result.ImageMeta
|
||||
import com.tenlionsoft.aimz_k.net.BaseApi
|
||||
import com.tenlionsoft.baselib.base.BaseViewModel
|
||||
import com.tenlionsoft.baselib.contacts.toFileBody
|
||||
import com.tenlionsoft.baselib.net.ExParse
|
||||
import com.tenlionsoft.baselib.net.RetrofitClient
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MineViewModel : ViewModel() {
|
||||
// TODO: Implement the ViewModel
|
||||
class MineViewModel(val context: Context) : BaseViewModel() {
|
||||
private val retrofitClient = RetrofitClient.getInstance(context)
|
||||
private val baseApi = retrofitClient.create(BaseApi::class.java)
|
||||
val isUploadIconSuccess = MutableLiveData<Boolean>()
|
||||
|
||||
|
||||
fun doUploadImg(meta: ImageMeta) {
|
||||
viewModelScope.launch {
|
||||
showLoadDialog.value = true
|
||||
try {
|
||||
val responseBean = retrofitClient.makeApiCall {
|
||||
val body = meta.file!!.toFileBody("image")
|
||||
baseApi.doUploadImage(body)
|
||||
}
|
||||
if (responseBean.code == 200) {
|
||||
//TODO 更新头像上传成功
|
||||
//设置成功后刷新页面
|
||||
isUploadIconSuccess.value = true
|
||||
showLoadDialog.value = false
|
||||
} else {
|
||||
isUploadIconSuccess.value = false
|
||||
showLoadDialog.value = false
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
isUploadIconSuccess.value = false
|
||||
ExParse.parse(e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.tenlionsoft.aimz_k.adapter.ContactAdapter
|
||||
import com.tenlionsoft.aimz_k.model.AddContactBean
|
||||
import com.tenlionsoft.aimz_k.model.ContactListBean
|
||||
import com.tenlionsoft.aimz_k.net.UserApi
|
||||
import com.tenlionsoft.aimz_k.net.BaseApi
|
||||
import com.tenlionsoft.baselib.base.BaseViewModel
|
||||
import com.tenlionsoft.baselib.contacts.toBody
|
||||
import com.tenlionsoft.baselib.model.ViewState
|
||||
@ -23,7 +23,7 @@ class SearchContactViewModel(val context: Context) : BaseViewModel() {
|
||||
val adapter = ContactAdapter(_contactList.value ?: emptyList(), this)
|
||||
val showApplyContentDialog = MutableLiveData<Boolean>(false)
|
||||
private val retrofitClient = RetrofitClient.getInstance(context)
|
||||
private val userApi = retrofitClient.create(UserApi::class.java)
|
||||
private val userApi = retrofitClient.create(BaseApi::class.java)
|
||||
fun onTxtChange(s: CharSequence, start: Int, before: Int, end: Int) {
|
||||
txtMsg.value = s.toString()
|
||||
}
|
||||
|
@ -54,16 +54,10 @@ object BindingUtils {
|
||||
if (url.isNullOrEmpty()) {
|
||||
imageView.setImageResource(R.drawable.app_logo_small)
|
||||
} else {
|
||||
val requestOptions = RequestOptions()
|
||||
.error(R.drawable.app_logo_small)
|
||||
.placeholder(R.drawable.app_logo_small)
|
||||
.skipMemoryCache(false)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerInside()
|
||||
Glide.with(imageView.context)
|
||||
.load(url)
|
||||
.apply(requestOptions)
|
||||
.into(imageView)
|
||||
val requestOptions = RequestOptions().error(R.drawable.app_logo_small)
|
||||
.placeholder(R.drawable.app_logo_small).skipMemoryCache(false)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerInside()
|
||||
Glide.with(imageView.context).load(url).apply(requestOptions).into(imageView)
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,16 +68,10 @@ object BindingUtils {
|
||||
if (url.isNullOrEmpty()) {
|
||||
imageView.setImageResource(R.drawable.ic_user_default)
|
||||
} else {
|
||||
val requestOptions = RequestOptions()
|
||||
.error(R.drawable.ic_psd)
|
||||
.placeholder(R.drawable.ic_psd)
|
||||
.skipMemoryCache(false)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.circleCrop()
|
||||
Glide.with(imageView.context)
|
||||
.load(url)
|
||||
.apply(requestOptions)
|
||||
.into(imageView)
|
||||
val requestOptions = RequestOptions().error(R.drawable.ic_user_default)
|
||||
.placeholder(R.drawable.ic_user_default).skipMemoryCache(false)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE).circleCrop()
|
||||
Glide.with(imageView.context).load(url).apply(requestOptions).into(imageView)
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,8 +114,7 @@ object BindingUtils {
|
||||
if (!fileDataBean.fileName.isNullOrEmpty()) {
|
||||
iv.visibility = View.VISIBLE
|
||||
val suffix = fileDataBean.fileName!!.substring(
|
||||
fileDataBean.fileName!!.lastIndexOf("."),
|
||||
fileDataBean.fileName!!.length
|
||||
fileDataBean.fileName!!.lastIndexOf("."), fileDataBean.fileName!!.length
|
||||
)
|
||||
Log.e("BindingUtils", "jsonConvertFileIcon: $suffix")
|
||||
var id = R.drawable.ic_audio
|
||||
@ -172,20 +159,17 @@ object BindingUtils {
|
||||
if (str.isNullOrEmpty()) {
|
||||
iv.setImageResource(com.tenlionsoft.baselib.R.drawable.ic_img_load_err)
|
||||
} else {
|
||||
val options: RequestOptions = RequestOptions()
|
||||
.placeholder(com.tenlionsoft.baselib.R.drawable.ic_loading) // 正在加载中的图片
|
||||
.error(com.tenlionsoft.baselib.R.drawable.ic_img_load_err) // 加载失败的图片
|
||||
val options: RequestOptions =
|
||||
RequestOptions().placeholder(com.tenlionsoft.baselib.R.drawable.ic_loading) // 正在加载中的图片
|
||||
.error(com.tenlionsoft.baselib.R.drawable.ic_img_load_err) // 加载失败的图片
|
||||
val gson = Gson()
|
||||
val bodyContent = gson.fromJson<BodyContent>(str, BodyContent::class.java)
|
||||
|
||||
val fileBean = gson.fromJson(bodyContent.content, FileDataBean::class.java)
|
||||
Glide.with(iv.context)
|
||||
.load(NetConfig.MAIN_URL + fileBean.fileUrl) // 图片地址
|
||||
.apply(options)
|
||||
.into(object : CustomTarget<Drawable?>() {
|
||||
Glide.with(iv.context).load(NetConfig.MAIN_URL + fileBean.fileUrl) // 图片地址
|
||||
.apply(options).into(object : CustomTarget<Drawable?>() {
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
transition: Transition<in Drawable?>?
|
||||
resource: Drawable, transition: Transition<in Drawable?>?
|
||||
) {
|
||||
val imageSize: ImageSize? =
|
||||
ImageUtils.getImageSize((resource as BitmapDrawable).bitmap)
|
||||
@ -194,9 +178,7 @@ object BindingUtils {
|
||||
imageLP?.width = imageSize.getWidth()
|
||||
imageLP?.height = imageSize.getHeight()
|
||||
iv.setLayoutParams(imageLP)
|
||||
Glide.with(iv.context)
|
||||
.load(resource)
|
||||
.apply(options) // 参数
|
||||
Glide.with(iv.context).load(resource).apply(options) // 参数
|
||||
.into(iv)
|
||||
}
|
||||
}
|
||||
@ -217,16 +199,11 @@ object BindingUtils {
|
||||
val body = gson.fromJson(str, BodyContent::class.java)
|
||||
val fileData = gson.fromJson(body.content, FileDataBean::class.java)
|
||||
|
||||
val requestOptions = RequestOptions()
|
||||
.error(R.drawable.app_logo_small)
|
||||
.placeholder(R.drawable.app_logo_small)
|
||||
.skipMemoryCache(false)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||
.centerInside()
|
||||
Glide.with(view.context)
|
||||
.load(NetConfig.MAIN_URL + fileData.fileUrl)
|
||||
.apply(requestOptions)
|
||||
.into(view)
|
||||
val requestOptions = RequestOptions().error(R.drawable.app_logo_small)
|
||||
.placeholder(R.drawable.app_logo_small).skipMemoryCache(false)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE).centerInside()
|
||||
Glide.with(view.context).load(NetConfig.MAIN_URL + fileData.fileUrl)
|
||||
.apply(requestOptions).into(view)
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,7 +213,7 @@ object BindingUtils {
|
||||
if (long == null) {
|
||||
tv.text = ""
|
||||
} else {
|
||||
tv.text = TimeUtils.millis2HMStr(long)
|
||||
tv.text = TimeUtils.getFriendlyTimeSpanByNow(long)
|
||||
}
|
||||
}
|
||||
|
||||
|
7
app/src/main/res/anim/activity_close_enter.xml
Normal file
7
app/src/main/res/anim/activity_close_enter.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="-100%"
|
||||
android:toXDelta="0"/>
|
||||
</set>
|
8
app/src/main/res/anim/activity_close_exit.xml
Normal file
8
app/src/main/res/anim/activity_close_exit.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:fromXDelta="0"
|
||||
android:toXDelta="100%"
|
||||
android:duration="300">
|
||||
</translate>
|
||||
</set>
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:fromXDelta="100%p"
|
||||
android:fromXDelta="100%"
|
||||
android:toXDelta="0"
|
||||
android:duration="500" />
|
||||
android:duration="300"/>
|
||||
</set>
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="0"
|
||||
android:toXDelta="-100%p"
|
||||
android:duration="500" />
|
||||
android:toXDelta="-100%" />
|
||||
</set>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="200"
|
||||
android:fromAlpha="0.0"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:toAlpha="1.0" />
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="200"
|
||||
android:fromAlpha="1.0"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:toAlpha="0.0" />
|
BIN
app/src/main/res/drawable-xhdpi/ic_title_icon.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_title_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 3.7 KiB |
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
@ -124,9 +125,9 @@
|
||||
android:minLines="1"
|
||||
android:onTextChanged="@{viewModel::onTxtChange}"
|
||||
android:padding="10dp"
|
||||
tools:text="测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试"
|
||||
android:text="@{viewModel.txtMsg}"
|
||||
android:textSize="14sp" />
|
||||
android:textSize="14sp"
|
||||
tools:text="测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_send"
|
||||
@ -172,7 +173,9 @@
|
||||
android:id="@+id/wv_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"
|
||||
android:visibility="@{viewModel.showReplyLayout? View.VISIBLE:View.GONE}" />
|
||||
android:visibility="@{viewModel.showReplyLayout? View.VISIBLE:View.GONE}"
|
||||
app:wv_normalItemTextColor="@color/gray_d1"
|
||||
app:wv_selectedItemTextColor="@color/black" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_choose"
|
||||
|
@ -19,24 +19,15 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="25dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="50dp"
|
||||
android:layout_marginRight="25dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="你好,"
|
||||
android:textColor="#ff282828"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_hint"
|
||||
android:textColor="#ff282828"
|
||||
android:textSize="20sp" />
|
||||
android:src="@drawable/ic_title_icon" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="25dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingTop="15dp"
|
||||
android:paddingRight="25dp"
|
||||
android:paddingBottom="15dp">
|
||||
@ -73,16 +73,13 @@
|
||||
<com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||
android:id="@+id/srl_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="15dp">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rlv_content"
|
||||
setLinearLayoutAdapter="@{model.adapter}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
tools:listitem="@layout/item_contact" />
|
||||
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
android:id="@+id/iv_user_icon"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:src="@drawable/ic_load_error" />
|
||||
android:src="@drawable/ic_user_default" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -40,9 +40,10 @@
|
||||
android:id="@+id/tv_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="名称"
|
||||
tools:text="名称"
|
||||
android:textColor="@color/txt_black"
|
||||
android:textSize="16sp" />
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_account"
|
||||
@ -50,7 +51,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:drawableRight="@drawable/ic_arrow_d7_right"
|
||||
android:text="账号"
|
||||
tools:text="账号"
|
||||
android:textColor="#ff7d7d7d"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
@ -80,8 +81,8 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:text="设置"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:text="回复短语"
|
||||
android:textColor="@color/txt_black"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
@ -110,7 +111,7 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:text="退出登录"
|
||||
android:textColor="@color/txt_black"
|
||||
android:textSize="14sp" />
|
||||
|
@ -31,25 +31,25 @@
|
||||
android:layout_margin="10dp">
|
||||
|
||||
<ImageView
|
||||
imageUrl="@{item.avatar}"
|
||||
imageUserIcon="@{item.avatar}"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:scaleType="fitXY"
|
||||
tools:src="@drawable/app_logo_small" />
|
||||
tools:src="@drawable/ic_user_default" />
|
||||
<!-- android:visibility="@{item.read?View.VISIBLE:View.GONE}"-->
|
||||
<ImageView
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:src="@drawable/shp_circle_red" />
|
||||
android:src="@drawable/shp_circle_red"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
@ -95,7 +95,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#CACACA"
|
||||
android:textSize="12sp"
|
||||
android:textSize="10sp"
|
||||
tools:text="16:00" />
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -23,14 +23,15 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:orientation="horizontal">
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:padding="10dp">
|
||||
|
||||
<ImageView
|
||||
imageUserIcon="@{bean.userIdAvatar}"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_margin="10dp"
|
||||
android:scaleType="fitXY"
|
||||
tools:src="@drawable/ic_user_default" />
|
||||
|
||||
@ -42,8 +43,7 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingRight="15dp">
|
||||
|
||||
@ -52,7 +52,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="10dp"
|
||||
android:paddingRight="10dp">
|
||||
|
||||
<TextView
|
||||
@ -63,12 +62,13 @@
|
||||
android:text="@{bean.userIdNickname}"
|
||||
android:textColor="#1D1D1D"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="名字" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text='@{bean.userIdPhone ==null ? "联系方式:未录入":@string/contact_item_phone(bean.userIdPhone)}'
|
||||
@ -100,6 +100,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="3dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:background="#E6E6E6"
|
||||
android:visibility="@{pos< size?View.VISIBLE:View.GONE}" />
|
||||
|
@ -1,16 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.Aimz_k" parent="Theme.AppCompat.Light.NoActionBar" />
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
|
||||
<style name="Anim_fade" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="android:windowAnimationStyle">@style/fade</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="android:windowAnimationStyle">@style/WindowAnimationStyle</item>
|
||||
</style>
|
||||
|
||||
<style name="fade" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="android:activityOpenEnterAnimation">@anim/fade_in</item>
|
||||
<item name="android:activityOpenExitAnimation">@anim/fade_out</item>
|
||||
<item name="android:activityCloseEnterAnimation">@anim/fade_in</item>
|
||||
<item name="android:activityCloseExitAnimation">@anim/fade_out</item>
|
||||
<style name="WindowAnimationStyle" parent="@android:style/Animation.Activity">
|
||||
<item name="android:activityOpenEnterAnimation">@anim/activity_open_enter</item>
|
||||
<item name="android:activityOpenExitAnimation">@anim/activity_open_exit</item>
|
||||
<item name="android:activityCloseEnterAnimation">@anim/activity_close_enter</item>
|
||||
<item name="android:activityCloseExitAnimation">@anim/activity_close_exit</item>
|
||||
|
||||
<item name="android:taskOpenEnterAnimation">@anim/activity_open_enter</item>
|
||||
<item name="android:taskOpenExitAnimation">@anim/activity_open_exit</item>
|
||||
<item name="android:taskCloseEnterAnimation">@anim/activity_close_enter</item>
|
||||
<item name="android:taskCloseExitAnimation">@anim/activity_close_exit</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
44
app/src/main/res/xml/provider_paths.xml
Executable file
44
app/src/main/res/xml/provider_paths.xml
Executable file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<external-path
|
||||
name="external_storage_root"
|
||||
path="." />
|
||||
<files-path
|
||||
name="files"
|
||||
path="." />
|
||||
<cache-path
|
||||
name="cache"
|
||||
path="." />
|
||||
<!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/DCIM/camerademo目录-->
|
||||
<external-path
|
||||
name="mq_DCIM"
|
||||
path="DCIM/camerademo" />
|
||||
|
||||
<!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/Pictures/camerademo目录-->
|
||||
<external-path
|
||||
name="mq_Pictures"
|
||||
path="Pictures/camerademo" />
|
||||
|
||||
<!--代表app 私有的存储区域 Context.getFilesDir()目录下的images目录 /data/user/0/com.hm.camerademo/files/images-->
|
||||
<files-path
|
||||
name="mq_private_files"
|
||||
path="images" />
|
||||
|
||||
<!--代表app 私有的存储区域 Context.getCacheDir()目录下的images目录 /data/user/0/com.hm.camerademo/cache/images-->
|
||||
<cache-path
|
||||
name="mq_private_cache"
|
||||
path="images" />
|
||||
|
||||
<!--代表app 外部存储区域根目录下的文件 Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)目录下的Pictures目录-->
|
||||
<external-files-path
|
||||
name="mq_external_files"
|
||||
path="Pictures" />
|
||||
<!--代表app 外部存储区域根目录下的文件 Context.getExternalCacheDir目录下的images目录-->
|
||||
<external-cache-path
|
||||
name="mq_external_cache"
|
||||
path="path" />
|
||||
|
||||
<root-path
|
||||
name="mq_external_cache"
|
||||
path="" />
|
||||
</paths>
|
@ -1,29 +1,30 @@
|
||||
package com.tenlionsoft.baselib.base
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import android.view.MotionEvent
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.tenlionsoft.baselib.R
|
||||
import com.tenlionsoft.baselib.utils.SpUtils
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
|
||||
abstract class BaseActivity : DataBindingActivity() {
|
||||
//点击空白隐藏软键盘
|
||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||
Log.e("BaseActivity", "onTouchEvent: ")
|
||||
val v = currentFocus
|
||||
if (v != null && v is EditText) {
|
||||
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.hideSoftInputFromWindow(v.windowToken, 0)
|
||||
}
|
||||
}
|
||||
return super.onTouchEvent(event)
|
||||
|
||||
fun reStartApp(){
|
||||
SpUtils.putToken("")
|
||||
SpUtils.putId("")
|
||||
SpUtils.putPassword("")
|
||||
SpUtils.putUserName("")
|
||||
// val broadcast = Intent()
|
||||
// broadcast.setAction(PathConfig.ACTION_PUSH_STOP_SOCKET)
|
||||
// sendBroadcast(broadcast)
|
||||
val intent = packageManager.getLaunchIntentForPackage(packageName)
|
||||
intent!!.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
fun exitApp() {
|
||||
|
@ -2,8 +2,11 @@ package com.tenlionsoft.baselib.contacts
|
||||
|
||||
import com.google.gson.Gson
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.asRequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.io.File
|
||||
|
||||
object NetConfig {
|
||||
const val BASE_URL = "http://192.168.0.26:8888/"
|
||||
@ -20,4 +23,9 @@ fun <T> T.toBody(): RequestBody {
|
||||
val gson = Gson()
|
||||
val str = gson.toJson(this)
|
||||
return str.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
|
||||
}
|
||||
|
||||
fun File.toFileBody(paramsStr: String): MultipartBody.Part {
|
||||
val requestFile: RequestBody = this.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||
return MultipartBody.Part.createFormData(paramsStr, this.getName(), requestFile)
|
||||
}
|
@ -40,5 +40,7 @@ object ProjectConfig {
|
||||
const val A_S_DISCONNECT: String = "com.tenlion.soft.aimz_k.socket.disconnect"//连接断开
|
||||
const val A_S_MSG_RECEIVER: String = "com.tenlion.soft.aimz_k.socket.receiver" //接收到信息
|
||||
const val A_S_MSG_SEND: String = "com.tenlion.soft.aimz_k.socket.send"//发送信息
|
||||
const val A_S_LOGOUT: String = "com.tenlion.soft.aimz_k.socket.logout"//断开socket
|
||||
const val A_S_RE_LOGIN: String = "com.tenlion.soft.aimz_k.socket.re_login"//重新连接socket
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.tenlionsoft.baselib.model
|
||||
|
||||
import androidx.annotation.IntDef
|
||||
import com.tenlionsoft.baselib.model.TimeConstants.DAY
|
||||
import com.tenlionsoft.baselib.model.TimeConstants.HOUR
|
||||
import com.tenlionsoft.baselib.model.TimeConstants.MIN
|
||||
import com.tenlionsoft.baselib.model.TimeConstants.MSEC
|
||||
import com.tenlionsoft.baselib.model.TimeConstants.SEC
|
||||
|
||||
object TimeConstants {
|
||||
|
||||
|
||||
const val MSEC: Int = 1
|
||||
const val SEC: Int = 1000
|
||||
const val MIN: Int = 60000
|
||||
const val HOUR: Int = 3600000
|
||||
const val DAY: Int = 86400000
|
||||
}
|
||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.VALUE_PARAMETER)
|
||||
@IntDef(MSEC, SEC, MIN, HOUR, DAY)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class Unit
|
@ -11,42 +11,42 @@ import retrofit2.converter.gson.GsonConverterFactory
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
open class RetrofitClient {
|
||||
private var mCtx: Context? = null;
|
||||
private val TIMEOUT: Long = 5;//超时时间
|
||||
private lateinit var mRetrofit: Retrofit;
|
||||
private var mCtx: Context? = null
|
||||
private val TIMEOUT: Long = 5//超时时间
|
||||
private lateinit var mRetrofit: Retrofit
|
||||
|
||||
private constructor(ctx: Context) {
|
||||
mCtx = ctx;
|
||||
initManager();
|
||||
mCtx = ctx
|
||||
initManager()
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Retrofit
|
||||
*/
|
||||
private fun initManager() {
|
||||
val client = getHttpClient();
|
||||
val client = getHttpClient()
|
||||
mRetrofit = Retrofit.Builder()
|
||||
.baseUrl(NetConfig.MAIN_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
|
||||
.client(client)
|
||||
.build();
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
private fun getHttpClient(): OkHttpClient {
|
||||
val builder: OkHttpClient.Builder = OkHttpClient.Builder();
|
||||
val builder: OkHttpClient.Builder = OkHttpClient.Builder()
|
||||
// setLocalProxy();
|
||||
// 设置超时
|
||||
builder.connectTimeout(TIMEOUT, TimeUnit.MINUTES);
|
||||
builder.readTimeout(TIMEOUT, TimeUnit.MINUTES);
|
||||
builder.writeTimeout(TIMEOUT, TimeUnit.MINUTES);
|
||||
builder.connectTimeout(TIMEOUT, TimeUnit.MINUTES)
|
||||
builder.readTimeout(TIMEOUT, TimeUnit.MINUTES)
|
||||
builder.writeTimeout(TIMEOUT, TimeUnit.MINUTES)
|
||||
//封装公共参数
|
||||
// builder.addInterceptor(new AreaInterceptor());
|
||||
//builder.addInterceptor(new CommInterceptor());
|
||||
//多BaseUrl连接器
|
||||
builder.addInterceptor(BaseUrlInterceptor());
|
||||
return builder.build();
|
||||
builder.addInterceptor(BaseUrlInterceptor())
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
suspend fun <T> makeApiCall(apiCall: suspend () -> T): T {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.tenlionsoft.baselib.utils
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
@ -23,7 +24,8 @@ class AppUtils {
|
||||
try {
|
||||
val pm = App.context.packageManager
|
||||
val pi = pm.getPackageInfo(pkgName, 0)
|
||||
return pi?.versionName ?: ""
|
||||
return pi?.versionName
|
||||
?: ""
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace();
|
||||
return ""
|
||||
@ -34,15 +36,38 @@ class AppUtils {
|
||||
return getAppVersionCode(App.context.packageName)
|
||||
}
|
||||
|
||||
|
||||
fun isRunningService(ctx: Context, className: String): Boolean {
|
||||
var isRunning = false
|
||||
val activityManager = ctx
|
||||
.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||
val servicesList = activityManager
|
||||
.getRunningServices(Int.MAX_VALUE)
|
||||
val l: Iterator<ActivityManager.RunningServiceInfo> = servicesList.iterator()
|
||||
while (l.hasNext()) {
|
||||
val si = l.next()
|
||||
if (className == si.service.className) {
|
||||
isRunning = true
|
||||
}
|
||||
|
||||
if (className == si.process) {
|
||||
isRunning = true
|
||||
}
|
||||
}
|
||||
return isRunning
|
||||
}
|
||||
|
||||
private fun getAppVersionCode(pkgName: String?): Long {
|
||||
if (pkgName.isNullOrEmpty()) return -1
|
||||
try {
|
||||
val pm = App.context.packageManager
|
||||
val pi = pm.getPackageInfo(pkgName, 0);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
return pi?.longVersionCode ?: -1
|
||||
return pi?.longVersionCode
|
||||
?: -1
|
||||
} else {
|
||||
return (pi?.versionCode ?: -1).toLong()
|
||||
return (pi?.versionCode
|
||||
?: -1).toLong()
|
||||
}
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
e.printStackTrace()
|
||||
@ -59,7 +84,8 @@ class AppUtils {
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
val newFile = file.createNewFile()
|
||||
uuid = UUID.randomUUID().toString()
|
||||
uuid = UUID.randomUUID()
|
||||
.toString()
|
||||
FileIOUtils.writeFileFromString(file, uuid)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
|
119
baselib/src/main/java/com/tenlionsoft/baselib/utils/FileUtils.kt
Normal file
119
baselib/src/main/java/com/tenlionsoft/baselib/utils/FileUtils.kt
Normal file
@ -0,0 +1,119 @@
|
||||
package com.tenlionsoft.baselib.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.content.FileProvider
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
|
||||
object FileUtils {
|
||||
private val MIME_MapTable: Array<Array<String>> = arrayOf( //{后缀名, MIME类型}
|
||||
arrayOf(".3gp", "video/3gpp"),
|
||||
arrayOf(".apk", "application/vnd.android.package-archive"),
|
||||
arrayOf(".asf", "video/x-ms-asf"),
|
||||
arrayOf(".avi", "video/x-msvideo"),
|
||||
arrayOf(".bin", "application/octet-stream"),
|
||||
arrayOf(".bmp", "image/bmp"),
|
||||
arrayOf(".c", "text/plain"),
|
||||
arrayOf(".class", "application/octet-stream"),
|
||||
arrayOf(".conf", "text/plain"),
|
||||
arrayOf(".cpp", "text/plain"),
|
||||
arrayOf(".doc", "application/msword"),
|
||||
arrayOf(".exe", "application/octet-stream"),
|
||||
arrayOf(".gif", "image/gif"),
|
||||
arrayOf(".gtar", "application/x-gtar"),
|
||||
arrayOf(".gz", "application/x-gzip"),
|
||||
arrayOf(".h", "text/plain"),
|
||||
arrayOf(".htm", "text/html"),
|
||||
arrayOf(".html", "text/html"),
|
||||
arrayOf(".jar", "application/java-archive"),
|
||||
arrayOf(".java", "text/plain"),
|
||||
arrayOf(".jpeg", "image/jpeg"),
|
||||
arrayOf(".jpg", "image/jpeg"),
|
||||
arrayOf(".js", "application/x-javascript"),
|
||||
arrayOf(".log", "text/plain"),
|
||||
arrayOf(".m3u", "audio/x-mpegurl"),
|
||||
arrayOf(".m4a", "audio/mp4a-latm"),
|
||||
arrayOf(".m4b", "audio/mp4a-latm"),
|
||||
arrayOf(".m4p", "audio/mp4a-latm"),
|
||||
arrayOf(".m4u", "video/vnd.mpegurl"),
|
||||
arrayOf(".m4v", "video/x-m4v"),
|
||||
arrayOf(".mov", "video/quicktime"),
|
||||
arrayOf(".mp2", "audio/x-mpeg"),
|
||||
arrayOf(".mp3", "audio/x-mpeg"),
|
||||
arrayOf(".mp4", "video/mp4"),
|
||||
arrayOf(".mpc", "application/vnd.mpohun.certificate"),
|
||||
arrayOf(".mpe", "video/mpeg"),
|
||||
arrayOf(".mpeg", "video/mpeg"),
|
||||
arrayOf(".mpg", "video/mpeg"),
|
||||
arrayOf(".mpg4", "video/mp4"),
|
||||
arrayOf(".mpga", "audio/mpeg"),
|
||||
arrayOf(".msg", "application/vnd.ms-outlook"),
|
||||
arrayOf(".ogg", "audio/ogg"),
|
||||
arrayOf(".pdf", "application/pdf"),
|
||||
arrayOf(".png", "image/png"),
|
||||
arrayOf(".pps", "application/vnd.ms-powerpoint"),
|
||||
arrayOf(".ppt", "application/vnd.ms-powerpoint"),
|
||||
arrayOf(".prop", "text/plain"),
|
||||
arrayOf(".rar", "application/x-rar-compressed"),
|
||||
arrayOf(".rc", "text/plain"),
|
||||
arrayOf(".rmvb", "audio/x-pn-realaudio"),
|
||||
arrayOf(".rtf", "application/rtf"),
|
||||
arrayOf(".sh", "text/plain"),
|
||||
arrayOf(".tar", "application/x-tar"),
|
||||
arrayOf(".tgz", "application/x-compressed"),
|
||||
arrayOf(".txt", "text/plain"),
|
||||
arrayOf(".wav", "audio/x-wav"),
|
||||
arrayOf(".wma", "audio/x-ms-wma"),
|
||||
arrayOf(".wmv", "audio/x-ms-wmv"),
|
||||
arrayOf(".wps", "application/vnd.ms-works"), //{".xml", "text/xml"},
|
||||
arrayOf(".xml", "text/plain"),
|
||||
arrayOf(".z", "application/x-compress"),
|
||||
arrayOf(".zip", "application/zip"),
|
||||
arrayOf("", "*/*")
|
||||
)
|
||||
|
||||
fun getFileProviderName(context: Context): String {
|
||||
return context.packageName + ".provider"
|
||||
}
|
||||
|
||||
fun openFile(context: Context, fileName: String?) {
|
||||
val intent = Intent()
|
||||
val file = File(fileName)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) //设置标记
|
||||
intent.setAction(Intent.ACTION_VIEW) //动作,查看
|
||||
val uri =
|
||||
FileProvider.getUriForFile(context, getFileProviderName(context), file)
|
||||
intent.setDataAndType(uri, getMIMEType(file)) //设置类型
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
fun openFile(context: Context, file: File?) {
|
||||
if (file == null) return
|
||||
val intent = Intent()
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) //设置标记
|
||||
intent.setAction(Intent.ACTION_VIEW) //动作,查看
|
||||
val uri =
|
||||
FileProvider.getUriForFile(context, getFileProviderName(context), file)
|
||||
intent.setDataAndType(uri, getMIMEType(file)) //设置类型
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
private fun getMIMEType(file: File): String {
|
||||
var type = "*/*"
|
||||
val fName = file.name
|
||||
//获取后缀名前的分隔符"."在fName中的位置。
|
||||
val dotIndex = fName.lastIndexOf(".")
|
||||
if (dotIndex < 0) return type
|
||||
/* 获取文件的后缀名 */
|
||||
val fileType = fName.substring(dotIndex).lowercase(Locale.getDefault())
|
||||
if (fileType == null || "" == fileType) return type
|
||||
//在MIME和文件类型的匹配表中找到对应的MIME类型。
|
||||
for (i in MIME_MapTable.indices) {
|
||||
if (fileType == MIME_MapTable[i][0]) type = MIME_MapTable[i][1]
|
||||
}
|
||||
return type
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -28,7 +28,7 @@ class StorageUtils {
|
||||
Log.w(
|
||||
"StorageUtils",
|
||||
"Can't define system cache directory! The app should be re-installed."
|
||||
)
|
||||
)
|
||||
}
|
||||
return appCacheDir
|
||||
}
|
||||
@ -43,7 +43,7 @@ class StorageUtils {
|
||||
Log.w(
|
||||
"StorageUtils",
|
||||
"Can't define system cache directory! The app should be re-installed."
|
||||
)
|
||||
)
|
||||
}
|
||||
return appCacheDir
|
||||
}
|
||||
@ -52,6 +52,19 @@ class StorageUtils {
|
||||
* 在cache下新增自定义缓存路径
|
||||
* apk下载路径为:SDCard/Android/data/com.winfo.update/cache/update_file/
|
||||
*/
|
||||
fun getExternalCacheCustomDir(context: Context): File? {
|
||||
val appCacheDir = File(context.externalCacheDir, "download_cache")
|
||||
return if (!appCacheDir.exists()) {
|
||||
if (appCacheDir.mkdirs()) {
|
||||
appCacheDir
|
||||
} else {
|
||||
context.externalCacheDir
|
||||
}
|
||||
} else {
|
||||
appCacheDir
|
||||
}
|
||||
}
|
||||
|
||||
fun getExternalCacheCustomDirectory(context: Context): File? {
|
||||
//在SDCard/Android/data/com.winfo.update/cache/update_file创建文件夹
|
||||
val appCacheDir = File(context.externalCacheDir, "update")
|
||||
|
@ -1,7 +1,10 @@
|
||||
package com.tenlionsoft.baselib.utils
|
||||
|
||||
import com.tenlionsoft.baselib.model.TimeConstants
|
||||
import java.text.DateFormat
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
@ -41,5 +44,89 @@ object TimeUtils {
|
||||
return format.format(Date(millis))
|
||||
}
|
||||
|
||||
fun getFriendlyTimeSpanByNow(millis: Long): String {
|
||||
val now = System.currentTimeMillis()
|
||||
val span = now - millis
|
||||
if (span < 0) return String.format("%tc", millis)
|
||||
if (span < 1000) {
|
||||
return "刚刚"
|
||||
} else if (span < TimeConstants.MIN) {
|
||||
return java.lang.String.format(Locale.getDefault(), "%d秒前", span / TimeConstants.SEC)
|
||||
} else if (span < TimeConstants.HOUR) {
|
||||
return java.lang.String.format(
|
||||
Locale.getDefault(), "%d分钟前", span / TimeConstants.MIN
|
||||
)
|
||||
}
|
||||
// 获取当天 00:00
|
||||
val wee: Long = getWeeOfToday()
|
||||
return if (millis >= wee) {
|
||||
String.format("%tR", millis)
|
||||
} else if (millis >= wee - TimeConstants.DAY) {
|
||||
String.format("昨天%tR", millis)
|
||||
} else {
|
||||
String.format("%tF", millis)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getWeeOfToday(): Long {
|
||||
val cal = Calendar.getInstance()
|
||||
cal[Calendar.HOUR_OF_DAY] = 0
|
||||
cal[Calendar.SECOND] = 0
|
||||
cal[Calendar.MINUTE] = 0
|
||||
cal[Calendar.MILLISECOND] = 0
|
||||
return cal.timeInMillis
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the friendly time span by now.
|
||||
*
|
||||
* The pattern is `yyyy-MM-dd HH:mm:ss`.
|
||||
*
|
||||
* @param time The formatted time string.
|
||||
* @return the friendly time span by now
|
||||
*
|
||||
* * 如果小于 1 秒钟内,显示刚刚
|
||||
* * 如果在 1 分钟内,显示 XXX秒前
|
||||
* * 如果在 1 小时内,显示 XXX分钟前
|
||||
* * 如果在 1 小时外的今天内,显示今天15:32
|
||||
* * 如果是昨天的,显示昨天15:32
|
||||
* * 其余显示,2016-10-15
|
||||
* * 时间不合法的情况全部日期和时间信息,如星期六 十月 27 14:21:20 CST 2007
|
||||
*
|
||||
*/
|
||||
fun getFriendlyTimeSpanByNow(time: String): String {
|
||||
return getFriendlyTimeSpanByNow(time, getDefaultFormat())
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the friendly time span by now.
|
||||
*
|
||||
* @param time The formatted time string.
|
||||
* @param format The format.
|
||||
* @return the friendly time span by now
|
||||
*
|
||||
* * 如果小于 1 秒钟内,显示刚刚
|
||||
* * 如果在 1 分钟内,显示 XXX秒前
|
||||
* * 如果在 1 小时内,显示 XXX分钟前
|
||||
* * 如果在 1 小时外的今天内,显示今天15:32
|
||||
* * 如果是昨天的,显示昨天15:32
|
||||
* * 其余显示,2016-10-15
|
||||
* * 时间不合法的情况全部日期和时间信息,如星期六 十月 27 14:21:20 CST 2007
|
||||
*
|
||||
*/
|
||||
fun getFriendlyTimeSpanByNow(
|
||||
time: String, format: DateFormat
|
||||
): String {
|
||||
return getFriendlyTimeSpanByNow(string2Millis(time, format))
|
||||
}
|
||||
|
||||
fun string2Millis(time: String, format: DateFormat): Long {
|
||||
try {
|
||||
return format.parse(time)?.time ?: -1L
|
||||
} catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
@ -5,11 +5,13 @@
|
||||
<activity
|
||||
android:name=".base.SimpleVideoActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:exported="false" />
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop" />
|
||||
<activity
|
||||
android:name=".base.SimplePhotoActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:exported="false" />
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
Loading…
Reference in New Issue
Block a user