I'm using notifications with fullscreen my code works find in Oreo and below version
But when i'm running android-Q I'm getting below exception
Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission
I'm using setFullScreenIntent() for notifications with fullscreen
Here is my code
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "123");
notificationBuilder.setAutoCancel(true)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setContentTitle(getString(R.string.app_name))
.setContentText("Test")
.setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setFullScreenIntent(pendingIntent,true)
.setSmallIcon(R.drawable.ic_launcher_background)
.setAutoCancel(true);
mNotificationManager.notify(1000, notificationBuilder.build());
Here is the answer
Now wee need to add <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> permission in manifest file
Permissions changes for fullscreen intents
Apps that target Android Q or higher and use notifications with fullscreen intents must request the USE_FULL_SCREEN_INTENT permission in their app's manifest file. This is a normal permission, so the system automatically grants it to the requesting app
SAMPLE CODE
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxx.xxx.xxx">
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
setFullScreenIntent
An intent to launch instead of posting the notification to the status bar. Only for use with extremely high-priority notifications demanding the user's immediate attention, such as an incoming phone call or alarm clock that the user has explicitly set to a particular time. If this facility is used for something else, please give the user an option to turn it off and use a normal notification, as this can be extremely disruptive.
https://developer.android.com/reference/android/app/Notification.Builder
Related
I am working on an Android application in which I want to open fullScreenPendingIntent from the notification when app is in the background (user press HOME button). It is an application which will not be uploaded to Google Store and has granted permissions for android.permission.USE_FULL_SCREEN_INTENT, android.permission.SYSTEM_ALERT_WINDOW, android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, android.permission.FOREGROUND_SERVICE, android.permission.POST_NOTIFICATIONS for Android 13 and more.
Part of the code from manifest
# just Splash activity on start and for permissions
<activity
android:name=".ui.splash.SplashActivity"
android:hardwareAccelerated="true"
android:screenOrientation="portrait"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
# Main Activity
<activity
android:name=".MainActivity"
android:hardwareAccelerated="true"
android:screenOrientation="portrait"
android:launchMode="singleInstance"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
# Activity for call when app in background
<activity
android:name=".ui.activity.call.CallFromBackground"
android:screenOrientation="portrait"
android:launchMode="singleTop"
android:noHistory="true"/>
When the call is received from the core service (.so lib) I trigger Broadcast message and receiver is defined in MainActivity. In the next steps notification is created with contentPendingIntent, fullScreenPendingIntent and an Action.
val notificationBuilder = NotificationCompat.Builder(context, CALL_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("$callWay - $callState - ${sessionState.callName}")
.setAutoCancel(false)
.setOngoing(true)
.setSilent(callNotificationAdditionalData.silent)
.setContentIntent(contentIntent)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_CALL)
if (callNotificationAdditionalData.fullScreenPendingIntent != null) {
notificationBuilder.setFullScreenIntent(callNotificationAdditionalData.fullScreenPendingIntent, true)
}
if (callNotificationAdditionalData.answerActionPendingIntent != null) {
notificationBuilder.addAction(NotificationCompat.Action(null, context.getString(R.string.msg_answer), callNotificationAdditionalData.answerActionPendingIntent))
}
if (callNotificationAdditionalData.includeDeclinePendingIntent) {
notificationBuilder.addAction(NotificationCompat.Action(null, context.getString(R.string.msg_decline), declineIntent(context, sessionId)))
}
val channel = NotificationChannel(
CALL_CHANNEL_ID, context.getString(R.string.msg_call_in_progress), NotificationManager.IMPORTANCE_HIGH
).apply {
lockscreenVisibility = Notification.VISIBILITY_PUBLIC
}
val notificationManagerCompat = NotificationManagerCompat.from(context)
notificationManagerCompat.createNotificationChannel(channel)
notificationManagerCompat.notify(sessionId, notificationBuilder.build())
Such notification on Android 10 is displayed and fullScreenPendingIntent (android:name=".ui.activity.call.CallFromBackground") is shown.
In Android 13 only notification is displayed and fullScreenPendingIntent does not appear. If I click on notification, contentPendingIntent is displayed (this is ok).
I tried a lot of stuff and my workaroud is not nice. For now if running version is Android 13 I manually (before notification is created) start MainActivity (with flags Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT - have no idea if this is needed) and then CallFromBackground activity.
val mainActivityToFront = Intent(context, MainActivity::class.java)
mainActivityToFront.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
context.startActivity(mainActivityToFront)
context.startActivity(!! Intent which is also used in fullScreenPendingIntent !!)
Is there a solution for this problem or it is not possible to fix this?
Maybe my architecture is completely wrong and I have to start foreground service for each call (multiple parallel calls are possible). Can foreground notification open fullScreenPendingIntent? There are also limitations when the app can start the foreground service. I already have one and it used for GPS locations.
I am new to learning flutter. My flutter app has a native android background service on kotlin where I have a socket running and whenever the socket listens to something I generate a notification using NotificationCompat.Builder.
But I am unable to bring the Flutter app back to foreground when ever the user taps on the notification.
I have tried creating a pendingintent and passing it to notificationbuilder setContentIntent() but nothing happens on tap.
shownotification function on Native background service:
fun shownotification (){
packageNamer = this.getPackageName()
launchIntent = this.getPackageManager().getLaunchIntentForPackage(packageName)
var className = launchIntent?.getComponent()!!.className.javaClass
intent.action = "SELECT_NOTIFICATION"
intent.setClass(this,className)
pendingIntent = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT)
var builder = NotificationCompat.Builder(this, "notifications")
.setOngoing(true)
.setContentIntent(pendingIntent)
.setFullScreenIntent(pendingIntent, true)
.setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
.setContentTitle("My notification")
.setContentText("Much longer text that cannot fit one line...")
.setStyle(NotificationCompat.BigTextStyle()
.bigText("Much longer text that cannot fit one line..."))
.setPriority(NotificationCompat.PRIORITY_HIGH)
manager?.notify(456,builder.build())
}
AndroidManifest.xml file:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name=".MyApplication"
android:label="bizzyb_demo"
android:icon="#mipmap/ic_launcher">
<service android:name=".MyService" android:exported="true" android:enabled="true"/>
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in #style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
What am I doing wrong here. I believe I am missing something very obvious here as I am new to mobile apps development.
Your expert feedbacks will be appreciated.
Thanks
You need to include click_action: FLUTTER_NOTIFICATION_CLICK as a "Custom data" key-value-pair in the notification payload.
Bundle bundle = new Bundle();
bundle.putString(Constants.EXAM_ID,String.valueOf(lectureDownloadStatus.getExamId()));
var builder = NotificationCompat.Builder(this, "notifications")
.setOngoing(true)
.setContentIntent(pendingIntent)
.setFullScreenIntent(pendingIntent, true)
.setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
.setContentTitle("My notification")
.setContentText("Much longer text that cannot fit one line...")
.setStyle(NotificationCompat.BigTextStyle()
.bigText("Much longer text that cannot fit one line..."))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setExtras(bundle) // Set the bundle
I have developed an Android application that allows the user to change some system settings. Once the user has configured the application, there is no reason to launch it anymore. That's why many users have asked me to add an option to hide the application from the launcher.
I tested the solution of this post.
I hide the application this way:
PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class); // activity which is first time open in manifiest file which is declare as <category android:name="android.intent.category.LAUNCHER" />
p.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
I unhide the application this way:
PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class);
p.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
It works very well... as long as I don't add permission to my application.
For example, I use the following permission:
<uses-permission android:name="android.permission.SET_WALLPAPER" />
And when I add this permission to the Manifest, the application does not disappear from the launcher. And, when I click on it it starts the Settings application on my application page, as shown in the following gif:
Here is my Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cannic.apps.hideapptest">
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
So my question is the following: Is there a way to hide an application from the launcher when the application asks permissions?
I'm not sure if "officially not supported" is an answer or not. But unfortunately, according to docs:
As of Android Q, at least one of the app's activities or synthesized
activities appears in the returned list unless the app satisfies at
least one of the following conditions:
The app is a system app.
The app doesn't request any permissions.
The tag in the app's manifest doesn't contain any child elements that represent app components.
Additionally, the system hides synthesized activities for some or all
apps in the following enterprise-related cases:
If the device is a fully managed device, no synthesized activities for any app appear in the returned list.
If the current user has a work profile, no synthesized activities for the user's work apps appear in the returned list.
FCM notifications are not working in Android latest version OREO.
Below is my code:
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example">
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#mipmap/luncher_logo"
android:label="#string/app_name"
android:roundIcon="#mipmap/luncher_logo"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".WelcomeActivity">
<intent-filter>
<action android:name="com.example.action.MAIN" />
<category android:name="com.example.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity" />
<service android:name=".firebase.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".firebase.FirebaseIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
</manifest>
In Android Oreo making channel is important,When yo create notification you must pass the channel id,or your notification won't show up in Oreo devices.
more information
quick fix is:
use setChannelId method in notification class.
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notif_icon)
.setContentTitle("testTitle")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setChannelId("testChannelId") // set channel id
.setContentIntent(pendingIntent);
complete answer in this link.
From Android 8.0 (API level 26+), notification channels are supported and recommended.
FCM provides a default notification channel with basic settings.
If you prefer to create and use your own default channel, set default_notification_channel_id to the ID of your notification channel object as shown below.
FCM will use this value whenever incoming messages do not explicitly set a notification channel.
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/default_notification_channel_id"/>
You can create channel id from this link
You need to create channels in order to display a notification in Oreo.
If you use default firebase notifications, you can add channel_id in manifest.
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/default_notification_channel_id"/>
If you create notifications manually, then you need to create channel programmatically. More details on official documentation.
I am starting a service class from my mainActivity like this:
Intent io = new Intent(MainActivity.this, Window.class);
startService(io);
It works perfectly on most of all devices but in some lenovo devices when I remove my app from background task the service is also destroyed with activity.I have tried Sticky service but it didn't worked.This type of issue is appearing on lenovo like devices only, on all most of other devices the service is not destroyed with activity and it is working fine.Can anyone help me to solve why is this happening.
I have also tried in this way but didn't worked out:
Intent io = new Intent(MainActivity.this, Window.class);
getBaseContext.startService(io);
My Manifest:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".Boot" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<service
android:name=".Capture"
android:label="#string/service_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.access"
android:resource="#xml/access" />
</service>
<activity android:name=".Faq"
android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen"
android:launchMode="singleInstance"/>
<service android:name=".Window"/>
<activity android:name=".Intro1"
android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen"/>
<activity android:name=".Intro2"
android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen"/>
<activity android:name=".Intro3"
android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen"/>
<activity android:name=".Permit"
android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen"/>
</application>
Had this problem too.
Most of Lenovo, Xiaomi, Asus, etc phones has Security system application in firmware which can block services. You should check it and unlock blocking of your app`s autostart if needed.
By default its turned off.
Also some BroadcastReceiver functions (like receiving of SMS) cannot work because of it even if you give required permission.
Worst thing is that you can`t check it programatically.
You can run your service in a separate process. Add the following attribute to the service declaration in the AndroidManifest
android:process=":any-name-for-process"
You might want to take a look at this :
How to keep a service running in background even after user quits the app?
and developer.android.com :
Running a Service in the Foreground
A foreground service is a service that's considered to be something the user is actively aware of and thus not a candidate for the system to kill when low on memory. A foreground service must provide a notification for the status bar, which is placed under the "Ongoing" heading, which means that the notification cannot be dismissed unless the service is either stopped or removed from the foreground.
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
Also, you can try to add to your onDestroy() function, a alarm that will restart the service after a few seconds since when it was destroyed.