Android Library for requesting Permissions with Kotlin Coroutines or AndroidX LiveData

Overview

PEKO

PErmissions with KOtlin

Build Status Android Arsenal License

Android Permissions with Kotlin Coroutines or LiveData

No more callbacks, builders, listeners or verbose code for requesting Android permissions.
Get Permission Request Result asynchronously with one function call.
Thanks to Kotlin Coroutines, permissions requests are async and lightweight (no new threads are used/created).

Or if you don't use Coroutines, and don't want to manage Lifecycles ... receive Permission Results with LiveData.


Installation

Hosted on Maven Central

implementation 'com.markodevcic:peko:2.1.2'

What is new

Peko Version 2 now uses Android X packages, Kotlin v1.4.0 and Coroutines 1.3.9.

Breaking changes from Peko Version 1.0

  • PermissionRequestResult is renamed to PermissionResult and is now a sealed class.

    PermissionResult has a sealed class hierarchy of following types: PermissionResult.Granted -> returned when all requested permissions were granted

    PermissionResult.Denied -> returned when at least one of the permissions was denied

    PermissionResult.Denied.NeedsRationale -> subclass of PermissionResult.Denied, returned when Android OS signals that at least one of the permissions needs to show a rationale

    PermissionResult.Denied.DeniedPermanently -> subclass of PermissionResult.Denied, returned when no permissions need a Rationale and at least one of the permissions has a ticked Do Not Ask Again check box

    PermissionResult.Denied.JustDenied -> subclass of PermissionResult.Denied, returned when previous two cases are not the cause, for example if you forget to register the Permission in AndroidManifest

    PermissionResult.Cancelled -> returned when Android System cancels the request, ie returned

  • PermissionRationale interface was removed. Library does not show Permission Rationales anymore. You can check now if PermissionResult is of type PermissionResult.NeedsRationale and implement the rationale yourself.

  • Added support for requesting permissions with LiveData

Peko Version 1.0 uses AppCompat libraries and is here.

Example

In an Activity or a Fragment that implements CoroutineScope interface:

launch {
    val result = Peko.requestPermissionsAsync(this, Manifest.permission.READ_CONTACTS) 
    
    if (result is PermissionResult.Granted) {
        // we have contacts permission
    } else {
        // permission denied
    }
}

Or use one of the extension functions on an Activity or a Fragment:

launch {
    val result = requestPermissionsAsync(Manifest.permission.READ_CONTACTS) 
    
    if (result is PermissionResult.Granted) {
        // we have contacts permission
    } else {
        // permission denied
    }
}

Request multiple permissions:

launch {
    val result = requestPermissionsAsync(Manifest.permission.READ_CONTACTS, Manifest.permission.CAMERA) 
    
    if (result is PermissionResult.Granted) {
        // we have both permissions
    } else if (result is PermissionResult.Denied) {
        result.deniedPermissions.forEach { p ->
            // this one was denied
        }
    }
}

Denied Result has three subtypes which can be checked to see if we need Permission Rationale or user Clicked Do Not Ask Again.

launch {
    val result = requestPermissionsAsync(Manifest.permission.BLUETOOTH, Manifest.permission.CAMERA) 
    
    when (result) {
        is PermissionResult.Granted -> { } // woohoo, all requested permissions granted
        is PermissionResult.Denied.JustDenied -> { } // at least one permission was denied, maybe we forgot to register it in the AndroidManifest?
        is PermissionResult.Denied.NeedsRationale -> { } // user clicked Deny, let's show a rationale
        is PermissionResult.Denied.DeniedPermanently -> { } // Android System won't show Permission dialog anymore, let's tell the user we can't proceed
        is PermissionResult.Cancelled -> { } // interaction was interrupted
    }
}

If you want to know which permissions were denied, they are a property of Denied class.

class Denied(val deniedPermissions: Collection<String>)

LiveData

Hate Coroutines? No problem ... just create an instance of PermissionsLiveData and observe the results with your LifecycleOwner

In a ViewModel ... if you need to support orientation changes, or anywhere else if not (Presenter)

    val permissionLiveData = PermissionsLiveData()
    
    fun checkPermissions(vararg permissions: String) {
        permissionLiveData.checkPermissions(*permissions)
    }

