Showing posts with label JobIntentService. Show all posts
Showing posts with label JobIntentService. Show all posts

Alarm Manager Example Android Kotlin

MainActivity.kt
package com.example.espl.alarmmanagerexamplekotlin

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
     
        val alarmReceiver=AlarmReceiver()

        btnSetAlarm.setOnClickListener(View.OnClickListener { v: View? ->
            //This will set repeating alarm on start of the app
           //On button click alarmManager will set exact repeating alarm android at interval of 1minute
            alarmReceiver.setRepeatingAlarmReminder(this)
        })

        btnCancelAlarm.setOnClickListener(View.OnClickListener { v: View? ->
            // this cancel repeating alarm on start of the app
            alarmReceiver.cancelAlarm(this)
        })
    }
}
BootBroadcastReceiver.kt
package com.example.espl.alarmmanagerexamplekotlin

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

class  BootBroadcastReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        val alarmReceiver = AlarmReceiver()
        if(intent?.action.equals(Intent.ACTION_BOOT_COMPLETED)){
            alarmReceiver.setRepeatingAlarmReminder(context!!);
            }
    }
}
AlarmSchedulingService.kt
package com.example.espl.alarmmanagerexamplekotlin

import android.content.Context
import android.content.Intent
import android.support.v4.app.JobIntentService
import android.util.Log
/**
 * JobIntentClass written in Kotlin
 **/
class AlarmSchedulingService : JobIntentService() {
    //Constant ID to recognise the job
    val JOB_ID = 1000
    fun enqueueWork(context: Context , work:Intent) {
        enqueueWork(context, AlarmSchedulingService::class.java, JOB_ID, work)
    }

    override fun onHandleWork(p0: Intent) {
        //JobIntentService as a android background service will handle the work assigned by alarmmanager intent in this example
        //do your work here.
        Log.e("onHandleWorkCalled","::"+p0.extras.getString("RepeatingAlarm"))
    }
}

AlarmReceiver.kt
package com.example.espl.alarmmanagerexamplekotlin

import android.app.AlarmManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.app.PendingIntent
import java.util.Date
import java.text.SimpleDateFormat


class AlarmReceiver: BroadcastReceiver(){
    override fun onReceive(context: Context?, intent: Intent?) {

        val service = Intent(context, AlarmSchedulingService::class.java)
//        Log.e("onHandleWorkCalled","::onReceive"+ intent?.extras?.getString("RepeatingAlarm"))
//        service.putExtra("RepeatingAlarm", intent?.extras?.getString("RepeatingAlarm"));
        val dateFormat = SimpleDateFormat("yyyy-MM-dd hh:mm:ss a")
        service.putExtra("RepeatingAlarm","Time:"+dateFormat.format(Date()))
        AlarmSchedulingService().enqueueWork(context!!,service)
    }

    fun setRepeatingAlarmReminder(context:Context) {
//Below code is to set alarm in android programmatically with repeating interval of 1 minute
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val intent = Intent(context, AlarmReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), (1000 * 60).toLong(), pendingIntent) // Millisec * Second
    }

    fun cancelAlarm(context: Context) {
        val intent = Intent(context, AlarmReceiver::class.java)
        val sender = PendingIntent.getBroadcast(context, 0, intent, 0)
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmManager.cancel(sender)
    }
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.espl.alarmmanagerexamplekotlin">

    <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
 
    <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>

        <receiver android:process=":remote" android:name=".AlarmReceiver"></receiver>

        <receiver android:name=".BootBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"></action>
            </intent-filter>
        </receiver>

        <service
                android:name=".AlarmSchedulingService"
                android:permission="android.permission.BIND_JOB_SERVICE" />
    </application>

</manifest>

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        tools:context=".MainActivity">

    <Button
            android:id="@+id/btnSetAlarm"
            android:layout_margin="20dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Start Alarm-set Repeating Alarm Reminder"
            android:textAllCaps="false"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

    <Button
            android:id="@+id/btnCancelAlarm"
            android:layout_margin="20dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cancel Alarm - cancel the repeating Alarm"
            android:textAllCaps="false"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

</LinearLayout>
Output log of repeating alarm android kotlin:
04-23 18:18:18.219 10840-12057/com.example.espl.alarmmanagerexamplekotlin E/onHandleWorkCalled: ::Time:2019-04-23 06:18:18 PM

