Skip to content

Commit

Permalink
Request notification permission in Mirroring app
Browse files Browse the repository at this point in the history
  • Loading branch information
hufman committed Feb 22, 2024
1 parent 6e1263a commit cf6dac6
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 15 deletions.
2 changes: 1 addition & 1 deletion screen_mirror/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ android {
applicationId "io.bimmergestalt.idriveconnectaddons.screenmirror"
compileSdk 33
minSdkVersion 23
targetSdkVersion 30
targetSdkVersion 33
versionCode 1
versionName "1.0"

Expand Down
5 changes: 3 additions & 2 deletions screen_mirror/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<!-- Connect to local etch port -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Provide a foreground service to indicate mirroring status -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Read the car's screen size from AAIdrive -->
<uses-permission android:name="io.bimmergestalt.permission.CDS_normal" />
Expand All @@ -15,13 +16,13 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.IDriveConnectAddons">
<activity android:name=".MainActivity">
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity android:name=".RequestActivity" />
<service android:name=".CarAppService">
<service android:name=".CarAppService" android:exported="true">
<intent-filter>
<action android:name="io.bimmergestalt.carconnection.service" />
</intent-filter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ class MainActivity : AppCompatActivity() {
setContentView(binding.root)
}

override fun onResume() {
super.onResume()
viewModel.updatePermissions(this)
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,72 @@
package io.bimmergestalt.idriveconnectaddons.screenmirror

import android.content.Context
import android.Manifest
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.core.app.ActivityCompat

class MainController(val context: Context) {
fun promptPermission() {
val intent = Intent(context, RequestActivity::class.java)
context.startActivity(intent)
class MainController(val activity: Activity) {

companion object {
const val REQUEST_POST_NOTIFICATIONS = 60
}

private fun tryOpenActivity(intent: Intent): Boolean {
if (activity.packageManager.resolveActivity(intent, 0) != null) {
try {
activity.startActivity(intent)
return true
} catch (e: ActivityNotFoundException) {
} catch (e: IllegalArgumentException) {}
}
return false
}

fun openApplicationPermissions(packageName: String) {
run {
val intent = Intent("miui.intent.action.APP_PERM_EDITOR")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.setClassName("com.miui.securitycenter",
"com.miui.permcenter.permissions.PermissionsEditorActivity")
intent.putExtra("extra_pkgname", packageName)
if (tryOpenActivity(intent)) return
}
run {
val intent = Intent("miui.intent.action.APP_PERM_EDITOR")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
// try an implicit intent without a classname
intent.putExtra("extra_pkgname", packageName)
if (tryOpenActivity(intent)) return
}
run {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.data = Uri.fromParts("package", packageName, null)
if (tryOpenActivity(intent)) return
}
run {
val intent = Intent(Settings.ACTION_SETTINGS)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
if (tryOpenActivity(intent)) return
}
}

fun promptMirroringPermission() {
val intent = Intent(activity, RequestActivity::class.java)
activity.startActivity(intent)
}

fun promptPostNotificationsPermission() {
if (android.os.Build.VERSION.SDK_INT >= 33 && activity.applicationInfo.targetSdkVersion >= 33) { // Android 13+
ActivityCompat.requestPermissions(activity,
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
REQUEST_POST_NOTIFICATIONS)
} else {
openApplicationPermissions(activity.packageName)
}
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package io.bimmergestalt.idriveconnectaddons.screenmirror

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import io.bimmergestalt.idriveconnectaddons.lib.LiveDataHelpers.map

class MainModel: ViewModel() {
val notificationPermission = MutableLiveData(false)
val mirroringState = ScreenMirrorProvider.state
val mirroringStateText: LiveData<Context.() -> String> = ScreenMirrorProvider.state.map({getString(R.string.lbl_status_not_ready)}) {
when (it) {
Expand All @@ -23,4 +28,9 @@ class MainModel: ViewModel() {
}
}
}

fun updatePermissions(context: Context) {
notificationPermission.value = Build.VERSION.SDK_INT < 33
|| context.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ class NotificationService: Service() {
// or an in-app request to tap to open the prompt for recording permission
if (ScreenMirrorProvider.state.value == MirroringState.NOT_ALLOWED) {
notificationBuilder
.setContentText(getText(R.string.btn_grant_auth))
.setContentIntent(PendingIntent.getActivity(applicationContext, 0, requestActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT))
.setContentText(getText(R.string.btn_grant_mirror_auth))
.setContentIntent(PendingIntent.getActivity(applicationContext, 0, requestActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE))
if (!foreground) {
// a background request to tap and start the grant flow
@Suppress("DEPRECATION")
Expand All @@ -145,7 +145,7 @@ class NotificationService: Service() {
if (ScreenMirrorProvider.state.value == MirroringState.WAITING) {
notificationBuilder
.setContentTitle(getText(R.string.lbl_status_waiting))
.setContentIntent(PendingIntent.getActivity(applicationContext, 0, mainActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT))
.setContentIntent(PendingIntent.getActivity(applicationContext, 0, mainActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE))

if (!IDriveConnectionStatus.isConnected) {
notificationBuilder
Expand All @@ -156,7 +156,7 @@ class NotificationService: Service() {
if (ScreenMirrorProvider.state.value == MirroringState.ACTIVE) {
notificationBuilder
.setContentTitle(getText(R.string.lbl_status_active))
.setContentIntent(PendingIntent.getActivity(applicationContext, 0, mainActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT))
.setContentIntent(PendingIntent.getActivity(applicationContext, 0, mainActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE))
}

val notification = notificationBuilder.build()
Expand Down
28 changes: 26 additions & 2 deletions screen_mirror/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,37 @@
android:text="@{viewModel.mirroringStateText}" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:orientation="vertical"
android:visibility="@{!viewModel.notificationPermission}"
>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="6dp"
android:paddingEnd="6dp"
android:text="@string/lbl_notification_auth" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:onClick="@{() -> controller.promptPostNotificationsPermission()}"
android:text="@string/btn_grant_notification_auth"/>

</LinearLayout>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:onClick="@{() -> controller.promptPermission()}"
android:onClick="@{() -> controller.promptMirroringPermission()}"
android:visibility="@{viewModel.mirroringState == MirroringState.NOT_ALLOWED}"
android:text="@string/btn_grant_auth"/>
android:text="@string/btn_grant_mirror_auth"/>

<TextView
android:layout_width="wrap_content"
Expand Down
4 changes: 3 additions & 1 deletion screen_mirror/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
<string name="lbl_status_not_allowed">Screen mirroring permission needed</string>
<string name="lbl_status_waiting">Screen mirroring ready</string>
<string name="lbl_status_active">Screen mirroring active</string>
<string name="btn_grant_auth">Grant permission</string>
<string name="btn_grant_mirror_auth">Grant mirroring permission</string>
<string name="btn_grant_notification_auth">Grant notification permission</string>
<string name="lbl_notification_auth">Prompt for mirroring permission as needed:</string>
<string name="lbl_status_autoclose">Automatically times out if the car isn\'t connected within a minute</string>
<string name="lbl_open_car">Next, open the app in the car</string>
<string name="lbl_status">Status:</string>
Expand Down

0 comments on commit cf6dac6

Please sign in to comment.