0

So I have a service that contains a Timer. The service is meant to run even when the app in the background and is supposed to pull the user to the app when the timer executes the method(from another activity). The service is triggered on and off by a toggle button. Currently my R.id reference to my spinner keeps throwing a NullPointerException that i don't know how to fix. Can someone please help me out?

The Method the Timer is running:

 public String TemperatureCatch()
        {
/*this line throws the error */            Spinner reeferchoice = (Spinner)findViewById(R.id.optionselecti);
                String reeferChoicei = reeferchoice.getSelectedItem().toString();
                if (reeferChoicei.equals("Yes")) {
                    final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 500);
                    tg.startTone(ToneGenerator.TONE_CDMA_ABBR_ALERT);
                    AlertDialog.Builder alert = new AlertDialog.Builder(this);
                    alert.setTitle("Temperature");
                    alert.setMessage("Input Temperature in F° (-20 to 65) ");
                    final EditText input = new EditText(this);
                    input.setInputType(InputType.TYPE_CLASS_PHONE);
                    alert.setView(input);
                    alert.setPositiveButton("Check-In", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            temperaturei = input.getText().toString();
                            Toast.makeText(getBaseContext(), "Updated", Toast.LENGTH_SHORT).show();
                            Updater(temperaturei);
                        }
                    });
                    alert.show();
                } else if (reeferChoicei.equals("No")) {
                    temperaturei = "DRY";
                    Updater(temperaturei);
                }
            return temperaturei;
        }

My service code:

import android.app.IntentService;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;

import java.util.Timer;
import java.util.TimerTask;

public class MyService extends Service {
    Locator locator;
    Timer myTimer;
    @Override
    public void onCreate() {
        locator = new Locator();
        myTimer = new Timer();
    }
    private class MyTimerTask extends TimerTask
    {

        @Override
        public void run() {
            Handler handler = new Handler(Looper.getMainLooper());

            handler.postDelayed(new Runnable() {
                @Override
                public void run() {

                    locator.TemperatureCatch();
                }
            }, 1000);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        MyTimerTask myTimerTask = new MyTimerTask();
            myTimer.scheduleAtFixedRate(myTimerTask, 0, 15000);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        myTimer.cancel();
    }
}

the button:

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
    {

        if (isChecked)
        {
 startService(new Intent(this, MyService.class));
            Toast.makeText(this,"Check-In will be done every 15 seconds",Toast.LENGTH_SHORT).show();
        }
        else
        {
stopService(new Intent(this, MyService.class));
            Toast.makeText(this,"Manual Check-In enabled",Toast.LENGTH_SHORT).show();
        }

    }

the stack trace:

  Process: com.example.adrian.trucktracker, PID: 9617
    java.lang.NullPointerException
            at android.app.Activity.findViewById(Activity.java:1952)
            at com.example.adrian.trucktracker.Locator.TemperatureCatch(Locator.java:192)
            at com.example.adrian.trucktracker.MyService$MyTimerTask$1.run(MyService.java:32)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:157)
            at android.app.ActivityThread.main(ActivityThread.java:5872)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:852)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:668)
            at dalvik.system.NativeStart.main(Native Method)

3 Answers3

0

You should not create a instance of Activity class.

locator = new Locator(); // do not do this

This results in NullPointerException when you initialize views.

Can i Create the object of a activity in other class?

Also what you are doing seems to be a design issue.

Community
  • 1
  • 1
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • @AdamPraiswater depends on what you want to do. What should service do? – Raghunandan Aug 15 '14 at 15:47
  • the service should contain a timer that excuted a method in the activity called `Locator`. This service should also run while the app is in the background – Adam Praiswater Aug 15 '14 at 15:48
  • I've tried to do that but I cannot find code suitable for use with a Service and I can't find how to to implement the method using an Alarm Manager – Adam Praiswater Aug 15 '14 at 15:53
  • @AdamPraiswater this seems to be a design issue. You don't want service running for long periods as it consumes battery. You need to think of a better design. – Raghunandan Aug 15 '14 at 15:54
  • Thats what I've told the client however this is the way he wants it set up. The toggle button whould turn the Service on and off – Adam Praiswater Aug 15 '14 at 15:56
  • @AdamPraiswater What does this `Updater(temperaturei);` do?. You are getting mixed up. You read the docs as to what service is used for. – Raghunandan Aug 15 '14 at 15:59
  • `Updater`writes a file then sends it – Adam Praiswater Aug 15 '14 at 16:03
  • `TemperatureCatch` brings up a dialog box if the option Yes on a spinner is selected and asks for an input before running `Updater` – Adam Praiswater Aug 15 '14 at 16:04
  • @AdamPraiswater 1. ui should be updated on the ui thread ( in oyur case locater Activity). 2. Service does not have a ui. 3. Updater should be in background thread as it just writes and sends it. 4. Consider re-designing as runnning services for long periods can cause battery drain. Read about services before going any further – Raghunandan Aug 15 '14 at 16:07
0

As previous comments already pointed out, service wont have any UI, so you cannot make findViewById method call.

If you want your service to change the UI, bind to this service from your activity and using callbacks/delegates, you can notify the activity to change the UI from the service.

bhargavg
  • 1,383
  • 9
  • 12
0

Activity objects are not supposed to be initialized by calling its constructor. By doing so, your overriden method onCreate() never get called, so the views are not initialized and findViewById will fail.

You should instead start the activity in the service instead of calling its contructor, something like this:

Intent t = new Intent (this, Locator.class);
t.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(t);

You can have a static getter in Locator class to get the instance of the Activity, so that you can use it in the Service.

Krypton
  • 3,337
  • 5
  • 32
  • 52