04-23 18:19:46.961 10840-12198/com.example.espl.alarmmanagerexamplekotlin E/onHandleWorkCalled: ::Time:2019-04-23 06:19:46 PM

04-23 18:20:46.735 10840-12297/com.example.espl.alarmmanagerexamplekotlin E/onHandleWorkCalled: ::Time:2019-04-23 06:20:46 PM

04-23 18:21:46.788 10840-12341/com.example.espl.alarmmanagerexamplekotlin E/onHandleWorkCalled: ::Time:2019-04-23 06:21:46 PM

04-23 18:22:48.589 10840-13166/com.example.espl.alarmmanagerexamplekotlin E/onHandleWorkCalled: ::Time:2019-04-23 06:22:48 PM

04-23 18:23:48.848 10840-13372/com.example.espl.alarmmanagerexamplekotlin E/onHandleWorkCalled: ::Time:2019-04-23 06:23:48 PM

WakefulBroadcastReceiver is deprecated

Android WakefulBroadcastReceiver deprecated Warning (Android Studio)

'android.support.v4.content.wakefulbroadcastreceiver' is deprecated.
This Inspection reports where deprecated code is used in the specified inspection scope

WakefulBroadcastReceiver Android Oreo deprecation

The WakefulBroadcastReceiver class was deprecated in API level 26.1.0 (Android – 8.0 Oreo).
As of Android O, background check restrictions make this class no longer generally useful. (It is generally not safe to start a service from the receipt of a broadcast, because you don't have any guarantees that your app is in the foreground at this point and thus allowed to do so.) Instead, developers should use android.app.job.JobScheduler to schedule a job, and this does not require that the app hold a wake lock while doing so (the system will take care of holding a wake lock for the job).

Android Service Wacklock, WAKE_LOCK permission and JobIntentService

To overcome this background restriction and WAKE_LOCK permission issues. According to documentation, the new JobIntentService class will work to handle both wake locks and backward compatibility:
JobIntentService is Helper for processing work that has been enqueued for a job/service. When running on Android O or later, the work will be dispatched as a job via JobScheduler.enqueue. When running on older android versions of the platform, it will use Context.startService. Use enqueueWork(Context, Class, int, Intent) to enqueue new work to be dispatched to and handled by your service. It will be executed in onHandleWork(Intent). You do not need to use WakefulBroadcastReceiver when using this class. When running on Android Oreo, the JobScheduler will take care of wake locks for you (holding a wake lock from the time you enqueue work until the job has been dispatched and while it is running). When running on previous versions of the platform, this wake lock handling is emulated in the class here by directly calling the PowerManager; this means the application must request the WAKE_LOCK permission. So, make sure to add the WAKE_LOCK permission in your AndroidManifest.xml.
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>

IntentService + WakefulBroadcastReceiver replacement with JobIntentService + BroadcastReceiver

There is much better solution for while migrating to Android O as IntentService + WakefulBroadcastReceiver are deprecated with API 26 (Android 8.0 Oreo). The best alternative is to use JobIntentService+BroadcastReceiver  which can be easily converted from IntentService + WakefulBroadcastReceiver model. JobIntentService class  of support library 26 relies on JobScheduler API of android and has the exact workflow of IntentService. So, For pre-Oreo android devices, JobIntentService will use old IntentService.

Use Jobintentservice Android O and BroadcastReceiver for background processing(Services)

Use the BroadcastReceiver and JobIntentService for background processing(Services) on Android Oreo (26)
TaskFinishReceiver.java
public class TaskFinishReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            //enqueueWork will pass service/work intent in the JobIntentService class
            MyJobIntentService.enqueueWork(context, intent);
        }
    }

MyJobIntentService.java
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.JobIntentService;
import android.util.Log;


/**
 * Example implementation of a JobIntentService.
 */

public class MyJobIntentService extends JobIntentService {
 
    static final int JOB_ID = 1000;

/**
     * Convenience method for enqueuing work in to this service.
     */
    static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, AlarmSchedulingService.class, JOB_ID, work);
    }

    @Override
    protected void onHandleWork(Intent intent) {
       // We have received work to do.  The system or framework is already
        // holding a wake lock for us at this point, so we can just go.
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("COMPLETED WORK:","All work complete");
    }
}

Popular Posts