How to stop running worker on android? - android

I created a worker that runs on connecting audio jack but I can't stop the running worker on audio jack disconnection which is triggered by Broadcast Receiver.
I want to keep track of headset usage limit with the help of worker which will only trigger when there is headset connection and will stop the worker whenever the audio jack/headset is detached.
Here is the Broadcast Reciver Code
package com.xanjit.focusly.broadcast_receivers
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.work.*
import com.xanjit.focusly.workers.GetHeadsetUsageTimeWorker
import java.sql.Timestamp
import java.time.Duration
class AudioInputBroadcastReceiver : BroadcastReceiver() {
// lateinit var workManager: WorkManager
// lateinit var workRequest: WorkRequest
#RequiresApi(Build.VERSION_CODES.O)
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = intent!!.getIntExtra("state", 0) === 1
val workManager = WorkManager.getInstance(context!!)
if (isConnected) {
var startTime = System.currentTimeMillis()
Toast.makeText(context,"Connected",Toast.LENGTH_SHORT).show()
val data = Data.Builder()
data.putLong("startTime", startTime)
val workRequest = OneTimeWorkRequest.Builder(
GetHeadsetUsageTimeWorker::class.java,
).setInputData(data.build())
.build()
workManager.enqueue(workRequest)
} else {
Toast.makeText(context,"Disconnected",Toast.LENGTH_SHORT).show()
// val data = Data.Builder()
//
// data.putBoolean("isStopped", true)
// val workRequest = OneTimeWorkRequest.Builder(
// GetHeadsetUsageTimeWorker::class.java,
// ).setInputData(data.build()).build()
workManager.cancelAllWork()
}
}
override fun peekService(myContext: Context?, service: Intent?): IBinder {
return super.peekService(myContext, service)
}
}
Worker Code
package com.xanjit.focusly.workers
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.graphics.BitmapFactory
import android.media.AudioAttributes
import android.net.Uri
import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.work.ListenableWorker
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.xanjit.focusly.R
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.sql.Timestamp
import kotlin.time.seconds
var TAG = "EarGuard"
class GetHeadsetUsageTimeWorker(context: Context, workerParams: WorkerParameters) : Worker(
context,
workerParams,
) {
#RequiresApi(Build.VERSION_CODES.O)
override fun doWork(): Result {
// Log.d("EarGuard", "StartTime Worker")
var startTime = inputData.getLong("startTime", System.currentTimeMillis())
// var stopped = inputData.getBoolean("isStopped", false)
// if (!isStopped and !stopped) {
// Log.d("EarGuard", "StartTime Worker" + startTime)
Log.d(TAG, isStopped.toString())
Thread {
while (!isStopped) {
Thread.sleep(1000)
var usageTime = System.currentTimeMillis()
usageTime -= startTime
Log.d(TAG, usageTime.toString())
if ((usageTime / 1000) == 5L) {
CoroutineScope(Dispatchers.Main).launch(Dispatchers.Main)
{
// Toast.makeText(
// applicationContext,
// "Time limit exceeded", Toast.LENGTH_LONG
// ).show()
val notificationChannel = NotificationChannel(
"123",
"EarGuard",
NotificationManager.IMPORTANCE_HIGH
)
notificationChannel.description =
"You have exceeded the maximum usage limit of listening on headset"
notificationChannel.name = "EarGuard"
notificationChannel.lockscreenVisibility = 1
notificationChannel.shouldShowLights()
notificationChannel.enableVibration(true)
notificationChannel.setSound(
Uri.parse("R.raw.sad"),
AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH).build()
)
notificationChannel.shouldVibrate()
var notificationManager =
applicationContext.getSystemService(NotificationManager::class.java)
notificationManager.createNotificationChannel(notificationChannel)
notificationManager.notify(
123, NotificationCompat.Builder(
applicationContext, "123"
).setSmallIcon(R.drawable.ic_launcher_foreground)
.setLargeIcon(
BitmapFactory.decodeResource(
applicationContext.resources,
R.drawable.ic_launcher_foreground
)
)
.setSound(
Uri.parse("R.raw.sad")
)
.setContentTitle("EarGuard")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentText("You have exceeded the maximum usage limit of listening on headset")
.setAutoCancel(false)
.setChannelId("123")
.build()
)
}
break
}
}
}.start()
// }
return Result.success()
}
// #SuppressLint("RestrictedApi")
// override fun isRunInForeground(): Boolean {
// return super.isRunInForeground()
// }
override fun onStopped() {
Log.d(TAG, "Stopped Worker")
super.onStopped()
}
}
MainActivity.kt
package com.xanjit.focusly
import android.content.*
import android.net.Uri
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material.*
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.WorkRequest
import com.xanjit.focusly.broadcast_receivers.AudioInputBroadcastReceiver
import com.xanjit.focusly.services.CustomService
import com.xanjit.focusly.workers.GetHeadsetUsageTimeWorker
import java.lang.Exception
class MainActivity : ComponentActivity() {
lateinit var receiver: BroadcastReceiver
var TAG = "EarGuard"
lateinit var workManager: WorkManager
lateinit var workRequest: WorkRequest
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
receiver = AudioInputBroadcastReceiver()
setContent {
Surface() {
Scaffold(
topBar = {
TopAppBar() {
}
}
) {
}
}
}
}
override fun onStart() {
super.onStart()
var intentFilter = IntentFilter("android.intent.action.HEADSET_PLUG");
registerReceiver(receiver, intentFilter)
}
}

