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)
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.
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.
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.
Related
I'm trying to create a timer that would launch in the background once onDestroy() is triggered, and once the timer reaches 6 hours, SharedPreferences will be used to make a change in the app.
I was wondering... what would be the correct way to setup CountDownTimer or anything similar it for onDestroy().
I will answer anything if needed. Thank you.
After about a week, a working answer came up. This answer includes what's related to how to make the service run. In this scenario, I'm building a CountDownTimer service.
AndroidManifest.xml
<service android:name=".TimeService"/>
MainActivity.java
import android.content.Intent;
import android.support.v4.content.ContextCompat;
public class MainActivity extends AppCompatActivity {
Intent i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
i = new Intent(this, TimeService.class);
stopService(i); //To stop the service the next time the app is launched.
}
#Override
protected void onDestroy() {
launchService(); //Launches the service once when app shuts down.
super.onDestroy();
}
public void launchService() { //How to launch the service, depending the phone's API.
if(Build.VERSION.SDK_INT >= 26) {
startForegroundService(new Intent(this, TimeService.class));
}
else{
Intent i;
i = new Intent(this, TimeService.class);
ContextCompat.startForegroundService(this, i);
}
}
}
TimeService.java
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.support.annotation.Nullable;
public class TimeService extends Service {
CountDownTimer cdt = null;
private SharedPreferences pref;
//Things you want SharedPreferences to change.
Intent i;
#Override
public void onCreate() {
i = new Intent(this, TimeService.class);
startService(i);
pref = this.getSharedPreferences("myAppPref", MODE_PRIVATE);
cdt = new CountDownTimer(3600000, 1000) { //One hour timer with one second interval.
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
//Whatever you need SharedPreferences to change here.
}
};
cdt.start();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
In my MainActivity XML file, I have an EditText which id is editsearch. I have a service class for listening to the clipboard text and open my app. Everything is happening fine but I can't set the text to my editsearch when my app opens from service class.
findViewById method is not work in the onStartCommand method of my service. I have also tried defining my editsearch EditText as a static property in my MainActivity class but not getting my expected result.
Here is my service class
package com.learn24bd.ad;
import android.app.Service;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
public class MyServiceReceiver extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MySerivce","Service Started");
final ClipboardManager clipboard = (ClipboardManager) this.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
public void onPrimaryClipChanged() {
String copiedText = clipboard.getText().toString();
Log.i("Copied",copiedText);
/* here i want to setText to my editsearch
also tried with static property
MainActivity.editsearch.setText(copiedText);
*/
Intent i = new Intent();
i.setClass(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
});
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Services aren't suitable for dealing with UI.
Instead, in your case, you should pass the clipboard content for the MainActivity class to handle. For that, pass it as an intent extra:
Intent i = new Intent();
i.setClass(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("clipboard_text", copiedText)
startActivity(i);
And receive and handle the text in your activity:
String clipboardText = getIntent().getStringExtra("clipboard_text");
Then you can set the text to your EditText:
editText.setText(clipboardText)
I make an android application with eclipse without activity just one class and the code inside it is this
public class PersistService extends Service {
private static final int INTERVAL = 3000; // poll every 3 secs
private static final string YOUR_APP_PACKAGE_NAME = "YOUR_APP_PACKAGE_NAME";
private static boolean stopTask;
private PowerManager.WakeLock mWakeLock;
#Override
public void onCreate() {
super.onCreate();
stopTask = false;
// Optional: Screen Always On Mode!
// Screen will never switch off this way
mWakeLock = null;
if (settings.pmode_scrn_on){
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "a_tag");
mWakeLock.acquire();
}
// Start your (polling) task
TimerTask task = new TimerTask() {
#Override
public void run() {
// If you wish to stop the task/polling
if (stopTask){
this.cancel();
}
// The first in the list of RunningTasks is always the foreground task.
RunningTaskInfo foregroundTaskInfo = activityManager.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
// Check foreground app: If it is not in the foreground... bring it!
if (!foregroundTaskPackageName.equals(YOUR_APP_PACKAGE_NAME)){
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage(YOUR_APP_PACKAGE_NAME);
startActivity(LaunchIntent);
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task, 0, INTERVAL);
}
#Override
public void onDestroy(){
stopTask = true;
if (mWakeLock != null)
mWakeLock.release();
super.onDestroy();
}
}
and i register my service in this way `register your service:
<service android:name="YOURPACAKGE.PersistService"
android:enabled="true"/>`
I have some error "red line appear under".
line number 1 -> service "cannot be resolved to a type"
line number 7 -> power manager "cannot be resolved to a type"
line number 10 -> onCreat() "The method onCreate() of typePersistService must override or implement a supertype method"
line number 11 -> super "Service cannot be resolved to a type"
line number 12 -> TimerTask "cannot be resolved to a type"
line number 28 -> activityManager "cannot be resolved"
line number 43 -> onDestroy() "The method onDestroy() of type PersistService must override or implement a supertype method"
You need add imports to this class
import android.app.*;
import android.content.*;
import android.os.*;
import java.util.*;
public class PersistService extends Service {
//Class Content
}
Note: I do not use eclipse but I think it is missing some plugin or something like that to import automatically. Eclipse users please correct me if I am wrong.
You can check this below code, you didn't import any class that is the problem, And I don't understand your solution, Why you should open your package when your application open..? We can use ActivityLifecycle too to identiy our app is opening or not.
import android.app.ActivityManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.annotation.Nullable;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by muthukrishnan on 10/06/17.
*/
public class PersistService extends Service {
private static final int INTERVAL = 3000; // poll every 3 secs
private static final String YOUR_APP_PACKAGE_NAME = "YOUR_APP_PACKAGE_NAME";
private static boolean stopTask;
private PowerManager.WakeLock mWakeLock;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
stopTask = false;
// Optional: Screen Always On Mode!
// Screen will never switch off this way
mWakeLock = null;
// NOTE : #Muthu I am not sure what is this variable called settings
if (settings.pmode_scrn_on){
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "a_tag");
mWakeLock.acquire();
}
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
// Start your (polling) task
TimerTask task = new TimerTask() {
#Override
public void run() {
// If you wish to stop the task/polling
if (stopTask){
this.cancel();
}
// The first in the list of RunningTasks is always the foreground task.
ActivityManager.RunningTaskInfo foregroundTaskInfo = activityManager.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
// Check foreground app: If it is not in the foreground... bring it!
if (!foregroundTaskPackageName.equals(YOUR_APP_PACKAGE_NAME)){
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage(YOUR_APP_PACKAGE_NAME);
startActivity(LaunchIntent);
}
}
};
Timer timer = new Timer();
timer.scheduleAtFixedRate(task, 0, INTERVAL);
}
#Override
public void onDestroy(){
stopTask = true;
if (mWakeLock != null)
mWakeLock.release();
super.onDestroy();
}
}
I'm trying to create a service for the first time that runs a method from the activity every 15 seconds once a toggle button is checked when app is the background of a phone and so far the tutorials havent been helpful; this is my code so far. Forgive me if I look stupid here, its my first time using a service.
Service Code
package com.example.adrian.trucktracker;
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 AutoUpdateService extends Service {
Locator locator = new Locator();
Timer 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 void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
MyTimerTask myTimerTask = new MyTimerTask();
myTimer.scheduleAtFixedRate(myTimerTask, 0, 15000);
}
#Override
public void onDestroy() {
super.onDestroy();
myTimer.cancel();
stopSelf();
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
My toggle button code
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked)
{
startService(new Intent(this,AutoUpdateService.class));
}
else
{
stopService(new Intent(this,AutoUpdateService.class));
}
You got it right to use Service. Do not use Timer, since it is extra thread you do not need. What you can do is to use AlarmManager to schedule your service intent to be launched every 15 seconds (interval). This will trigger interval time your service by calling onStartCommand in your service where you can do whatever you need by reading (if need) intent from parameters of onStartCommand.
Hi I'm a complete beginner at Android development so I don't really know too much of what I'm doing. I keep getting nullpointerexecption and my program crashes whenever getActivity() is called. This includes in toast messages as well as when I try to start another activity with an intent. I'm not entirely sure how to use intents either so if that could be explained that would be great.
Here is the class that has the getActivity() calls as well as intent:
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Toast;
public class loginDialog extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState){
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.loginw)
.setItems(R.array.account_types, new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which){
if(which==0){
Toast.makeText(getActivity(),"todo",Toast.LENGTH_SHORT).show();
}else if(which==1){
Toast.makeText(getActivity(),"todo",Toast.LENGTH_SHORT).show();
}else if(which==2){
AlertDialog.Builder builder1=new AlertDialog.Builder(getActivity());
LayoutInflater inflater=getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.login_dialog,null);
builder1.setView(view);
builder1.setTitle("Login with Email Address");
builder1.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog1, int which) {
//Toast.makeText(getActivity(), "Cancel", Toast.LENGTH_SHORT).show(); //Force Closes. Nullpointer Exception? Probably because of getActivity()
//dialog1.dismiss();
}
});
builder1.setNeutralButton("Forgot Password",new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog1, int which){
dialog1.dismiss();
AlertDialog.Builder builder2=new AlertDialog.Builder(getActivity());
builder2.setTitle("Forgot Password");
builder2.setMessage("Enter your Email Address");
builder2.setPositiveButton("OK",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//TODO
}
});
builder2.setNegativeButton("Cancel",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//TODO
}
});
builder2.show();
}
});
builder1.setPositiveButton(R.string.login, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog1, int which) {
//Toast.makeText(getActivity(),"Login complete",Toast.LENGTH_SHORT).show(); //Force Closes. Nullpointer Exception? Probably because of getActivity()
dialog1.dismiss();
Intent intent = new Intent(getActivity(),Groups.class);
startActivity(intent);
}
});
Dialog dialog1 = builder1.create();
dialog1.show();
}
}
});
Dialog dialog=builder.create();
return dialog;
}
}
Here is the logcat (note this is only for the intent call because the other getActivity()s are commented out):
java.lang.NullPointerException
at android.content.ComponentName.<init>(ComponentName.java:77)
at android.content.Intent.<init>(Intent.java:3813)
at com.app.u.loginDialog$1$3.onClick(loginDialog.java:67)
at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:166)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
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:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
You should call getActivity after the onActivityCreated method has returned in the Overriden dialogfragment class. in ur case loginDialog class. that is the safe place to call getActivity
public class LoginDialog extends DialogFragment {
Activity mAct;
#Override
public void onAttach(Activity act) {
super.onAttach(act);
mAct = act; // use this mAct instead of getActivity() function
}
You cannot create the Intent inside the dialogue popup message So you should use like this Or declare inside your dialogue Like this it will help you Definitely...All the best
Context context = activity.getApplicationContext();
Intent intent = new Intent(context, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Try using getApplicationContext() instead
Intent intent = new Intent(getApplicationContext(), Groups.class);
startActivity(intent);
And remember to declare your new activity in your AndroidManifest file!
<activity android:name=".Groups"/>