In your LifecycleOwner, for example in an Activity

override fun onCreate(savedInstanceState: Bundle?) {
    viewModel = ViewModelProviders.of(this).get(YourViewModel::class.java)
    // observe has to be called before checkPermissions, so we can get the LifecycleOwner
    viewModel.permissionLiveData.observe(this, Observer { r: PermissionResult ->
        // do something with permission results
    })
}

private fun askContactsPermissions() {
    viewModel.checkPermissions(Manifest.permission.READ_CONTACTS)
}

Screen rotations

Library has support for screen rotations. To avoid memory leaks, all Coroutines that have not completed yet, should be cancelled in the onDestroy function. When you detect a orientation change, cancel the Job of a CoroutineScope with an instance of ActivityRotatingException. Internally, this will retain the current request that is in progress. The request is then resumed with calling resumeRequest method.

Example:

First:

// job that will be cancelled in onDestroy
private val job = Job()

private fun requestPermission(vararg permissions: String) {
    launch { 
        val result = Peko.requestPermissionsAsync(this@MainActivity, *permissions)
        // check granted permissions
    }
}

Then in onDestroy of an Activity:

if (isChangingConfigurations) {
    job.cancel(ActivityRotatingException()) // screen rotation, retain the results
} else { 
    job.cancel() // no rotation, just cancel the Coroutine
}

And when this Activity gets recreated in one of the Activity lifecycle functions, e.g.onCreate:

// check if we have a request already (or some other way you detect screen orientation)
if (Peko.isRequestInProgress()) {
    launch {
        // get the existing request and await the result
        val result = Peko.resumeRequest() 
        // check granted permissions
    }
}

LiveData and screen rotations

You don't have to do anything, this logic is already inside the PermissionsLiveData class. You just have to call observe in the onCreate method and of course use androidx.lifecycle.ViewModel.

License

