How to create scheduled notification without opening the app?
I already made one but it only fires the alarm when the app is opened.
Try using work manager
You could do something like this:
class NotificationWorker(context: Context,
params: WorkerParameters
) : Worker(context, params) {
override fun doWork(): Result {
//Trigger your notification here
return Result.success()
}
}
class App: Application(){
override fun onCreate() {
super.onCreate()
val work = PeriodicWorkRequestBuilder<NotificationWorker>(15, TimeUnit.MINUTES)
.build()
val workManager = WorkManager.getInstance(this)
workManager.enqueueUniquePeriodicWork(
NotificationWorker::class.java.simpleName,
ExistingPeriodicWorkPolicy.REPLACE,
work
)
}
}
Related
I create link from Campaign Builder and remove ad network
and I try this code, but nothing appears on my play console. And some issue occurs about SDK 31 or above
/////////////////////
Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
/////////////////////
but function just use intent not pendingintent
referrerClient.startConnection(object : InstallReferrerStateListener {
override fun onInstallReferrerSetupFinished(responseCode: Int) {
when (responseCode) {
InstallReferrerResponse.OK -> {
val response: ReferrerDetails? = try {
referrerClient.installReferrer
} catch (e: RemoteException) {
e.printStackTrace()
return
}
val referrerUrl = response?.installReferrer
trackInstallReferrer(referrerUrl)
referrerClient.endConnection()
}
InstallReferrerResponse.FEATURE_NOT_SUPPORTED -> {
}
InstallReferrerResponse.SERVICE_UNAVAILABLE -> {
}
}
}
override fun onInstallReferrerServiceDisconnected() {}
})
private fun trackInstallReferrer(referrerUrl: String) {
Handler(mainLooper).post {
val receiver = CampaignTrackingReceiver()
val intent = Intent("com.android.vending.INSTALL_REFERRER")
intent.putExtra("referrer", referrerUrl)
receiver.onReceive(applicationContext, intent)
}
}
What is wrong with my function or do you have any idea to give me?
and how long this tracking will show in my play console?
there is no clear Documentation for playing audio
assets files with the latest Exoplayer
wanted to play multiple audio files simultaneously
and in loop
like Soft Sound
what is the correct way to omit deprecated classes of exoplayer and play audio
build.gradle
// ExoPlayer
api "com.google.android.exoplayer:exoplayer-core:2.18.1"
my
PlayerService.kt file
class PlayerService : Service() {
private val notificationID = 132
private val tag = "Player"
// called when sound is started or stopped
var playerChangeListener: (() -> Unit)? = null
inner class PlayerBinder : Binder() {
fun getService(): PlayerService {
return this#PlayerService
}
}
private val playerBinder = PlayerBinder()
override fun onCreate() {
// load each player into the map
Sound.values().forEach {
exoPlayers[it] = initializeExoPlayer(it.file)
}
}
enum class Sound(val file: String) {
RAIN("rain_sound.ogg"),
...
TABLA("tabla_sound.ogg")
}
private val exoPlayers = mutableMapOf<Sound, ExoPlayer>()
private fun initializeExoPlayer(soundFile: String): ExoPlayer {
// create the player
val trackSelector = DefaultTrackSelector(this)
val exoPlayer = ExoPlayer.Builder(this).setTrackSelector(trackSelector).build()
// load the media source
val dataSource = DefaultDataSourceFactory(this,
Util.getUserAgent(this, this.getString(R.string.app_name)))
val mediaSource = ProgressiveMediaSource.Factory(dataSource)
.createMediaSource(MediaItem.fromUri(Uri.parse("asset:///$soundFile")))
// load the media
Log.d("MAIN", "loading $soundFile")
exoPlayer.setMediaSource(mediaSource)
exoPlayer.prepare()
exoPlayer.play()
// loop indefinitely
exoPlayer.repeatMode = Player.REPEAT_MODE_ALL
return exoPlayer
}
override fun onUnbind(intent: Intent?): Boolean {
// don't continue if we're not playing any sound and the main activity exits
playerChangeListener = null
if (!isPlaying()) {
stopSelf()
Log.d(tag, "stopping service")
}
return super.onUnbind(intent)
}
override fun onBind(intent: Intent?): IBinder {
// return the binding interface
return playerBinder
}
fun startForeground() {
// move to the foreground if we are playing sound
if (isPlaying()) {
....
}
}
fun stopForeground(){...}
fun stopPlaying(){...}
fun isPlaying(): Boolean{...}
fun setVolume(sound: Sound, volume: Float){...}
fun toggleSound(sound: Sound){...}
}
Any help would be highly appreciated.
This question already has answers here:
Android - implementing startForeground for a service?
(11 answers)
Closed 11 months ago.
I've createde a simple app (following this link How to Play Sound On Button Click in Android Studio Java 2021 ), and everything works fine, but, i need this app can still playing the sound after minimize then or block the phone (is a white noise app from help on sleep for my baby daughter, and i need that keep playing all night).
Is there any way or setting that allows the sound not to stop after minimizing or blocking the application?
Thank you for enveryone that could help me and my baby :)
If you add the ability to run your application in the background, it will solve your problem. Resources you can review:
https://developer.android.com/guide/components/services
https://developer.android.com/guide/background/threading
Basic Example :
AndroidManifest.xml :
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
*
*
*
*
<service android:name=".ui.main.AudioPlayerService"/>
</application>
AudioPlayerService :
private const val PLAYBACK_CHANNEL_ID = "blabla"
private const val PLAYBACK_NOTIFICATION_ID = 1
class AudioPlayerService : Service() {
private var player: SimpleExoPlayer? = null
private var playerNotificationManager: PlayerNotificationManager? = null
private val mediaItem: MediaItem = MediaItem.fromUri(ApiInterface.Channel24LiveURL)
/** Classes to be connected to the service with the
service
*reference providing the link between
*/
private val mBinder = AudioServiceBinder()
/**
* Data that the service will share to other classes. */
inner class AudioServiceBinder : Binder() {
val service
get() = this#AudioPlayerService
val player
get() = this#AudioPlayerService.player
}
override fun onBind(intent: Intent?): IBinder? {
return mBinder
}
/**
* Service start part
*/
override fun onCreate() {
super.onCreate()
// init player
player = SimpleExoPlayer.Builder(this)
.build().apply {
setMediaItem(mediaItem)
playWhenReady = true
prepare()
}
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
applicationContext,
PLAYBACK_CHANNEL_ID,
R.string.playback_channel_name,
R.string.playback_channel_desc,
PLAYBACK_NOTIFICATION_ID,
object : PlayerNotificationManager.MediaDescriptionAdapter {
override fun getCurrentContentTitle(player: Player): CharSequence {
return getString(R.string.def_playback_title)
}
override fun createCurrentContentIntent(player: Player): PendingIntent? {
return PendingIntent.getActivity(
applicationContext,
0,
Intent(applicationContext, MainActivity::class.java),
PendingIntent.FLAG_CANCEL_CURRENT
)
}
override fun getCurrentContentText(player: Player): CharSequence? {
return null
}
override fun getCurrentLargeIcon(
player: Player,
callback: PlayerNotificationManager.BitmapCallback
): Bitmap? {
return getBitmapFromVectorDrawable(applicationContext, R.mipmap.ic_launcher)
}
}, object : PlayerNotificationManager.NotificationListener {
override fun onNotificationCancelled(notificationId: Int, dismissedByUser: Boolean) {
stopSelf()
}
override fun onNotificationPosted(notificationId: Int, notification: Notification, ongoing: Boolean) {
if (ongoing) {
// Make sure the service will not get destroyed while playing media.
startForeground(notificationId, notification)
} else {
// Make notification cancellable.
stopForeground(false)
}
}
}
).apply {
// previous and next actions.
setUseNavigationActions(true)
setPlayer(player)
}
}
#MainThread
private fun getBitmapFromVectorDrawable(
context: Context,
#Suppress("SameParameterValue") #DrawableRes drawableId: Int
): Bitmap? {
return ContextCompat.getDrawable(context, drawableId)?.let {
val drawable = DrawableCompat.wrap(it).mutate()
val bitmap = Bitmap.createBitmap(
drawable.intrinsicWidth,
drawable.intrinsicHeight,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
bitmap
}
}
#MainThread
fun changePlayerVolume(view: ImageView) {
player?.let {
if (it.volume == 1.0f) {
it.volume = 0.0f
view.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_volume_off))
} else {
it.volume = 1.0f
view.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_volume_up))
}
}
}
#MainThread
fun jumpLiveStream() {
player?.let {
it.setMediaItem(mediaItem)
it.playWhenReady = true
}
}
/**
* Triggered when the app is closed. */
override fun onTaskRemoved(rootIntent: Intent?) {// Stop the service when the user closes the application.l
releasePlayer()
stopSelf()
super.onTaskRemoved(rootIntent)
}
override fun onDestroy() {
releasePlayer()
stopSelf()
super.onDestroy()
}
/**
* delete player and playerNotificationManager */
private fun releasePlayer() {
player?.let {
it.release()
player = null
}
playerNotificationManager?.let {
it.setPlayer(null)
playerNotificationManager = null
}
}
}
Good luck!
I'm using a bluetooth printer SDK,
which has a call back interface method to be trigger on search completed.
fun method1(){
val callBack = HoinPrinterCallBack(callBack = fun (): Int{
//Triggered after search completed
return 0;
})
mHoinPrinter = HoinPrinter.getInstance(this, 1, callBack)
}
Callback interface implementation
typealias CallBack = () -> Int
class HoinPrinterCallBack () : PrinterCallback {
override fun onEvent(p0: PrinterEvent?) {
print(p0)
if(p0?.event == Constant.EVENT_FIND_BT_DEVICE || p0?.event == Constant.EVENT_DISCOVERY_BT_FINISHED){
callBack()
}
}
}
}
I pass a callBack method to be triggered on search completed event in above code.
Then there is a separate method API for search of bluetooth device.
fun methhod2(){
mHoinPrinter.startBtDiscovery();
}
My requirement is to wait for the completed event callback after startBTDiscovery. Any suggestions on how I can proceed further?
I need to develop an app which monitors a list of apps and, if the system is rebooted, return to the last open page of the monitored apps. So, say that android was on the youtube app playing lofi hip hop radio - beats to relax/study to. How could my app send android back to this given video? Also, is there a way for me to know where in the app the user is? For example, can I know that the user was on youtube playing lofi and open it back again for them?
I already know how to open another app as well as detect whichever app is currently open, but I need to know the its uri as well. I can use adb and shell script if it is needed.
I have the following code to launch another app:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val intent = Intent(this, BackAppListenerService::class.java)
startService(intent)
openApp(this, "com.google.android.youtube")
}
/** Open another app.
* #param context current Context, like Activity, App, or Service
* #param packageName the full package name of the app to open
* #return true if likely successful, false if unsuccessful
*/
fun openApp(context: Context, packageName: String?): Boolean {
val manager = context.packageManager
return try {
val i = manager.getLaunchIntentForPackage(packageName!!)
if (i == null) {
println("Activity not found")
return false;
//throw new ActivityNotFoundException();
}
//throw new ActivityNotFoundException();
i.addCategory(Intent.CATEGORY_LAUNCHER)
context.startActivity(i)
true
} catch (e: ActivityNotFoundException) {
println(e)
false
}
}
}
And with this I get the current foreground app
class BackAppListenerService : Service() {
private var isRunning = false
private var lastApp = ""
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate() {
isRunning = true
Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
//Creating new thread for my service
//Always write your long running tasks in a separate thread, to avoid ANR
Thread(Runnable {
while (true) {
try {
Thread.sleep(10)
} catch (e: Exception) {
}
val currentForegroundApp = getForegroundApp()
val currentApp = currentForegroundApp.first
if (currentApp != lastApp) {
// New app on front
lastApp = currentApp
println("Current App $lastApp")
}
}
}).start()
return START_STICKY
}
// Must Have Usage Access Permission
fun getForegroundApp(): Pair<String, UsageStats> {
var currentApp = "NULL"
var currentAppInfo: UsageStats? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val usm = this.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
val time = System.currentTimeMillis()
val appList =
usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 1000, time)
if (appList != null && appList.size > 0) {
val mySortedMap: SortedMap<Long, UsageStats> =
TreeMap<Long, UsageStats>()
for (usageStats in appList) {
mySortedMap.put(usageStats.lastTimeUsed, usageStats)
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentAppInfo = mySortedMap[mySortedMap.lastKey()]!!
currentApp = mySortedMap[mySortedMap.lastKey()]!!.packageName
}
}
} else {
val am = this.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val tasks = am.runningAppProcesses
currentApp = tasks[0].processName
}
return Pair(currentApp.split(".").last(), currentAppInfo!!)
}
[...]
}
Any help is much appreciated.