How to open app after installing manually - android

Installing App Manually
val install = Intent(Intent.ACTION_VIEW)
install.setDataAndType(
uri,
APP_INSTALL_PATH
)
// install.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
install.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
}
startActivity(install)
Handling Broadcast Receiver
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED)
intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
intentFilter.addAction(Intent.ACTION_PACKAGE_INSTALL)
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED)
intentFilter.addAction(Intent.ACTION_MY_PACKAGE_REPLACED)
intentFilter.addDataScheme("package")
registerReceiver(restartAppReceiver, intentFilter)
private val restartAppReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Toast.makeText(this#LoginActivity, getString(R.string.sign_out), Toast.LENGTH_LONG)
.show()
//start activity
val i = Intent()
Log.i("App_started", "Yes")
i.setClassName(packageName, packageName+".screen.activity.LoginActivity")
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context?.startActivity(i)
}
}
Problem Facing
Here I'm not able to receive anything on receiver when app gets installed manually. I need to open the app automatically when it gets installed manually without any action from users end.

thats simple: you can't. user must open it manually. starting Android 10 you can't start any Activity from BroadcastReceiver. besides that: most of your IntentFilter entries are no-op (why are you calling addDataScheme)

Related

How to make socket io work in the background android

I have socket IO connected to an android app and it's receiving events via background services. while this is working fine when the app is in foreground. When I close the app or when app goes in background I have confirmed that the sockets are connected but I'm not able to receive events when app is in background.
This is my service
const val SOCKET_EVENT = "message:response"
#AndroidEntryPoint
class MService : LifecycleService() {
#Inject
lateinit var ioSocket: Socket
override fun onCreate() {
super.onCreate()
ioSocket.connect()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
ioSocket.connect()
AndroidRemoteDebugger.Log.d("Starting My Service")
listenToSocketsEvents()
return START_STICKY
}
private fun listenToSocketsEvents() {
ioSocket.on(SOCKET_EVENT, onSocketEvent)
}
private val onSocketEvent: Emitter.Listener = object : Emitter.Listener {
override fun call(vararg args: Any?) {
try {
val data = args[0] as JSONObject
//While the main thing about the service is that I'm logging data jhere when I get an
// incoming socket event it does log when app is in foreground but when it's in
// background it doesn't log
AndroidRemoteDebugger.Log.v(data.toString())
val message = data.getJSONObject("message")
val id = message.getString("id")
playSound()
val topic = "message-request"
val intent = Intent(
this#MService,
MessageReceiver::class.java
).apply {
putExtra("messageId", id)
putExtra("topic", topic)
}
sendBroadcast(intent)
} catch (e: JSONException) {
AndroidRemoteDebugger.Log.e(e.message)
return
}
}
}
private fun playSound() {
val notificationSound: Uri =
Uri.parse(
(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
packageName) + "/" + R.raw.car_horn
)
val ringtone: Ringtone = RingtoneManager.getRingtone(
applicationContext,
notificationSound
)
ringtone.play()
}
}
This is my receiver
class MessageReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val topic = intent?.getStringExtra("topic")
val tripId = intent?.getStringExtra("tripId")
val intent = Intent(Constants.NOTIFICATION).apply {
putExtra("Notify", topic)
putExtra("tripId", tripId)
putExtra("from", Constants.SOCKETS)
}
if (context != null) {
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
}
}
}
While the main thing about the service is that I'm logging something when I get an incoming socket event it does log when app is in foreground but when it's in background it doesn't log
LifecycleService will be killed when the app goes in the background/killed.
You should use ForegroundService to run any background tasks.
From official doc
While an app is in the foreground, it can create and run both foreground and background services freely. When an app goes into the background, it has a window of several minutes in which it is still allowed to create and use services. At the end of that window, the app is considered to be idle. At this time, the system stops the app's background services, just as if the app had called the services' Service.stopSelf() methods.
Your sockets are still connected because you don't disconnect the socket when the service gets killed. Always disconnect the socket when you're done with the service to avoid unnecessary resource consumption.

Broadcast Receiver not receiving AlarmManager intents after restarting WearOS device