You could try keep you workRequest.id on your AudioInputBroadcastReceiver and in case of disconnection you can stop this work. I think its a bad practice cancel all running works if you only want to finish your audio work.
cancelAllWork()
Cancels all unfinished work. Use this method with extreme caution! By invoking it, you will potentially affect other modules or libraries in your codebase. It is strongly recommended that you use one of the other cancellation methods at your disposal.
class AudioInputBroadcastReceiver : BroadcastReceiver() {
val workerRequestId: UUID? = null
#RequiresApi(Build.VERSION_CODES.O)
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = intent!!.getIntExtra("state", 0) === 1
val workManager = WorkManager.getInstance(context!!)
if (isConnected) {
....
val workRequest = OneTimeWorkRequest.Builder(
GetHeadsetUsageTimeWorker::class.java,
).setInputData(data.build()).build()
workerRequestId = workRequest.id
workManager.enqueue(workRequest)
} else {
Toast.makeText(context,"Disconnected",Toast.LENGTH_SHORT).show()
workerRequestId?.let { workManager.cancelWorkById(it) }
}
}
...

Related

Create a real-time line chart by using kotlin

I'm trying to create a chart that displays sensor data from a cell phone in real time. I wrote a code for this, but the data was recorded, but the graph was recorded only on the same x-axis. The code is shown below. How should I solve this? If I need to create a separate thread, where should I add it?
package com.example.ex_linear_acc_graph
import android.content.Context
import android.graphics.Color
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.widget.LinearLayout
import android.widget.TextView
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.Legend
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.components.YAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.formatter.ValueFormatter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import kotlin.concurrent.timer
class linearActivity : AppCompatActivity(), SensorEventListener {
private val mSensorManager by lazy {
getSystemService(Context.SENSOR_SERVICE) as SensorManager
}
private lateinit var chart: LineChart
private lateinit var data: LineData
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_linear)
chart = findViewById(R.id.chart_line)
chart.description.isEnabled = false
chart.setTouchEnabled(true)
chart.isDragEnabled = true
chart.setScaleEnabled(true)
chart.setPinchZoom(false)
chart.legend.form = Legend.LegendForm.LINE
chart.xAxis.position = XAxis.XAxisPosition.BOTTOM
chart.xAxis.setDrawLabels(true)
chart.xAxis.axisMaximum = 0f
chart.xAxis.setDrawAxisLine(true)
chart.xAxis.setDrawGridLines(false)
chart.axisRight.isEnabled = false
chart.legend.textColor = Color.WHITE
chart.animateXY(2000, 2000)
chart.invalidate()
data = LineData()
chart.data = data
}
override fun onResume() {
super.onResume()
mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also{
linearacceleration -> mSensorManager.registerListener(
this,
linearacceleration,
SensorManager.SENSOR_DELAY_NORMAL,
SensorManager.SENSOR_DELAY_UI
)}
}
override fun onPause() {
super.onPause()
mSensorManager.unregisterListener(this)
}
override fun onSensorChanged(event: SensorEvent) {
var second : Float = 0f
timer(period = 1000, initialDelay = 1000){
second++
}
if(event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD){
val mag_x = event.values[0]
val mag_y = event.values[1]
val mag_z = event.values[2]
val tv_mag : TextView = findViewById(R.id.tv_linear_acc)
tv_mag.text = "mag_x : ${mag_x}\nmag_y : ${mag_y}\nmag_z : ${mag_z}"
val dataSet = LineDataSet(listOf(Entry(second, mag_x), Entry(second, mag_y), Entry(second, mag_z)), "Accelerometer Data")
data.addDataSet(dataSet)
chart.notifyDataSetChanged()
}
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
// Do nothing
}
}

