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
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.os.PowerManager
import androidx.activity.ComponentActivity
import com.arkivanov.decompose.ComponentContext
import androidx.compose.ui.platform.setContent
import com.arkivanov.decompose.extensions.compose.jetbrains.rootComponent
import com.arkivanov.mvikotlin.logging.store.LoggingStoreFactory
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.FetchPlatformQueryResult
import com.shabinder.common.di.createDirectories
import com.shabinder.common.root.SpotiFlyerRoot
import com.shabinder.common.root.SpotiFlyerRootContent
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
import com.shabinder.common.ui.SpotiFlyerTheme
import com.shabinder.database.Database
import kotlinx.coroutines.*
import org.koin.android.ext.android.inject
class MainActivity : AppCompatActivity() {
const val disableDozeCode = 1223
val database: Database by inject()
val fetcher: FetchPlatformQueryResult by inject()
val dir: Dir by inject()
class MainActivity : ComponentActivity() {
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?) {
super.onCreate(savedInstanceState)
setContent {
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 =
SpotiFlyerRoot(
@ -43,4 +64,42 @@ class MainActivity : AppCompatActivity() {
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) {
when (intent) {//TODO: Add Dispatchers where needed
when (intent) {
is Intent.OpenPlatform -> openPlatform(intent.platformID, intent.platformLink)
is Intent.GiveDonation -> giveDonation()
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.main.SpotiFlyerMain
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
import com.shabinder.database.Database
import com.shabinder.common.root.integration.SpotiFlyerRootImpl
import com.shabinder.common.utils.Consumer
interface SpotiFlyerRoot {
val routerState: Value<RouterState<*, Child>>
val callBacks: SpotiFlyerRootCallBacks
sealed class Child {
data class Main(val component: SpotiFlyerMain) : 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
@Composable
fun SpotiFlyerRootContent(component: SpotiFlyerRoot) {
fun SpotiFlyerRootContent(component: SpotiFlyerRoot):SpotiFlyerRoot {
val appBarColor = MaterialTheme.colors.surface
Column(
modifier = Modifier.fillMaxSize()
@ -43,6 +44,7 @@ fun SpotiFlyerRootContent(component: SpotiFlyerRoot) {
}
}
}
return component
}
@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.Child
import com.shabinder.common.root.SpotiFlyerRoot.Dependencies
import com.shabinder.common.root.callbacks.SpotiFlyerRootCallBacks
import com.shabinder.common.utils.Consumer
internal class SpotiFlyerRootImpl(
componentContext: ComponentContext,
dependencies: Dependencies
dependencies: Dependencies,
) : SpotiFlyerRoot, ComponentContext by componentContext, Dependencies by dependencies {
private val router =
@ -30,6 +31,10 @@ internal class SpotiFlyerRootImpl(
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 =
when (configuration) {
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,
accessToken TEXT 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
expect fun openPlatform(platformID:String ,platformLink:String)
expect fun openPlatform(packageID:String, platformLink:String)
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
actual fun openPlatform(platformID:String ,platformLink:String){
actual fun openPlatform(packageID:String, platformLink:String){
//TODO
}

View File

@ -22,6 +22,10 @@ kotlin {
implementation(project(":common:database"))
implementation(project(":common:dependency-injection"))
implementation(project(":common:compose-ui"))
implementation(Decompose.decompose)
implementation(Decompose.extensionsCompose)
implementation(MVIKotlin.mvikotlin)
implementation(MVIKotlin.mvikotlinMain)
}
}
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")
}
}