I am trying to reboot my device and relaunch my alarm following this https://developer.android.com/training/scheduling/alarms#boot.
But unfortunately only the BOOT_COMPLETED action is received. Other intents from Alarm is not received.
During on BOOT_COMPLETED . I schedule my task for the alarm once again.
I also have confirmed using the command below
adb shell dumpsys alarm
That I still have the alarm after rebooting. but the when the alarm fires Broadcast receiver does not receive it.
Does anyone have an idea what I might missing? Thank you.
NOTE: If I use the same code without restarting the device. The alarm will be received by the Broadcast receiver. Issue only happens if I restart.
Here is the code for the Playground App im testing it on.
MainActivity
class MainActivity : Activity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val receiver = ComponentName(applicationContext, BootReceiver::class.java)
applicationContext.packageManager.setComponentEnabledSetting(
receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
val prefs = getSharedPreferences("TEST_PREF", MODE_PRIVATE)
binding.text.text = "Hello!! " + prefs.getString("message", "No message defined") //"No name defined" is the default value.
Log.d("TESTER", "app loaded")
}
}
BroadcastReceiver
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if(context == null) return
if(intent == null) return
if (intent.action == "android.intent.action.BOOT_COMPLETED") {
// Set the alarm here.
ScheduleManager.scheduleAlarm(context, TEST_TIME)
Log.d("TESTER", "android.intent.action.BOOT_COMPLETED")
} else {
val message = intent.getStringExtra(MESSAGE_KEY)
val editor: SharedPreferences.Editor = context.applicationContext.getSharedPreferences("TEST_PREF", MODE_PRIVATE).edit()
editor.putString("message", message)
editor.apply()
Log.d("TESTER", "message from alarm received")
}
}
}
Alarm Manager
object ScheduleManager {
const val MESSAGE_KEY = "message"
const val TEST_TIME = 1647915300000L //2022-03-22 10:15:00
fun scheduleAlarm(context: Context, time: Long) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, BootReceiver::class.java)
intent.putExtra(MESSAGE_KEY, "This is from the alarm $time")
val pendingIntent = PendingIntent.getBroadcast(
context,
1111,
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
time,
pendingIntent
)
}
}
Log Results
Launched the app at 2022-03-22 10:11:17.414
2022-03-22 10:11:17.414 4360-4360/com.wearosplayground D/TESTER: app loaded
proceeds rebooting WearOs device
Boot complete action received at 2022-03-22 10:13:49.586
2022-03-22 10:13:49.586 3576-3576/com.ausom.wearosplayground D/TESTER: android.intent.action.BOOT_COMPLETED
I have set the alarm at this time to be at 2022-03-22 10:15:00
but nothing happens
const val TEST_TIME = 1647915300L //2022-03-22 10:15:00
Is specified as seconds.
You should change this to 1647915300000L
See
println(java.util.Date(1647915300L)) //Tue Jan 20 01:45:15 UTC 1970
Using this link as a reference, the solution using accessibility works.
BUT, this is not advisable as it accessibility is for disabled users. So for now the real solution I can think of is communicate with your WearOS device manufacturer and ask for whitelisting. Other than that we will need to continue resorting to tricks listed in the link I have shared.

Broadcast receiver added inside onCreate() of foreground service not working

Broadcast receiver class inside the service
inner class ServiceNotificationReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val action = intent!!.action
Util.log("action from foreground services")
when (action) {
FOREGROUND_NEXT -> {
next()
}
FOREGROUND_PREVIOUS -> {
prevoius()
}
FOREGROUND_PLAY_PAUSE -> {
if (exoPlayer.isPlaying) {
pause()
} else {
play()
}
}
FOREGROUND_STOP -> {
stopSelf()
}
}
}
}
I am registering it inside the onCreate() of the service like so
serviceNotificationListener = ServiceNotificationReceiver()
val intentfliter = IntentFilter().apply {
addAction(FOREGROUND_PLAY_PAUSE)
addAction(FOREGROUND_PREVIOUS)
addAction(FOREGROUND_NEXT)
addAction(FOREGROUND_STOP)
}
this.registerReceiver(serviceNotificationListener, intentfliter)
The pending intent
playintent = Intent(this, ServiceNotificationReceiver::class.java).setAction(
FOREGROUND_PLAY_PAUSE
)
playpendingIntent =
PendingIntent.getBroadcast(this, 0, playintent, PendingIntent.FLAG_UPDATE_CURRENT)
I am adding it as an action inside the notification builder like so
addAction(
com.google.android.exoplayer2.R.drawable.exo_icon_previous,
"Previous",
previouspendingIntent
)
However the clicks are not registering inside the service. I cannot add it in the manifest due to some complexity in the app and this is the only way. So what could be the issue. Is it the flags or something else.
You're setting your intent target component to yourpackage.YourService.ServiceNotificationReceiver which is not registered in manifest, system will not be able to resolve it and nothing is executed.
Modify your intent to target only your apps package then your receiver will be able to match it:
playintent = Intent().setPackage(this.packageName).setAction(FOREGROUND_PLAY_PAUSE)

Call activity method from BroadcastReceiver Class Kotlin