Kotlin livedata observer not triggered

i'm practising a bit with kotlin and was testing Room and livedata, my app gets data from a json and the stores it in room, i want to move this network call to its own file and class, but if i do so the observer i set to get the changes don't trigger anymore, any help would be appreciated
here is a snipped of my mainactivity, if more is needed to know what happens please let me know
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import androidx.room.Room
import com.optiva.videoplayer.data.*
import com.optiva.videoplayer.network.GetData
import com.optiva.videoplayer.network.Networking
import com.optiva.videoplayer.network.RetrofitConnect
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val dbcategories = Room.databaseBuilder(applicationContext, CategoriesDatabase::class.java,"categories.db").build()
val dbvideo = Room.databaseBuilder(applicationContext, VideosDatabase::class.java,"videos.db").build()
val retrofitData = RetrofitConnect.retrofitInst?.create(GetData::class.java)
val categoriesList = retrofitData?.getAll()
categoriesList?.enqueue(object: Callback<DataList> {
override fun onResponse(
call: Call<DataList>,
response: Response<DataList>
) {
val test = response?.body()
val cat = test?.categories
val vid = test?.videos
lifecycleScope.launch(Dispatchers.IO) {
if (cat != null) {
for(c in cat){
dbcategories.categoriesDAO().insertAll(CategoriesEntity(c.id,c.title,c.type))
}
}
if (vid != null) {
for(v in vid){
dbvideo.VideosDAO().insertAll(VideosEntity(v.id,v.thumb,v.videoUrl,v.categoryId,v.name))
}
}
}
}
override fun onFailure(call: Call<DataList>, t: Throwable) {
Toast.makeText(applicationContext,"error", Toast.LENGTH_LONG).show()
}
})
val textView: TextView = findViewById(R.id.test) as TextView
dbcategories.categoriesDAO().getALL().observeForever({categories ->
if(categories.size>0){
textView.text= categories[0].title
}
})
dbcategories.categoriesDAO().getALL().observe(this, {categories ->
if(categories.size>0){
textView.text= categories[0].title
}
}
} ```

My foreground notification service doesn't work properly if i change my package prefix name in putExtra Method why?

I used the Foreground Service code from Floating Window in localazy.com. My foreground Service didn't send correct codes to the onStartCommand() after I change the package prefix name that they in given in their code in the putExtra Method it always sends null instead of sending the EXIT and NOTE command. Actually, what is the use of the package prefix in the key name? Why did this problem happen?.
package com.krithik.floatingnote.service
import android.app.*
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.util.Log
import android.widget.Toast
import androidx.core.app.NotificationCompat
import com.krithik.floatingnote.R
const val INTENT_COMMAND = "com.localazy.quicknote.COMMAND"
const val INTENT_COMMAND_EXIT = "EXIT"
const val INTENT_COMMAND_NOTE = "NOTE"
private const val NOTIFICATION_CHANNEL_GENERAL = "note_general"
private const val CODE_FOREGROUND_SERVICE = 1
private const val CODE_EXIT_INTENT = 2
private const val CODE_NOTE_INTENT = 3
class FloatingService : Service() {
override fun onBind(intent: Intent?): IBinder? = null
/**
* Remove the foreground notification and stop the service.
*/
private fun stopService() {
stopForeground(true)
stopSelf()
}
/**
* Create and show the foreground notification.
*/
private fun showNotification() {
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val exitIntent = Intent(this, FloatingService::class.java).apply {
putExtra(INTENT_COMMAND, INTENT_COMMAND_EXIT)
}
val noteIntent = Intent(this, FloatingService::class.java).apply {
putExtra(INTENT_COMMAND, INTENT_COMMAND_NOTE)
}
val exitPendingIntent = PendingIntent.getService(
this, CODE_EXIT_INTENT, exitIntent, 0
)
val notePendingIntent = PendingIntent.getService(
this, CODE_NOTE_INTENT, noteIntent, 0
)
// From Android O, it's necessary to create a notification channel first.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
with(
NotificationChannel(
NOTIFICATION_CHANNEL_GENERAL,
getString(R.string.notification_channel_general),
NotificationManager.IMPORTANCE_DEFAULT
)
) {
lockscreenVisibility = Notification.VISIBILITY_PUBLIC
manager.createNotificationChannel(this)
}
} catch (ignored: Exception) {
// Ignore exception.
}
}
with(
NotificationCompat.Builder(
this,
NOTIFICATION_CHANNEL_GENERAL
)
) {
setContentTitle(getString(R.string.app_name))
setContentText(getString(R.string.notification_text))
setAutoCancel(false)
setOngoing(true)
setSmallIcon(R.drawable.ic_baseline_note_24)
setContentIntent(notePendingIntent)
addAction(
NotificationCompat.Action(
0,
getString(R.string.notification_exit),
exitPendingIntent
)
)
startForeground(CODE_FOREGROUND_SERVICE, build())
}
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val command = intent.getStringExtra(INTENT_COMMAND)
Log.i("ServiceCommand", command.toString())
// Exit the service if we receive the EXIT command.
// START_NOT_STICKY is important here, we don't want
// the service to be relaunched.
if (command == INTENT_COMMAND_EXIT) {
stopService()
return START_NOT_STICKY
}
// Be sure to show the notification first for all commands.
// Don't worry, repeated calls have no effects.
showNotification()
// Show the floating window for adding a new note.
if (command == INTENT_COMMAND_NOTE) {
Toast.makeText(
this,
"Floating window to be added",
Toast.LENGTH_SHORT
).show()
}
return START_STICKY
}
}
package com.krithik.floatingnote
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.krithik.floatingnote.database.Note
import com.krithik.floatingnote.database.NoteDatabase
import com.krithik.floatingnote.database.NoteRepository
import com.krithik.floatingnote.databinding.ActivityMainBinding
import com.krithik.floatingnote.service.FloatingService
import com.krithik.floatingnote.service.INTENT_COMMAND
import com.krithik.floatingnote.viewModel.NoteViewModel
import com.krithik.floatingnote.viewModel.NoteViewModelFactory
import com.krithik.floatingnote.viewModel.RecyclerViewAdapter
class MainActivity : AppCompatActivity(), RecyclerViewAdapter.RowClickListener {
private lateinit var binding: ActivityMainBinding
private lateinit var noteViewModel: NoteViewModel
private lateinit var adapter: RecyclerViewAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startFloatingService()
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val dao = NoteDatabase.getInstance(application).noteDao
val repository = NoteRepository(dao)
val factory = NoteViewModelFactory(repository)
noteViewModel = ViewModelProvider(this, factory).get(NoteViewModel::class.java)
binding.noteViewModel = noteViewModel
binding.lifecycleOwner = this
noteViewModel.message.observe(this, Observer {
it.getContentIfNotHandled()?.let {
Toast.makeText(this, it, Toast.LENGTH_LONG).show()
}
})
initRecyclerView()
noteViewModel.noteList.observe(this, Observer {
adapter.submitList(it)
})
}
private fun initRecyclerView() {
binding.noteRecyclerView.layoutManager = LinearLayoutManager(this)
adapter = RecyclerViewAdapter(this)
binding.noteRecyclerView.adapter = adapter
}
override fun onDeleteNote(note: Note) {
noteViewModel.deleteNote(note)
}
private fun Context.startFloatingService(command: String = "") {
val intent = Intent(this, FloatingService::class.java)
if (command.isNotBlank()) intent.putExtra(INTENT_COMMAND, command)
Log.i("Command", INTENT_COMMAND + command)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.startForegroundService(intent)
} else {
this.startService(intent)
}
}
}
```

