0

I'm having trouble running this small Java-based Android Studio app on my Android Emulator. When I try to schedule a job using a job scheduler feature for notifications on Android, my App crashes and gives me this error message "Caused by: java.lang.IllegalArgumentException: No such service ComponentInfo{com.example.notificationscheduler/com.example.notificationscheduler.NotificationJobService}". Please help me, my app information is down below.

I'm on the latest version of Android Studio.

Build.Gradle Module:app configuration details:

  compileSdkVersion 29
     buildToolsVersion "29.0.2"

  defaultConfig {
    applicationId "com.example.notificationscheduler"
    minSdkVersion 21
    targetSdkVersion 29
    versionCode 1
    versionName "1.0"

My MainActivity Class Code:

     package com.example.notificationscheduler;


     import android.app.job.JobInfo;
     import android.app.job.JobScheduler;
     import android.content.ComponentName;
     import android.os.Bundle;
     import android.view.View;
     import android.widget.RadioGroup;
     import android.widget.SeekBar;
     import android.widget.Switch;
     import android.widget.TextView;
     import android.widget.Toast;

     import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

private static final int JOB_ID = 0;
private JobScheduler mScheduler;

// Switches for setting job options.
private Switch mDeviceIdleSwitch;
private Switch mDeviceChargingSwitch;

// Override deadline seekbar.
private SeekBar mSeekBar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mDeviceIdleSwitch = findViewById(R.id.idleSwitch);
    mDeviceChargingSwitch = findViewById(R.id.chargingSwitch);
    mSeekBar = findViewById(R.id.seekBar);

    final TextView seekBarProgress = findViewById(R.id.seekBarProgress);

    mScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);

    // Updates the TextView with the value from the seekbar.
    mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            if (i > 0) {
                seekBarProgress.setText(getString(R.string.seconds, i));
            } else {
                seekBarProgress.setText(R.string.not_set);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
        }
    });
    }

public void scheduleJob(View view) {
    RadioGroup networkOptions = findViewById(R.id.networkOptions);

    int selectedNetworkID = networkOptions.getCheckedRadioButtonId();

    int selectedNetworkOption = JobInfo.NETWORK_TYPE_NONE;

    int seekBarInteger = mSeekBar.getProgress();
    boolean seekBarSet = seekBarInteger > 0;


    switch (selectedNetworkID) {
        case R.id.noNetwork:
            selectedNetworkOption = JobInfo.NETWORK_TYPE_NONE;
            break;
        case R.id.anyNetwork:
            selectedNetworkOption = JobInfo.NETWORK_TYPE_ANY;
            break;
        case R.id.wifiNetwork:
            selectedNetworkOption = JobInfo.NETWORK_TYPE_UNMETERED;
            break;
    }

    ComponentName serviceName = new ComponentName(getPackageName(),
            NotificationJobService.class.getName());
    JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, serviceName)
            .setRequiredNetworkType(selectedNetworkOption)
            .setRequiresDeviceIdle(mDeviceIdleSwitch.isChecked())
            .setRequiresCharging(mDeviceChargingSwitch.isChecked());

    if (seekBarSet) {
        builder.setOverrideDeadline(seekBarInteger * 1000);
    }
    boolean constraintSet = selectedNetworkOption
            != JobInfo.NETWORK_TYPE_NONE
            || mDeviceChargingSwitch.isChecked()
            || mDeviceIdleSwitch.isChecked()
            || seekBarSet;

    if (constraintSet) {
        JobInfo myJobInfo = builder.build();
        mScheduler.schedule(myJobInfo);
        Toast.makeText(this, R.string.job_scheduled, Toast.LENGTH_SHORT)
                .show();
    } else {
        Toast.makeText(this, R.string.no_constraint_toast,
                Toast.LENGTH_SHORT).show();
    }
}


public void cancelJobs(View view) {

    if (mScheduler != null) {
        mScheduler.cancelAll();
        mScheduler = null;
        Toast.makeText(this, R.string.jobs_canceled, Toast.LENGTH_SHORT)
                .show();
    }
  }
}

My NotificationJobService class code:

package com.example.notificationscheduler;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;
import android.graphics.Color;