Copyright 2021 Marko Devcic

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Is it possible to find out if user clicked do not ask again?

    Is it possible to find out if user clicked do not ask again?

    I haven't found possibility to check whether it make sense to ask for that permission again. Ideally I would like to have something like

    val result = Peko.requestPermission(Bluetooth, context)
    when (result)  {
      GRANTED -> proceed()
      DENIED -> postExplanation() //and request again
      BLOCKED -> showDifferentExplanation()
    }
    
    opened by Dmitry-Borodin 10
  • ClosedSendChannelException in PekoActivity

    ClosedSendChannelException in PekoActivity

    Hi, I have a few crashes in PekoActivity.onRequestPermissionsResult when processing the result to the corountine channel

    viewModel.channel.offer(
        when {
            permissions.isEmpty() -> PermissionResult.Cancelled
            deniedPermissions.isEmpty() -> PermissionResult.Granted(grantedPermissions)
            needsRationale -> PermissionResult.Denied.NeedsRationale(deniedPermissions)
            doNotAskAgain -> PermissionResult.Denied.DeniedPermanently(deniedPermissions)
            else -> PermissionResult.Denied.JustDenied(deniedPermissions)
        })
    

    I happen to have a closed channel. with the following stack

    kotlinx.coroutines.channels.Closed.getSendException (Closed.java:1139)
    kotlinx.coroutines.channels.AbstractSendChannel.helpCloseAndGetSendException (AbstractSendChannel.java:173)
    kotlinx.coroutines.channels.AbstractSendChannel.trySend-JP2dKIU (AbstractSendChannel.java:165)
    kotlinx.coroutines.channels.SendChannel$DefaultImpls.offer (SendChannel.java:166)
    kotlinx.coroutines.channels.AbstractSendChannel.offer (AbstractSendChannel.java:142)
    com.markodevcic.peko.PekoActivity.onRequestPermissionsResult (PekoActivity.java:52)
    

    I didn't manage to reproduce it. I can only guess that, somehow, the coroutine is started from a lifecycle dependent object, which is dead by the time the PekoActivity try to send the result ? Maybe is wise to add a basic check like this at PekoActivity:52:

    if(!channel.isClosedForSend) {
        viewModel.channel.offer(
            when {
                permissions.isEmpty() -> PermissionResult.Cancelled
                deniedPermissions.isEmpty() -> PermissionResult.Granted(grantedPermissions)
                needsRationale -> PermissionResult.Denied.NeedsRationale(deniedPermissions)
                doNotAskAgain -> PermissionResult.Denied.DeniedPermanently(deniedPermissions)
                else -> PermissionResult.Denied.JustDenied(deniedPermissions)
            })
    }
    

    What do you think ? Thank you, Regards.

    opened by ghost 5
  • Crash when using app-context for permission request

    Crash when using app-context for permission request

    Nice permission framework, I was just looking for something with coroutines.

    PEKO 2.1.4.

    I get this error, when doing Peko.requestPermissionsAsync(application, locationPermission)

    but not when doing

    Peko.requestPermissionsAsync(activity, locationPermission)

    So I suspect the method should be changed to require activity as input... (?).

    
        Process: dk.bnr.bnr.dev, PID: 3849
        android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
            at android.app.ContextImpl.startActivity(ContextImpl.java:1029)
            at android.app.ContextImpl.startActivity(ContextImpl.java:1005)
            at android.content.ContextWrapper.startActivity(ContextWrapper.java:403)
            at com.markodevcic.peko.PermissionRequesterFactoryImpl.getRequesterAsync(PermissionRequesterFactory.kt:21)
            at com.markodevcic.peko.PekoService$requestPermissions$3.invokeSuspend(PekoService.kt:59)
            at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
            at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
            at android.os.Handler.handleCallback(Handler.java:938)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:233)
            at android.app.ActivityThread.main(ActivityThread.java:8010)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:631)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:978)
        	Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@fe01cb9, Dispatchers.Main]
    
    opened by arberg 4
  • Migrate to Maven Central

    Migrate to Maven Central

    JFrog just announced that they'll be shutting down JCenter, keeping it as a read-only package repo: https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/

    Key dates are:

    • March 31st 2021: No more submissions will be accepted to Bintray, JCenter

    Hence Peko should also be migrated to another maven repository like Maven central.

    opened by bearlysophisticated 4
  • Sunsetting jcenter

    Sunsetting jcenter

    https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/ Please provide another way to access you library, many people depend on it -) I need to do the same for some of my libs, not sure yet of what is the right solution.

    opened by Dmitry-Borodin 4
  • Suggestion: Add Peko.isGranted(activity, permission)

    Suggestion: Add Peko.isGranted(activity, permission)

    I would be nice to have an isGranted (because Androids' API suck).

    Such as extension-function on activity, and/or Peko function.

    I also suggest creating an Peko instance-class which could wrap the activity object, because that gives nicer interface for all peko methods. Like 'rxPermissions' does:

    https://github.com/tbruyelle/RxPermissions/blob/master/lib/src/main/java/com/tbruyelle/rxpermissions3/RxPermissions.java

    It would be nice to have a peko.shouldShowRequestPermissionRationale peko.isGranted

    opened by arberg 2
  • If less than API-23 then permissions should be treated as granted

    If less than API-23 then permissions should be treated as granted

    I noticed this:

    suspend fun requestPermissionsAsync(context: Context, vararg permissions: String): PermissionResult {
    
            if (isTargetSdkUnderAndroidM(context)) {
                return PermissionResult.Denied.JustDenied(permissions.toList())
            }
    

    Before Android-23 all permissions are granted without asking user, just by declaring in manifest. So this should return Granted. Like rxPermission does in isGranted here:

    https://github.com/tbruyelle/RxPermissions/blob/master/lib/src/main/java/com/tbruyelle/rxpermissions3/RxPermissions.java

    opened by arberg 2
  • Add android:exported attribute to AndroidManifest

    Add android:exported attribute to AndroidManifest

    I believe I am getting Manifest Merger errors because of the missing attribute in this lib.

    Please see Android Dev documentation:

    If your app targets Android 12 and contains activities, services, or broadcast receivers that use intent filters, you must explicitly declare the android:exported attribute for these app components.

    I set the attribute to "true" in this PR but setting it to "false" would also fix compatibility with Android 12.

    opened by sebastinto 2
  • viewLifeCycleOwner of a fragment is throwing: Unsupported lifecycle owner

    viewLifeCycleOwner of a fragment is throwing: Unsupported lifecycle owner

    According to https://developer.android.com/topic/libraries/architecture/livedata and some articles https://proandroiddev.com/5-common-mistakes-when-using-architecture-components-403e9899f4cb, viewLifeCycleOwner is the right one to use instead of the fragment itself but when we try:

    private fun observePermissions() {
            viewModel.permissionLiveData.observe(viewLifecycleOwner) {
                when(it) {
    
                    is PermissionResult.Granted -> {
                        onPermissionGranted(it.grantedPermissions)
                    }
    
                    is PermissionResult.Denied.JustDenied -> {
                        onPermissionDenied(it.deniedPermissions)
                    }
    
                    is PermissionResult.Denied.NeedsRationale -> {
                        showPermissionRationale(it.deniedPermissions)
                    }
    
                    is PermissionResult.Denied.DeniedPermanently -> {
                        showPermissionRationale(it.deniedPermissions)
                    }
    
                    is PermissionResult.Cancelled -> {
                        onCancelPermissionDialog()
                    }
                }
            }
        }
    

    It gives an exception: "Unsupported lifecycle owner". It is working fine if we pass "this" as a lifecycle owner for the fragment.

    opened by sagarpatel288 2
  • Feature request: Add PermissionRequester.isAnyGranted function

    Feature request: Add PermissionRequester.isAnyGranted function

    It will be helpful to add PermissionRequester.isAnyGranted in case of we need any of requested permissions. In case of requesting permissionRequester.areGranted(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION) we can't get permission for both of them - there is no actually need in both - any of them will be fine). But method PermissionRequester.areGranted checks for empty denied requests. In this case would be helpful to have function such as PermissionRequester.isAnyGranted which will return true if any of permissions was granted

    opened by FogelAO 1
  • PermissionResult.NeedsRationale and PermissionResult.DoNotAskAgain is better not a subclass of PermissionResult.Denied

    PermissionResult.NeedsRationale and PermissionResult.DoNotAskAgain is better not a subclass of PermissionResult.Denied

    The sample code of README is as follows,

    launch {
        val result = requestPermissionsAsync(Manifest.permission.BLUETOOTH, Manifest.permission.CAMERA) 
        
        when (result) {
            is PermissionResult.Granted -> { } // woohoo, all requested permissions granted
            is PermissionResult.Denied -> { } // at least one permission was denied
            is PermissionResult.NeedsRationale -> { } // user clicked Deny, let's show a rationale
            is PermissionResult.DoNotAskAgain -> { } // Android System won't show Permission dialog anymore, let's tell the user we can't proceed 
        }
    }
    

    In this case, if result variable is PermissionResult.NeedsRationale, First match PermissionResult.Denied, PermissionResult.NeedsRationale block is not executed.

    This can be handled by changing the evaluation order of result variable in the order of NeedsRationale, DoNotAskAgain, Denied, But it's not good because the behavior changes depending on how it line up.

    opened by cnaos 1
  • Deadlock when executing request permission

    Deadlock when executing request permission

    PEKO 3.0.1

    If I request permission on a fresh app startup where permissions has not been requested previously, then the app is stuck in a deadlock style ANR. It never proceeds. The same code I run works when I execute it via button press later

    private val permissionRequester = PermissionRequester.instance() // Creates new instance
    
        fun register() {
            CoroutineScope(Dispatchers.Main).launch {
                permissionRequester.request(android.Manifest.permission.ACCESS_FINE_LOCATION)
                    .collect {
                        // MyStuff - It never arrives to collect when deadlocked
                    }
            }
        }
    

    Debugging indicates that it hangs after executing PermissionRequester:75 which is this line

    val requester = requesterFactory.getRequesterAsync(requireContext()).await()
    

    And the PekoActivity executes onPostCreate (with non-null requesterDeferred) but neither requestPermissions, onRequestPermissionsResult nor finish got executed on PekoActivity according to my breakpoints. Apparantly your maven upload included the source-code, so IntelliJ could debug it which was pretty cool.

    If I change the code so it performs the request on another thread, then it works

        fun register() {
            CoroutineScope(Dispatchers.Main).launch {
                // do my stuff on main (if needed, otherwise we could just create the above coroutine on IO or elsewhere
                withContext(Dispatchers.IO) { // this works, no deadlock
                    permissionRequester.request(android.Manifest.permission.ACCESS_FINE_LOCATION)
                        .collect {
                            withContext(Dispatchers.Main) {
                                // do my stuff back on mair
                            }
                        }
                }
            }
        }
    

    After changing to the above code, the coroutine proceeded past the PermissionRequester:75 await line, performed the permission-requests and then things ran along fine from there.

    For some reason the main-thread code only hung when I executed during my startup work (but long after onCreate), but did not hang when executed from user button click. But then again, that just indicates deadlocks can be tricky.

    Its quite unclear to me how it can be a deadlock, as your coroutines seem fine. They suspend and should allow the main to do its work.

    I have no idea if you can make any sense of that. I'll probably roll back to v2 though that had a resume rare bug, but for now I'll skip requesting permission on startup and let the user trigger it.

    if you changed your library to the following I suspect it would work:

    					val asyncRequester = requesterFactory.getRequesterAsync(requireContext())
    					val requester = 
    					withContext(Dispaters.IO) {
    					    asyncRequester.await()
    					}
    

    Best Alex

    opened by arberg 10
  • DeniedPermanently triggered when selecting Approximate instead of Precise location

    DeniedPermanently triggered when selecting Approximate instead of Precise location

    As stated in title.

    Compile SDK: 33 Android version: 13 Image: https://i.imgur.com/FwdLvgh.png

    CoroutineScope(Default).launch {
                val result = requestPermissionsAsync(
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION
                )
    
                when (result) {
                    is PermissionResult.Granted -> {Log.e("Activity", "GRANTED") } // woohoo, all requested permissions granted
                    is PermissionResult.Denied.JustDenied -> {Log.e("Activity", "JUST DENIED") } // at least one permission was denied, maybe we forgot to register it in the AndroidManifest?
                    is PermissionResult.Denied.NeedsRationale -> {Log.e("Activity", "NEEDS") } // user clicked Deny, let's show a rationale
                    is PermissionResult.Denied.DeniedPermanently -> { Log.e("Activity", "DENIED PERM")} // Android System won't show Permission dialog anymore, let's tell the user we can't proceed
                    is PermissionResult.Cancelled -> {Log.e("Activity", "CANCELLED") } // interaction was interrupted
                }
            }
    
    opened by KrLx1994roller 2
  • DeniedPermanently triggered when clicking outside of permissions dialog

    DeniedPermanently triggered when clicking outside of permissions dialog

    Hey,

    When the user does not click on any button of the Android native request dialog but outside, the dialog gets dismissed and Peko triggers the PermissionResult.Denied.DeniedPermanently result. I think in this case PermissionResult.Cancelled should be called. The native dialog is triggered on next Activity execution despite Peko's PermissionResult.Denied.DeniedPermanently result.

    Compile SDK: 33 Android version: 13

    CoroutineScope(Default).launch {
                val result = requestPermissionsAsync(
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION
                )
    
                when (result) {
                    is PermissionResult.Granted -> {Log.e("Activity", "GRANTED") } // woohoo, all requested permissions granted
                    is PermissionResult.Denied.JustDenied -> {Log.e("Activity", "JUST DENIED") } // at least one permission was denied, maybe we forgot to register it in the AndroidManifest?
                    is PermissionResult.Denied.NeedsRationale -> {Log.e("Activity", "NEEDS") } // user clicked Deny, let's show a rationale
                    is PermissionResult.Denied.DeniedPermanently -> { Log.e("Activity", "DENIED PERM")} // Android System won't show Permission dialog anymore, let's tell the user we can't proceed
                    is PermissionResult.Cancelled -> {Log.e("Activity", "CANCELLED") } // interaction was interrupted
                }
            }
    
    opened by KrLx1994roller 4
  • Downgrade com.google.android.material:material:1.5.0

    Downgrade com.google.android.material:material:1.5.0

    When using com.google.android.material:material:1.0.0 i got an error that some files (sdk 31) are missing. please downgrade to a lower material gradle

    opened by prologikus 1
  • Provide a way to pass a custom CoroutineDispatcher to requestPermissionsAsync

    Provide a way to pass a custom CoroutineDispatcher to requestPermissionsAsync

    Due to the issue in Dispatchers.Main described here https://github.com/Kotlin/kotlinx.coroutines/issues/878, using requestPermissionsAsync might block the main thread for a few hundred milliseconds causing a frame drop. It would make sense to be able to pass an optional CoroutineDispatcher to requestPermissionsAsync so that we can use self-made main dispatchers like here https://github.com/Kotlin/kotlinx.coroutines/issues/878#issuecomment-458658434.

    opened by Ornolfr 1
Releases(v3.0.1)
  • v3.0.1(Nov 4, 2022)

    Major release with a breaking change. Permission results are now returned as Kotlin coroutine Flow.

    • PermissionResult now has a single String permission as property.
    • Peko singleton is removed. PermissionRequester interface is now its replacement.
    • Extension functions for Fragment and Activity are removed.
    • PermissionLiveData class removed
    • Updated to Kotlin v1.6.21 and coroutines v1.6.4
    Source code(tar.gz)
    Source code(zip)
  • v3.0.0-ALPHA-01(Oct 17, 2022)

    Major release with a breaking change from vanilla Kotlin coroutines to Kotlin coroutine Flow.

    • PermissionResult now has a single String permission as property.
    • Peko singleton is removed. PermissionRequester interface is now its replacement.
    • Extension functions for Fragment and Activity are removed.
    • PermissionLiveData class removed
    • Updated to Kotlin v1.6.21 and coroutines v1.6.4
    Source code(tar.gz)
    Source code(zip)
  • v2.2.0(Apr 13, 2022)

    Peko 2.2.0 What is new:

    • updated Kotlin to v1.5.30
    • updated Coroutines to v.1.5.2
    • added areGranted method to check if permissions are granted
    • fix #17 Application Context can now be used to check for permissions
    • fix #18 Android version before M now properly returns all permissions as granted
    Source code(tar.gz)
    Source code(zip)
  • v2.1.4(Sep 14, 2021)

  • v2.1.3(May 23, 2021)

  • v2.1.2(Oct 14, 2020)

    Release 2.1.2


    • don't leak internal libraries outside, ie. use implementation instead of api
    • suspend fun requestPermissionsAsync method now requires Context instead of Activity
    • update to Kotlin v.1.4.0 and Coroutines v.1.3.9
    Source code(tar.gz)
    Source code(zip)
Owner
Marko Devcic
Software developer by day. By night, also a software developer. Author of Kotlin Quick Start Guide by Packt Publishing
Marko Devcic
Android To-Do MVVM Architecture App written in Kotlin.(ViewModel, ROOM, Livedata, Coroutines)

MVVM-To-Do-App A To-Do application written in kotlin using Android Architectural components What's new? Room + Coroutines - Upgraded Room to v2.1. Roo

Naveen T P 77 Dec 8, 2022
Anime quotes rest api app with mvvm, LiveData, Coroutines, Navigation Component etc

AnimeQuote Anime quotes image rest api app with mvvm, LiveData, Coroutines, Navigation Component, clean achitecture etc An app created during mentorin

Ehma Ugbogo 4 Jun 11, 2021
Marvel Super Heroes | MVVM | Coroutines | DaggerHilt | LiveData

As an iOS developer, I'm learning Android and Kotlin trying to apply best practices, so I've started the same iOS project based on MARVEL, but now for ANDROID!

Míchel Marqués 2 Jun 4, 2022
A minimal notes application in Jetpack Compose with MVVM architecture. Built with components like DataStore, Coroutines, ViewModel, LiveData, Room, Navigation-Compose, Coil, koin etc.

Paper - A Minimal Notes App A minimal notes application in Jetpack Compose with MVVM architecture. Built with components like DataStore, Coroutines, V

Akshay Sharma 139 Jan 2, 2023
🔓 Kotlin version of the popular google/easypermissions wrapper library to simplify basic system permissions logic on Android M or higher.

EasyPermissions-ktx Kotlin version of the popular googlesample/easypermissions wrapper library to simplify basic system permissions logic on Android M

Madalin Valceleanu 326 Dec 23, 2022
Recycler-coroutines - RecyclerView Auto Add Data Using Coroutines

Sample RecyclerView Auto Add With Coroutine Colaborator Very open to anyone, I'l

Faisal Amir 8 Dec 1, 2022
ViewModel e LiveData - Android Studio - Kotlin

Unscramble App Starter code for Android Basics codelab - Store the data in a ViewModel Unscramble is a single player game app that displays scrambled

Ademir Oliveira 1 Nov 23, 2021
[Android-Kotlin] MVVM, ViewModel, LiveData, Observer, DataBinding, Repository, Retrofit, Dagger example

SimpleMvvmDaggerKotlin [Android-Kotlin] MVVM, ViewModel, LiveData, Observer, DataBinding, Repository, Retrofit, Dagger example [Image1 : User informat

DONGGEUN JUNG 2 Oct 24, 2022
Sample app that implements MVVM architecture using Kotlin, ViewModel, LiveData, and etc.

TheShard is a project to showcase different architectural approaches to developing Android apps. In its different branches you will find the same app (A movie Listing and detail page) implemented with small differences.

null 17 Aug 19, 2021
Wrapper of FusedLocationProviderClient for Android to support modern usage like LiveData and Flow

FancyLocationProvider Wrapper of FusedLocationProviderClient for Android to support modern usage like LiveData or Flow. Install Add Jitpack repository

Jintin 66 Aug 15, 2022
Android Clean Architechture with MVVM, LiveData, Coroutine, Dagger Hilt, Room, DataStore

MovKu An application that displays a list of popular movies and detail Concepts Tech Stack Kotlin -A modern programming language that makes developers

ꦤꦤꦁ​​ꦲꦫꦶꦥ꦳ꦸꦢꦶꦤ꧀ 3 Jul 29, 2022
LiveData 数据倒灌:别问,问就是不可预期 - Perfect alternative to SingleLiveEvent, supporting multiple observers.

前言 大家好,我是《Jetpack MVVM Best Practice》作者 KunMinX。 今天提到的 “数据倒灌” 一词,缘于我为了方便理解和记忆 “页面在 ‘二进宫’ 时收到旧数据推送” 的情况,而在 2019 年 自创并在网上传播的 关于此类现象的概括。 它主要发生在:通过 Shared

KunMinX 924 Jan 5, 2023
Basic app to use different type of observables StateFlow, Flow, SharedFlow, LiveData, State, Channel...

stateflow-flow-sharedflow-livedata Basic app to use different type of observables StateFlow, Flow, SharedFlow, LiveData, State, Channel... StateFlow,

Raheem 5 Dec 21, 2022
ViewModel ve DataBindig ile LiveData kullanım örneği.

#Android Kotlin ViewModel ve Livedata Görsel Kaynak: https://www.youtube.com/watch?v=suC0OM5gGAA Temiz kod mantığı ve bu mantık doğrultusunda geliştir

Murat YÜKSEKTEPE 0 Nov 20, 2021
Realize EventBus with LiveData

LiveDataBus 增強UnPeek-LiveData,將其包裝成觀察者模式的事件總線 Getting started Add it in your root build.gradle at the end of repositories: allprojects { repositor

JaredDoge 2 Oct 25, 2022
A Kotlin Android library for content provider queries with reactive streams and coroutines.

Pickpocket An Android library for content provider queries with reactive streams and coroutines. Calendar Contacts SMS MMS Files/Media Call Log Bookma

Chris Basinger 27 Nov 14, 2022
Library to use Kotlin Coroutines from Swift code in KMP apps

KMP-NativeCoroutines A library to use Kotlin Coroutines from Swift code in KMP apps. Flows Kotlin Create an extension property to expose the Flow as a

Rick Clephas 508 Jan 3, 2023
Server Sent Events (SSE) client multiplatform library made with Kotlin and backed by coroutines

OkSSE OkSSE is an client for Server Sent events protocol written in Kotlin Multiplatform. The implementation is written according to W3C Recommendatio

BioWink GmbH 39 Nov 4, 2022
A tiny Kotlin multiplatform library that assists in saving and restoring objects to and from disk using kotlinx.coroutines, kotlinx.serialisation and okio

Store A tiny Kotlin multiplatform library that assists in saving and restoring objects to and from disk using kotlinx.coroutines, kotlinx.serialisatio

Isuru Rajapakse 98 Jan 3, 2023