260 lines
10 KiB
Kotlin
260 lines
10 KiB
Kotlin
package com.aiosman.ravenow
|
||
|
||
import android.Manifest
|
||
import android.app.NotificationChannel
|
||
import android.app.NotificationManager
|
||
import android.content.Context
|
||
import android.content.Intent
|
||
import android.content.pm.ActivityInfo
|
||
import android.content.pm.PackageManager
|
||
import android.net.Uri
|
||
import android.os.Build
|
||
import android.os.Bundle
|
||
import android.util.Log
|
||
import androidx.activity.ComponentActivity
|
||
import androidx.activity.compose.setContent
|
||
import androidx.activity.enableEdgeToEdge
|
||
import androidx.activity.result.contract.ActivityResultContracts
|
||
import androidx.annotation.RequiresApi
|
||
import androidx.compose.animation.AnimatedContentScope
|
||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||
import androidx.compose.animation.SharedTransitionScope
|
||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||
import androidx.compose.runtime.CompositionLocalProvider
|
||
import androidx.compose.runtime.compositionLocalOf
|
||
import androidx.core.content.ContextCompat
|
||
import androidx.core.view.WindowCompat
|
||
import androidx.lifecycle.ProcessLifecycleOwner
|
||
import androidx.navigation.NavHostController
|
||
import cn.jiguang.api.utils.JCollectionAuth
|
||
import cn.jpush.android.api.JPushInterface
|
||
import com.aiosman.ravenow.data.AccountService
|
||
import com.aiosman.ravenow.data.AccountServiceImpl
|
||
import com.aiosman.ravenow.data.UserService
|
||
import com.aiosman.ravenow.data.UserServiceImpl
|
||
import com.aiosman.ravenow.ui.Navigation
|
||
import com.aiosman.ravenow.ui.NavigationRoute
|
||
import com.aiosman.ravenow.ui.dialogs.CheckUpdateDialog
|
||
import com.aiosman.ravenow.ui.navigateToPost
|
||
import com.aiosman.ravenow.ui.post.NewPostViewModel
|
||
import com.google.firebase.Firebase
|
||
import com.google.firebase.analytics.FirebaseAnalytics
|
||
import com.google.firebase.analytics.analytics
|
||
import kotlinx.coroutines.CoroutineScope
|
||
import kotlinx.coroutines.Dispatchers
|
||
import kotlinx.coroutines.launch
|
||
import androidx.compose.runtime.remember
|
||
import androidx.compose.runtime.mutableStateOf
|
||
import androidx.compose.runtime.LaunchedEffect
|
||
import androidx.compose.runtime.getValue
|
||
import androidx.compose.runtime.setValue
|
||
import com.aiosman.ravenow.ui.splash.SplashScreen
|
||
|
||
class MainActivity : ComponentActivity() {
|
||
// Firebase Analytics
|
||
private lateinit var analytics: FirebaseAnalytics
|
||
private val scope = CoroutineScope(Dispatchers.Main)
|
||
val context = this
|
||
|
||
// 请求通知权限
|
||
private val requestPermissionLauncher = registerForActivityResult(
|
||
ActivityResultContracts.RequestPermission(),
|
||
) { isGranted: Boolean ->
|
||
if (isGranted) {
|
||
// FCM SDK (and your app) can post notifications.
|
||
} else {
|
||
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取账号信息
|
||
*/
|
||
private suspend fun getAccount(): Boolean {
|
||
val accountService: AccountService = AccountServiceImpl()
|
||
try {
|
||
val resp = accountService.getMyAccount()
|
||
return true
|
||
} catch (e: Exception) {
|
||
return false
|
||
}
|
||
}
|
||
|
||
@OptIn(ExperimentalMaterial3Api::class)
|
||
@RequiresApi(Build.VERSION_CODES.P)
|
||
override fun onCreate(savedInstanceState: Bundle?) {
|
||
super.onCreate(savedInstanceState)
|
||
|
||
// 设置屏幕方向为竖屏
|
||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||
|
||
// 监听应用生命周期
|
||
ProcessLifecycleOwner.get().lifecycle.addObserver(MainActivityLifecycleObserver())
|
||
// 创建通知渠道
|
||
createNotificationChannel()
|
||
// 沉浸式状态栏
|
||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||
// 初始化 Places SDK
|
||
|
||
// 初始化 Firebase Analytics
|
||
analytics = Firebase.analytics
|
||
// 请求通知权限
|
||
askNotificationPermission()
|
||
// 加载一些本地化的配置
|
||
AppStore.init(this)
|
||
|
||
JPushInterface.setDebugMode(true);
|
||
|
||
// 调整点一:初始化代码前增加setAuth调用
|
||
JCollectionAuth.setAuth(this, true)
|
||
|
||
JPushInterface.init(this)
|
||
|
||
if (AppState.darkMode) {
|
||
window.decorView.setBackgroundColor(android.graphics.Color.BLACK)
|
||
}
|
||
enableEdgeToEdge()
|
||
|
||
scope.launch {
|
||
// 检查是否有登录态
|
||
val isAccountValidate = getAccount()
|
||
var startDestination = NavigationRoute.Login.route
|
||
// 如果有登录态,且记住登录状态,且账号有效,则初始化应用状态,下一步进入首页
|
||
if (AppStore.token != null && AppStore.rememberMe && (isAccountValidate || AppStore.isGuest)) {
|
||
// 根据用户类型进行相应的初始化(游客模式会跳过推送和TRTC初始化)
|
||
AppState.initWithAccount(scope, this@MainActivity)
|
||
startDestination = NavigationRoute.Index.route
|
||
}
|
||
|
||
setContent {
|
||
var showSplash by remember { mutableStateOf(true) }
|
||
|
||
LaunchedEffect(Unit) {
|
||
kotlinx.coroutines.delay(2000)
|
||
showSplash = false
|
||
}
|
||
|
||
if (showSplash) {
|
||
SplashScreen()
|
||
} else {
|
||
CompositionLocalProvider(
|
||
LocalAppTheme provides AppState.appTheme
|
||
) {
|
||
CheckUpdateDialog()
|
||
Navigation(startDestination) { navController ->
|
||
|
||
// 处理带有 postId 的通知点击
|
||
val postId = intent.getStringExtra("POST_ID")
|
||
var commentId = intent.getStringExtra("COMMENT_ID")
|
||
val action = intent.getStringExtra("ACTION")
|
||
if (action == "newFollow") {
|
||
navController.navigate(NavigationRoute.Followers.route)
|
||
return@Navigation
|
||
}
|
||
if (action == "followCount") {
|
||
navController.navigate(NavigationRoute.Followers.route)
|
||
return@Navigation
|
||
}
|
||
if (action == "TRTC_NEW_MESSAGE") {
|
||
val userService:UserService = UserServiceImpl()
|
||
val sender = intent.getStringExtra("SENDER")
|
||
sender?.let {
|
||
scope.launch {
|
||
try {
|
||
val profile = userService.getUserProfileByTrtcUserId(it,0)
|
||
navController.navigate(NavigationRoute.Chat.route.replace(
|
||
"{id}",
|
||
profile.id.toString()
|
||
))
|
||
}catch (e:Exception){
|
||
e.printStackTrace()
|
||
}
|
||
}
|
||
}
|
||
return@Navigation
|
||
}
|
||
|
||
if (commentId == null) {
|
||
commentId = "0"
|
||
}
|
||
|
||
if (postId != null) {
|
||
Log.d("MainActivity", "Navigation to Post$postId")
|
||
navController.navigateToPost(
|
||
id = postId.toInt(),
|
||
highlightCommentId = commentId.toInt(),
|
||
initImagePagerIndex = 0
|
||
)
|
||
}
|
||
// 处理分享过来的图片
|
||
if (intent?.action == Intent.ACTION_SEND || intent?.action == Intent.ACTION_SEND_MULTIPLE) {
|
||
val imageUris: List<Uri>? = if (intent.action == Intent.ACTION_SEND) {
|
||
listOf(intent.getParcelableExtra(Intent.EXTRA_STREAM)!!)
|
||
} else {
|
||
intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)
|
||
}
|
||
NewPostViewModel.asNewPostWithImageUris(imageUris!!.map { it.toString() })
|
||
navController.navigate(NavigationRoute.NewPost.route)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* 请求通知权限
|
||
*/
|
||
private fun askNotificationPermission() {
|
||
// This is only necessary for API level >= 33 (TIRAMISU)
|
||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
|
||
PackageManager.PERMISSION_GRANTED
|
||
) {
|
||
// FCM SDK (and your app) can post notifications.
|
||
} else if (shouldShowRequestPermissionRationale(android.Manifest.permission.POST_NOTIFICATIONS)) {
|
||
|
||
} else {
|
||
// Directly ask for the permission
|
||
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建通知渠道
|
||
*/
|
||
private fun createNotificationChannel() {
|
||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||
val channelId = ConstVars.MOMENT_LIKE_CHANNEL_ID
|
||
val channelName = ConstVars.MOMENT_LIKE_CHANNEL_NAME
|
||
val channel =
|
||
NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT)
|
||
val notificationManager =
|
||
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||
notificationManager.createNotificationChannel(channel)
|
||
}
|
||
}
|
||
}
|
||
|
||
val LocalNavController = compositionLocalOf<NavHostController> {
|
||
error("NavController not provided")
|
||
}
|
||
|
||
@OptIn(ExperimentalSharedTransitionApi::class)
|
||
val LocalSharedTransitionScope = compositionLocalOf<SharedTransitionScope> {
|
||
error("SharedTransitionScope not provided")
|
||
}
|
||
|
||
val LocalAnimatedContentScope = compositionLocalOf<AnimatedContentScope> {
|
||
error("AnimatedContentScope not provided")
|
||
}
|
||
|
||
|
||
val LocalAppTheme = compositionLocalOf<AppThemeData> {
|
||
error("AppThemeData not provided")
|
||
}
|