-2

I want to edit textview text from MainActivity class and I put a function which is connected to interface, which then goes into another class named JobService (class for sending something with threads in it). But I am getting an error in constructor part It alludes to null pointer exception at myCallback part. Even when I give the string with code inside (timestampJob) it goes to null pointer exception.

//MainActivity class

public class MainActivity extends AppCompatActivity implements MyCallback

    TextView timestampMails;

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

    timestampMails = (TextView) findViewById(R.id.timeStampMainMails);

    }

    //function for changeing the textview connected with interface to JobService class
    public void setTimestampMain(String time){
        timestampMails.setText(time);
    }

//Interface class

public interface MyCallback {
    public void setTimestampMain(String myString);
}

//JobService class

public class JobService extends android.app.job.JobService {

    //interface call
    MyCallback myCallback = null;
    //constructor
    public JobService(MyCallback callback){
        this.myCallback = callback;
    }
    public void timeStampJob(String time){
        //HERE IS THE EXCEPTION (I think)
        if(myCallback != null){
            myCallback.setTimestampMain(time);
        }
    }

    @Override
    public boolean onStartJob(JobParameters params) {
        Log.d(TAG, "Job started");
        doBackgroundWork(params);

        return true;
    }

    private void doBackgroundWork(JobParameters params) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i=0; i<1; i++){

                    //get device time function and populate function with that string
                    String deviceTime = new     SimpleDateFormat("HH:mm").format(Calendar.getInstance().getTime());
                    timeStampJob(deviceTime);

                 
                    if(jobCancelled){
                        return;
                    }

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
                Log.d(TAG, "Job finished:");
                jobFinished(params, false);
            }
        }).start();

    }

    @Override
    public boolean onStopJob(JobParameters params) {
        Log.d(TAG, "Job cancelled before completion");
        jobCancelled = true;

        return true;
    }

Process: com.example.gmailemailsolution, PID: 3944
java.lang.RuntimeException: Unable to instantiate service
com.example.gmailemailsolution.JobService: java.lang.InstantiationException:
java.lang.Class<com.example.gmailemailsolution.JobService> has no zero
argument constructor (HERE)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3268)
at android.app.ActivityThread.-wrap5(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1608)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:173)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:938)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:828)
Caused by: java.lang.InstantiationException:
java.lang.Class<com.example.gmailemailsolution.JobService> has no zero
argument constructor (HERE)
at java.lang.Class.newInstance(Native Method)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3265)
at android.app.ActivityThread.-wrap5(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1608)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:173)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:938)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:828) 

Tried interface class, calling it with constructor and making textview static but did not made it work.

NikolaN
  • 3
  • 4
  • Hi, did you try to run the Code in UI thread? You can do it with a Handler. – Sametcey Jul 01 '23 at 20:25
  • @Sametcey hmm I did not try that. Do you think that exception is thrown because of dedicated thread? – NikolaN Jul 01 '23 at 20:46
  • I write an answer please try that. – Sametcey Jul 01 '23 at 20:58
  • 1
    The error you posted is because the JobService class requires a zero-argument constructor, but yours does not have one. Have a look at [this question](https://stackoverflow.com/questions/45438539/error-service-class-has-no-zero-argument-constructor) for an example of how to implement that, but depending on what you actually want to do in the service this might be overkill. You would get better answers if you also included in the question *why* you want a service in the first place and what work will be done on it. – Tyler V Jul 01 '23 at 22:36
  • Also some relevant examples [here](https://stackoverflow.com/questions/51057471/service-error-has-no-zero-argument-constructor?rq=1) – Tyler V Jul 01 '23 at 22:41
  • 2
    You would NEVER update the UI from a JobService. Services are separate contexts, there should be no way for a service to access an Activity. Doing so is 100% a memory leak if you manage to find some way to do it. JobService is meant to be used with JobScheduler, which is a mechanism for scheduling work to be done in the future. There is no promise that your Activity is running when it fires, in fact the usual reason to use it is that your activity *isn't* expected to be. You need to step back, describe what you're actually trying to do with this code, and learn the correct way to do it. – Gabe Sechan Jul 02 '23 at 03:40
  • @TylerV so I am implementing time stamps when job is finished. First I tried implementing time stamp into successful job scheduled but that fires right away when button is clicked since job goes thru. Maybe I am not aware of some functions that JobScheduler brings but can i check if thread is finished from main activity where I am implementing it? Its basic code for JobScheduler where it is called lets say once a day. – NikolaN Jul 02 '23 at 15:20
  • @GabeSechan I described it in comment above. Can I like get some check when threads are done or something from Scheduler? – NikolaN Jul 02 '23 at 15:22
  • "I am implementing time stamps when job is finished" does not really describe what "job" is or what you are trying to do (or, more importantly, why you think you need to use a service for it instead of just using a background thread in the app). If you need a service, one option would be to write the timestamp to [SharedPreferences](https://stackoverflow.com/questions/13558550/can-i-get-data-from-shared-preferences-inside-a-service), and have the activity query the SharedPreferences at some interval in its own thread. – Tyler V Jul 02 '23 at 16:07
  • @TylerV yea I just read about SharedPreferences so I am gonna try and do that. Time stamps are for when email is sent so there is like value for person to see when is the last job finished with success. – NikolaN Jul 02 '23 at 16:26

1 Answers1

-1

You can also update UI thread from background thread in this way also:

Handler handler = new Handler();

//below piece of code is written in function of class that extends from AsyncTask

handler.post(new Runnable() {
    @Override
    public void run() {
        textView.setText(stringBuilder);
    }
});

You must pass the view object to the class in which the handler are running.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Sametcey
  • 141
  • 1
  • 6
  • I am not sure how to implement this into my code. – NikolaN Jul 01 '23 at 21:33
  • This fails to explain, for example, where to put `Handler handler = new Handler();` Due to your use of the deprecated zero-argument constructor, that's _very_ important. – Ryan M Aug 22 '23 at 03:03