import androidx.core.app.NotificationCompat;

  public class NotificationJobService extends JobService {

// Notification channel ID.
private static final String PRIMARY_CHANNEL_ID =
        "primary_notification_channel";
// Notification manager.
NotificationManager mNotifyManager;

@Override
public boolean onStartJob(JobParameters jobParameters) {

    // Create the notification channel.
    createNotificationChannel();

    // Set up the notification content intent to launch the app when clicked

    PendingIntent contentPendingIntent = PendingIntent.getActivity
            (this, 0, new Intent(this, MainActivity.class),
                    PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder builder = new NotificationCompat.Builder
            (this, PRIMARY_CHANNEL_ID)
            .setContentTitle(getString(R.string.job_service))
            .setContentText(getString(R.string.job_running))
            .setContentIntent(contentPendingIntent)
            .setSmallIcon(R.drawable.ic_job_running)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setDefaults(NotificationCompat.DEFAULT_ALL)
            .setAutoCancel(true);

    mNotifyManager.notify(0, builder.build());
    return false;
}


@Override
public boolean onStopJob(JobParameters jobParameters) {
    return false;
}

public void createNotificationChannel() {

    // Create a notification manager object.
    mNotifyManager =
            (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

    // Notification channels are only available in OREO and higher.
    // So, add a check on SDK version.
    if (android.os.Build.VERSION.SDK_INT >=
            android.os.Build.VERSION_CODES.O) {

        // Create the NotificationChannel with all the parameters.
        NotificationChannel notificationChannel = new NotificationChannel
                (PRIMARY_CHANNEL_ID,
                        getString(R.string.job_service_notification),
                        NotificationManager.IMPORTANCE_HIGH);

        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.enableVibration(true);
        notificationChannel.setDescription
                (getString(R.string.notification_channel_description));

        mNotifyManager.createNotificationChannel(notificationChannel);
    }
}
}

strings.xml code:

   <resources>
   <string name="app_name">NotificationScheduler</string>
   <string name="seconds">%1$d s</string>
   <string name="required_network_type">Network Type Required:</string>
   <string name="none">None</string>
   <string name="any">Any</string>
   <string name="wifi">Wifi</string>
   <string name="requires">Requires:</string>
   <string name="device_idle">Device Idle</string>
   <string name="device_charging">Device Charging</string>
   <string name="override_deadline">Override Deadline:</string>
   <string name="not_set">Not set</string>
   <string name="schedule_job">Schedule Job</string>
   <string name="cancel_jobs">Cancel Jobs</string>
   <string name="job_service">Job Service</string>
   <string name="job_running">Your Job ran to completion!</string>
   <string name="job_service_notification">Job Service notification</string>
   <string name="notification_channel_description">Notifications from Job Service</string>
   <string name="job_scheduled">Job Scheduled, will run when the constraints are    met</string>
   <string name="no_constraint_toast">Please set at least one constraint</string>
   <string name="jobs_canceled">Jobs Canceled</string>
   </resources>

activity_main.xml

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:padding="@dimen/layout_padding">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/view_margin"
        android:text="@string/required_network_type"
        android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />

    <RadioGroup
        android:id="@+id/networkOptions"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/view_margin"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/noNetwork"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="@string/none" />

        <RadioButton
            android:id="@+id/anyNetwork"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/any" />

        <RadioButton
            android:id="@+id/wifiNetwork"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/wifi" />
    </RadioGroup>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/view_margin"
        android:text="@string/requires"
        android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="4dp"
        android:orientation="horizontal">

        <Switch
            android:id="@+id/idleSwitch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/view_margin"
            android:text="@string/device_idle" />

        <Switch
            android:id="@+id/chargingSwitch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/view_margin"
            android:text="@string/device_charging" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/view_margin"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/seekBarLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/override_deadline"
            android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />

        <TextView
            android:id="@+id/seekBarProgress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/not_set"
            android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
    </LinearLayout>

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/view_margin" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_margin="@dimen/view_margin"
        android:onClick="scheduleJob"
        android:text="@string/schedule_job" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_margin="@dimen/view_margin"
        android:onClick="cancelJobs"
        android:text="@string/cancel_jobs" />
</LinearLayout>

dimens.xml

 <resources>
   <dimen name="layout_padding">16dp</dimen>
   <dimen name="view_margin">4dp</dimen>
 </resources>
Lou
  • 67
  • 1
  • 8
  • 1
    Does this answer your question? [Android java.lang.IllegalArgumentException: No such service ComponentInfo JobScheduler](https://stackoverflow.com/questions/33364096/android-java-lang-illegalargumentexception-no-such-service-componentinfo-jobsch) – donquih0te Mar 13 '20 at 04:29
  • I forgot to add to my Android Manifest file. – Lou Mar 13 '20 at 04:57

0 Answers0