Android Intents & Callbacks

This commit is contained in:
shabinder 2021-02-10 22:55:36 +05:30
parent 9d892507c6
commit 02e6ef3a47
33 changed files with 225 additions and 55 deletions

View File

@ -1,37 +1,58 @@
package com.shabinder.android package com.shabinder.android
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import android.os.PowerManager
import androidx.activity.ComponentActivity
import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.ComponentContext
import androidx.compose.ui.platform.setContent import androidx.compose.ui.platform.setContent
import com.arkivanov.decompose.extensions.compose.jetbrains.rootComponent import com.arkivanov.decompose.extensions.compose.jetbrains.rootComponent
import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
import com.shabinder.android.utils.checkIfLatestVersion
import com.shabinder.android.utils.disableDozeMode
import com.shabinder.android.utils.requestStoragePermission
import com.shabinder.common.di.Dir import com.shabinder.common.di.Dir
import com.shabinder.common.di.FetchPlatformQueryResult import com.shabinder.common.di.FetchPlatformQueryResult
import com.shabinder.common.di.createDirectories import com.shabinder.common.di.createDirectories
import com.shabinder.common.root.SpotiFlyerRoot import com.shabinder.common.root.SpotiFlyerRoot
import com.shabinder.common.root.SpotiFlyerRootContent import com.shabinder.common.root.SpotiFlyerRootContent
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
import com.shabinder.common.ui.SpotiFlyerTheme import com.shabinder.common.ui.SpotiFlyerTheme
import com.shabinder.database.Database import com.shabinder.database.Database
import kotlinx.coroutines.*
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
class MainActivity : AppCompatActivity() { const val disableDozeCode = 1223
val database: Database by inject() class MainActivity : ComponentActivity() {
val fetcher: FetchPlatformQueryResult by inject()
val dir: Dir by inject() private val database: Database by inject()
private val fetcher: FetchPlatformQueryResult by inject()
private val dir: Dir by inject()
private lateinit var root: SpotiFlyerRoot
private val callBacks: SpotiFlyerRootCallBacks
get() = root.callBacks
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
SpotiFlyerTheme { SpotiFlyerTheme {
SpotiFlyerRootContent(rootComponent(::spotiFlyerRoot)) root = SpotiFlyerRootContent(rootComponent(::spotiFlyerRoot))
} }
} }
dir.createDirectories() initialise()
} }
private fun initialise() {
checkIfLatestVersion()
requestStoragePermission()
disableDozeMode(disableDozeCode)
dir.createDirectories()
}
private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot = private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot =
SpotiFlyerRoot( SpotiFlyerRoot(
@ -43,4 +64,42 @@ class MainActivity : AppCompatActivity() {
override val directories: Dir = this@MainActivity.dir override val directories: Dir = this@MainActivity.dir
} }
) )
@SuppressLint("ObsoleteSdkInt")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == disableDozeCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val pm =
getSystemService(Context.POWER_SERVICE) as PowerManager
val isIgnoringBatteryOptimizations =
pm.isIgnoringBatteryOptimizations(packageName)
if (isIgnoringBatteryOptimizations) {
// Ignoring battery optimization
} else {
disableDozeMode(disableDozeCode)//Again Ask For Permission!!
}
}
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
handleIntentFromExternalActivity(intent)
}
private fun handleIntentFromExternalActivity(intent: Intent? = getIntent()) {
if (intent?.action == Intent.ACTION_SEND) {
if ("text/plain" == intent.type) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
val filterLinkRegex = """http.+\w""".toRegex()
val string = it.replace("\n".toRegex(), " ")
val link = filterLinkRegex.find(string)?.value.toString()
callBacks.searchLink(link)
}
}
}
}
} }

View File

@ -0,0 +1,49 @@
package com.shabinder.android.utils
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.PowerManager
import android.provider.Settings
import com.github.javiersantos.appupdater.AppUpdater
import com.github.javiersantos.appupdater.enums.Display
import com.github.javiersantos.appupdater.enums.UpdateFrom
fun Activity.checkIfLatestVersion() {
AppUpdater(this,0).run {
setDisplay(Display.NOTIFICATION)
showAppUpdated(false)//true:Show App is Updated Dialog
setUpdateFrom(UpdateFrom.XML)
setUpdateXML("https://raw.githubusercontent.com/Shabinder/SpotiFlyer/Compose/app/src/main/res/xml/app_update.xml")
setCancelable(false)
start()
}
}
@SuppressLint("BatteryLife", "ObsoleteSdkInt")
fun Activity.disableDozeMode(requestCode:Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val pm =
this.getSystemService(Context.POWER_SERVICE) as PowerManager
val isIgnoringBatteryOptimizations = pm.isIgnoringBatteryOptimizations(packageName)
if (!isIgnoringBatteryOptimizations) {
val intent = Intent().apply{
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
data = Uri.parse("package:$packageName")
}
startActivityForResult(intent, requestCode)
}
}
}
@SuppressLint("ObsoleteSdkInt")
fun Activity.requestStoragePermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
this.requestPermissions(
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
786
)
}
}