How to invoke flutter method from broadcastReceiver class?

I am trying to awake flutter method on a received call. I already done the receiving part, but I can't awake flutter method yet.
I tried calling method channel in onReceive() method in MainActivity.kt class, but it gives me error. method channel only seems to work in onCreate() method.
The question is how can I invoke flutter method in onReceive() or is there another way to do it?
MainActivity.kt
import android.Manifest
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import io.flutter.app.FlutterActivity
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity(){
var updateUIReciver: BroadcastReceiver? = null
#RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
registerReceiver(broadcastReceiver, IntentFilter("Service.to.activity"));
val channel = "my.data"
val methodChannel = MethodChannel(flutterView, channel)
val map: HashMap<String, String> = HashMap()
val permissionCheck: Int = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission granted ", Toast.LENGTH_LONG).show();
} else {
//TODO
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 4);
Toast.makeText(this, "Permission not granted ", Toast.LENGTH_LONG).show();
}
methodChannel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result? ->
if (call.method == "callMyFunction") {
methodChannel.invokeMethod("callMyFunction", map)
} else {
}
}
}
var broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "Incoming call received", Toast.LENGTH_LONG).show()
// I can't call "methodChannel.invokeMethod("callMyFunction", map)" here cause of error.
}
}
}
MyBroadcastReceiver.kt
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.telephony.PhoneStateListener
import android.telephony.TelephonyManager
import androidx.core.app.NotificationCompat
import android.app.NotificationManager;
import android.os.Build;
import android.os.IBinder;
import android.widget.Toast
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val telephony = context.getSystemService(Service.TELEPHONY_SERVICE) as TelephonyManager
telephony.listen(object : PhoneStateListener() {
override fun onCallStateChanged(state: Int, incomingNumber: String) {
super.onCallStateChanged(state, incomingNumber)
context.sendBroadcast(Intent("Service.to.activity"))
}
}, PhoneStateListener.LISTEN_CALL_STATE)
}
}
Flutter code
const platform = const MethodChannel('my.data');
Future<void> _receiveFromNative(MethodCall call) async {
try {
if (call.method == "callMyFunction") {
print("Received in flutter");
}
} on PlatformException catch (e) {}
}
platform.setMethodCallHandler(_receiveFromNative);
Basically you can't access methodChannel in BroadcastReceiver directly so you have to make methodChannel in compaion object So,
Add these lines to your MainActivity
companion object {
lateinit var methodChannel: MethodChannel
}
And in onCreate method of MainActivity replace
val methodChannel = MethodChannel(flutterView, channel)
To :
methodChannel = MethodChannel(flutterView, channel)
now you can use MainActivity.methodChannel anywhere in your app.