I'm a beginner to Android and Kotlin. Im developing an audio player with audio controls in notification. In my Audio activity I have public methods playAudio() and pauseAudio(). I need to call this method from a broadcast receiver as below
class AudioControlsInNotification : BroadcastReceiver() {
var audioMain: Audio? = null
fun setMainActivityHandler(main: Audio) {
audioMain = main
}
override fun onReceive(context: Context?, intent: Intent?) {
if (intent != null) {
when (intent.action) {
"PAUSEAUDIO" -> {
audioMain?.pauseAudio()
}
"PLAYAUDIO" -> {
audioMain?.playAudio()
}
}
}
}
audioMain always returns null.
While clicking Play and Pause button,
notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
mBuilder = NotificationCompat.Builder(applicationContext, "MYAUDIOCHANNEL")
contentView = RemoteViews(packageName, R.layout.audio_notification)
val notifyPauseIntent = Intent(this, AudioControlsInNotification::class.java).apply {
action = "PAUSEAUDIO"
}
val notifyPausePendingIntent: PendingIntent = PendingIntent.getBroadcast(this,0,notifyPauseIntent,0)
contentView!!.setOnClickPendingIntent(R.id.notifyPause, notifyPausePendingIntent)
val notifyPlayIntent = Intent(this, AudioControlsInNotification::class.java).apply {
action = "PLAYAUDIO"
}
val notifyPlayPendingIntent: PendingIntent = PendingIntent.getBroadcast(this,0,notifyPlayIntent,0)
contentView!!.setOnClickPendingIntent(R.id.notifyPlay, notifyPlayPendingIntent)
I received intent actions in the AudioControlsInNotification but i can't access the methods of Audio Activity. I tried many answers from stackoverflow but nothing helps me. I need this BroadcastReceiver on for this Audio activity only.
In my Audio activity I have public methods
That can only make sense if they are declared static in your activity class.
If they are not static then hat does not make sense as you have no pointer to your activity as activities cannot be created with the new operater but only using an intent.

requestActivityTransitionUpdates never calls the registered BroadcastReceiver

I am coding a simple app that measures all available sensors of the android device (Wifi, BT, etc). One of them is the user activity (via ActivityRecognition API), but I can't make it works properly.
I code a class to do everything related to user activity. I want to get only 4 states and one attribute to store the current one:
var VEHICLE = "vehicle"
var WALKING = "walking"
var STILL = "still"
var UNKNOWN = "unknown"
private var current: String? = null
It also includes a BroadcastReceiver object to handle activity transitions:
private var recognitionHandler = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (ActivityRecognitionResult.hasResult(intent)) {
val result = ActivityRecognitionResult.extractResult(intent)
val activity = result.mostProbableActivity
current = when(activity.type) {
DetectedActivity.IN_VEHICLE,
DetectedActivity.ON_BICYCLE -> VEHICLE
DetectedActivity.WALKING,
DetectedActivity.RUNNING -> WALKING
DetectedActivity.STILL -> STILL
else -> UNKNOWN
}
}
}
}
The class also have two methods to define the intent and request:
private fun createIntent() : PendingIntent {
val intent = Intent(context, recognitionHandler.javaClass)
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
context.registerReceiver(recognitionHandler, IntentFilter())
return pendingIntent
}
private fun createRequest() : ActivityTransitionRequest {
val types = listOf(
DetectedActivity.IN_VEHICLE,
DetectedActivity.WALKING,
DetectedActivity.RUNNING,
DetectedActivity.ON_BICYCLE,
DetectedActivity.STILL
)
val transitions = mutableListOf<ActivityTransition>()
types.forEach { activity ->
transitions.add(
ActivityTransition.Builder()
.setActivityType(activity)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build()
)
}
return ActivityTransitionRequest(transitions)
}
And also one to start listening:
override fun start(onResult: (res: String?) -> Unit) {
// ...
intent = createIntent()
val request = createRequest()
ActivityRecognition.getClient(context)
.requestActivityTransitionUpdates(request, intent)
.addOnSuccessListener {
Log.d("UserActivity Service info", "listening...")
}
.addOnFailureListener { e ->
Log.d("UserActivity Service error", e.toString())
}
// ...
}
The problem is that the current attribute is always null. I think I have some issues with intent or handler registration, but I have no idea where.
Does someone have any comments? :)
Thanks!
This is your problem. In this code from createIntent():
val intent = Intent(context, recognitionHandler.javaClass)
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
context.registerReceiver(recognitionHandler, IntentFilter())
return pendingIntent
You return a PendingIntent that you use in the call to requestActivityTransitionUpdates(). However, that PendingIntent refers to a dynamically created inner class (your BroadcastReceiver) and Android cannot instantiate that class.
You also additionally call registerReceiver(), however you pass an empty IntentFilter in that call so the registered BroadcastReceiver is never called.
To fix the problem, you can either provide a correctIntentFilter that matches your PendingIntent OR you can refactor your BroadcastReceiver into a proper class (not a private inner class) and make sure that you've added the BroadcastReceiver to your manifest and make it publicly available (exported="true").
Here's an example of how to do this using a BroadcastReceiver:
https://steemit.com/utopian-io/#betheleyo/implementing-android-s-new-activity-recognition-transition-api

Categories

Resources