View File

@ -31,14 +31,3 @@ kotlin {
} }
} }
} }
/*
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
//useIR = true
freeCompilerArgs = listOf("-Xallow-jvm-ir-dependencies",
"-Xallow-unstable-dependencies","-Xskip-prerelease-check",
"-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-Xuse-experimental=kotlinx.coroutines.TheAnnotationYouWantToDisable"
)
}
}*/

View File

@ -62,7 +62,7 @@ internal class SpotiFlyerMainStoreProvider(
} }
override suspend fun executeIntent(intent: Intent, getState: () -> State) { override suspend fun executeIntent(intent: Intent, getState: () -> State) {
when (intent) {//TODO: Add Dispatchers where needed when (intent) {
is Intent.OpenPlatform -> openPlatform(intent.platformID, intent.platformLink) is Intent.OpenPlatform -> openPlatform(intent.platformID, intent.platformLink)
is Intent.GiveDonation -> giveDonation() is Intent.GiveDonation -> giveDonation()
is Intent.ShareApp -> shareApp() is Intent.ShareApp -> shareApp()

View File

@ -9,13 +9,17 @@ import com.shabinder.common.di.FetchPlatformQueryResult
import com.shabinder.common.list.SpotiFlyerList import com.shabinder.common.list.SpotiFlyerList
import com.shabinder.common.main.SpotiFlyerMain import com.shabinder.common.main.SpotiFlyerMain
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
import com.shabinder.database.Database import com.shabinder.database.Database
import com.shabinder.common.root.integration.SpotiFlyerRootImpl import com.shabinder.common.root.integration.SpotiFlyerRootImpl
import com.shabinder.common.utils.Consumer
interface SpotiFlyerRoot { interface SpotiFlyerRoot {
val routerState: Value<RouterState<*, Child>> val routerState: Value<RouterState<*, Child>>
val callBacks: SpotiFlyerRootCallBacks
sealed class Child { sealed class Child {
data class Main(val component: SpotiFlyerMain) : Child() data class Main(val component: SpotiFlyerMain) : Child()
data class List(val component: SpotiFlyerList) : Child() data class List(val component: SpotiFlyerList) : Child()

View File

@ -18,7 +18,8 @@ import com.shabinder.common.ui.SpotiFlyerLogo
import com.shabinder.common.ui.appNameStyle import com.shabinder.common.ui.appNameStyle
@Composable @Composable
fun SpotiFlyerRootContent(component: SpotiFlyerRoot) { fun SpotiFlyerRootContent(component: SpotiFlyerRoot):SpotiFlyerRoot {
val appBarColor = MaterialTheme.colors.surface val appBarColor = MaterialTheme.colors.surface
Column( Column(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
@ -43,6 +44,7 @@ fun SpotiFlyerRootContent(component: SpotiFlyerRoot) {
} }
} }
} }
return component
} }
@Composable @Composable

View File

@ -0,0 +1,5 @@
package com.shabinder.common.root.callbacks
interface SpotiFlyerRootCallBacks {
fun searchLink(link:String)
}

View File

@ -14,11 +14,12 @@ import com.shabinder.common.main.SpotiFlyerMain
import com.shabinder.common.root.SpotiFlyerRoot import com.shabinder.common.root.SpotiFlyerRoot
import com.shabinder.common.root.SpotiFlyerRoot.Child import com.shabinder.common.root.SpotiFlyerRoot.Child
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
import com.shabinder.common.utils.Consumer import com.shabinder.common.utils.Consumer
internal class SpotiFlyerRootImpl( internal class SpotiFlyerRootImpl(
componentContext: ComponentContext, componentContext: ComponentContext,
dependencies: Dependencies dependencies: Dependencies,
) : SpotiFlyerRoot, ComponentContext by componentContext, Dependencies by dependencies { ) : SpotiFlyerRoot, ComponentContext by componentContext, Dependencies by dependencies {
private val router = private val router =
@ -30,6 +31,10 @@ internal class SpotiFlyerRootImpl(
override val routerState: Value<RouterState<*, Child>> = router.state override val routerState: Value<RouterState<*, Child>> = router.state
override val callBacks = object : SpotiFlyerRootCallBacks{
override fun searchLink(link: String) = onMainOutput(SpotiFlyerMain.Output.Search(link))
}
private fun createChild(configuration: Configuration, componentContext: ComponentContext): Child = private fun createChild(configuration: Configuration, componentContext: ComponentContext): Child =
when (configuration) { when (configuration) {
is Configuration.Main -> Child.Main(spotiFlyerMain(componentContext)) is Configuration.Main -> Child.Main(spotiFlyerMain(componentContext))

View File

@ -1,4 +1,4 @@
CREATE TABLE Token ( CREATE TABLE IF NOT EXISTS Token (
tokenIndex INTEGER NOT NULL DEFAULT 0 PRIMARY KEY ON CONFLICT REPLACE, tokenIndex INTEGER NOT NULL DEFAULT 0 PRIMARY KEY ON CONFLICT REPLACE,
accessToken TEXT NOT NULL, accessToken TEXT NOT NULL,
expiry INTEGER NOT NULL expiry INTEGER NOT NULL

View File

@ -0,0 +1,34 @@
package com.shabinder.common.di
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import com.shabinder.common.database.appContext
import com.shabinder.common.models.TrackDetails
actual fun openPlatform(packageID:String, platformLink:String){
val manager: PackageManager = appContext.packageManager
try {
val intent = manager.getLaunchIntentForPackage(packageID)
?: throw PackageManager.NameNotFoundException()
intent.addCategory(Intent.CATEGORY_LAUNCHER)
appContext.startActivity(intent)
} catch (e: PackageManager.NameNotFoundException) {
val uri: Uri =
Uri.parse(platformLink)
val intent = Intent(Intent.ACTION_VIEW, uri)
appContext.startActivity(intent)
}
}
actual fun shareApp(){
//TODO
}
actual fun giveDonation(){
//TODO
}
actual fun downloadTracks(list: List<TrackDetails>){
//TODO
}

View File

@ -2,7 +2,7 @@ package com.shabinder.common.di
import com.shabinder.common.models.TrackDetails import com.shabinder.common.models.TrackDetails
expect fun openPlatform(platformID:String ,platformLink:String) expect fun openPlatform(packageID:String, platformLink:String)
expect fun shareApp() expect fun shareApp()

View File

@ -1,19 +0,0 @@
package com.shabinder.common.di
import com.shabinder.common.models.TrackDetails
actual fun openPlatform(platformID:String ,platformLink:String){
//TODO
}
actual fun shareApp(){
//TODO
}
actual fun giveDonation(){
//TODO
}
actual fun downloadTracks(list: List<TrackDetails>){
//TODO
}

View File

@ -2,7 +2,7 @@ package com.shabinder.common.di
import com.shabinder.common.models.TrackDetails import com.shabinder.common.models.TrackDetails
actual fun openPlatform(platformID:String ,platformLink:String){ actual fun openPlatform(packageID:String, platformLink:String){
//TODO //TODO
} }

View File

@ -22,6 +22,10 @@ kotlin {
implementation(project(":common:database")) implementation(project(":common:database"))
implementation(project(":common:dependency-injection")) implementation(project(":common:dependency-injection"))
implementation(project(":common:compose-ui")) implementation(project(":common:compose-ui"))
implementation(Decompose.decompose)
implementation(Decompose.extensionsCompose)
implementation(MVIKotlin.mvikotlin)
implementation(MVIKotlin.mvikotlinMain)
} }
} }
val jvmTest by getting val jvmTest by getting

View File

@ -0,0 +1,50 @@
import androidx.compose.desktop.DesktopMaterialTheme
import androidx.compose.desktop.Window
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Surface
import androidx.compose.ui.Modifier
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.extensions.compose.jetbrains.rootComponent
import com.arkivanov.mvikotlin.core.lifecycle.LifecycleRegistry
import com.arkivanov.mvikotlin.core.lifecycle.resume
import com.arkivanov.mvikotlin.main.store.DefaultStoreFactory
import com.shabinder.common.di.Dir
import com.shabinder.common.di.FetchPlatformQueryResult
import com.shabinder.common.di.initKoin
import com.shabinder.common.root.SpotiFlyerRoot
import com.shabinder.common.root.SpotiFlyerRootContent
import com.shabinder.common.ui.SpotiFlyerColors
import com.shabinder.common.ui.SpotiFlyerShapes
import com.shabinder.common.ui.SpotiFlyerTypography
import com.shabinder.database.Database
private val koin = initKoin(enableNetworkLogs = true).koin
fun main(){
val lifecycle = LifecycleRegistry()
lifecycle.resume()
Window("SpotiFlyer") {
Surface(modifier = Modifier.fillMaxSize()) {
DesktopMaterialTheme(
// colors = SpotiFlyerColors,
// typography = SpotiFlyerTypography,
// shapes = SpotiFlyerShapes
) {
SpotiFlyerRootContent(rootComponent(factory = ::spotiFlyerRoot))
}
}
}
}
private fun spotiFlyerRoot(componentContext: ComponentContext): SpotiFlyerRoot =
SpotiFlyerRoot(
componentContext = componentContext,
dependencies = object : SpotiFlyerRoot.Dependencies {
override val storeFactory = DefaultStoreFactory
override val database: Database = koin.get()
override val fetchPlatformQueryResult: FetchPlatformQueryResult = koin.get()
override val directories: Dir = koin.get()
}
)

View File

@ -1,12 +0,0 @@
import androidx.compose.desktop.Window
import androidx.compose.foundation.layout.Column
import androidx.compose.material.Text
import com.shabinder.common.di.initKoin
private val koin = initKoin(enableNetworkLogs = true).koin
fun main() = Window {
Column{
Text("Hello World")
}
}