App not work in background - Ui.thread + Timer

I create easy first my App in Android Studio but i dont know why my App not work in background.
The application works very well if it is on all the time, but when I hide it, it stops working. What am I doing wrong? I try used Intent for background ready but.. i think here is my problem :<
"MojaKlasa" is empty class. If I replace "MojaKlasa" with "MainActivity" in Intent, the application starts, but when the condition from Timer is met, it stops working and turns off.
My code:
package com.example.vicky.notificationexample
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.VibrationEffect
import android.os.Vibrator
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.RemoteViews
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.toast
import org.jetbrains.anko.uiThread
import java.net.URL
import java.nio.charset.Charset
import java.util.*
import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() {
lateinit var notificationManager : NotificationManager
lateinit var notificationChannel : NotificationChannel
lateinit var builder : Notification.Builder
private val channelId = "com.example.vicky.notificationexample"
private val description = "Test notification"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val intent = Intent(this,MojaKlasa::class.java)
val pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT)
val contentView = RemoteViews(packageName,R.layout.notification_layout)
contentView.setTextViewText(R.id.tv_title,"Test")
contentView.setTextViewText(R.id.tv_content,"Notify")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationChannel = NotificationChannel(channelId,description,NotificationManager.IMPORTANCE_HIGH)
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.GREEN
notificationChannel.enableVibration(false)
notificationManager.createNotificationChannel(notificationChannel)
builder = Notification.Builder(this,channelId)
.setContent(contentView)
.setSmallIcon(R.drawable.ic_launcher_round)
.setLargeIcon(BitmapFactory.decodeResource(this.resources,R.drawable.ic_launcher))
.setContentIntent(pendingIntent)
}else{
builder = Notification.Builder(this)
.setContent(contentView)
.setSmallIcon(R.drawable.ic_launcher_round)
.setLargeIcon(BitmapFactory.decodeResource(this.resources,R.drawable.ic_launcher))
.setContentIntent(pendingIntent)
}
val executor = Executors.newScheduledThreadPool(5)
doAsync(executorService = executor){
val result = URL("https://linkdomain/app2.php").readText()
uiThread {
toast(result)
var stare:Int = result.toInt()
Timer().scheduleAtFixedRate(object : TimerTask() {
#SuppressLint("SimpleDateFormat", "ServiceCast")
override fun run() {
val url = URL("https://linkdomain/app.php").readText(Charset.forName("ISO-8859-1"))
url.toInt();
if (url > stare.toString()) {
stare = stare.toInt()+1
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (vibrator.hasVibrator()) { // Vibrator availability checking
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE)) // New vibrate method for API Level 26 or higher
} else {
vibrator.vibrate(500) // Vibrate method for below API Level 26
}
}
notificationManager.notify(stare.toInt(),builder.build())
}
//Log.d("TAG", "url "+url)
//Log.d("TAG", "cos "+stare)
}
}, 0, 1000) //put here time 1000 milliseconds=1 second
}
}
}
fun buTestUpdateText2 (view: View) {
val destination = Intent(this#MainActivity.baseContext, MainActivity::class.java)
.also { it.putExtra("KEY", 0) }
startActivity(destination)
}
}

Categories

Resources