My service does not start.
I used the following onCreate method within my service:
public void onCreate(Bundle savedInstanceState){
wsConnection = new WSConnection();
handler = new Handler();
Bundle b = savedInstanceState;
this.dbManager = b.getParcelable("object");
super.onCreate();
Log.i("prova","servizio attivato");
TimerTask task = new TimerTask(){
public void run(){
FindPendingData();
}
};
timer = new Timer();
//timer.schedule(task, cal.getTime());
timer.schedule(task, 0, 30000);
}
while, the following code starts my service:
Intent intent = new Intent(this, myService.class);
intent.putExtra("object", myObject);
startService(intent);
object extends Object and implements Parcelable
I also declare in the Manifest:
<service android:name="myPackage.myService" />
Any idea Where the problem may be?
EDIT: I tried removing the Bundle parameter and now the service starts! But I don't understand why! Someone can help me?
use onStartCommand(Intent, int, int) or onStart() instead of onCreate of Service for getting Intent data as:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// get intent data here
return START_STICKY;
}
as in comment OP says :
no error. I always use this code for starting service and usually
this works good
but if we see in doc onCreate() not take any parameter if you are overriding it
Related
I am building a game where I want the user to go through many activities in 20 seconds. Once the 20 seconds is over, I want to send the user to the GameOver screen. To run the timer in the background, I used a service. The issue is, the service doesn't seem to be running?
The weird thing is, that even the toast isn't showing. Here is the place where I call the service:
Here is the manifest:
Please let me know as to why the service or the timer aren't running. Thank you so much for all of your help, I really appreciate it! If you need any more code, just let me know and I will show you. Thanks!
:-)
{Rich}
Services can't interact with UI, which is what Toast does. If you want to do that, try using runOnUIThread along with getApplicationContext or the fancy way with binding/callbacks. Also, take a look at AlarmManager, might be a simpler solution instead of running a service.
BroadcastReciever should be a solution to get and to show the toasts. Just send the message from service and catch it in activity. Then use it wherever you want.
//Service class
final static String ACTION = "ACTION";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
intent = new Intent();
intent.setAction(ACTION);
intent.putExtra("StartToast", "Started!");
sendBroadcast(intent);
return START_STICKY;
}
//Activity class
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(MainActivity.this, ServiceClass.class);
myReceiver = new MyReceiver();
intentFilter = new IntentFilter();
intentFilter.addAction(ServiceClass.ACTION);
registerReceiver(myReceiver, intentFilter);
}
private class MyReceiver extends BroadcastReceiver {
public String startToast;
#Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
startToast = arg1.getStringExtra("StartedToast");
Toast.makeText(MainActivity.this, startToast, Toast.LENGTH_SHORT).show();
}
Once you register this receiver, you get the message and create a toast automatically when you send data with intent.putExtra(....); .
What I want to do is quite simple: my application offers the user to watch a maximum of 10 min of video, then it stops the video and gets back to my application (previous activity). The video is shown in an external player with that code:
Intent intentVideo = new Intent();
intentVideo.setAction(Intent.ACTION_VIEW);
intentVideo.setData(Uri.parse(url)));
startActivity(intentVideo);
Then a background Service check periodically if time is elapsed or not.
How can my service kill the video activity (where I can't add code or listeners, or whatever, because it is provided by an external app) and make my app go back to its previous activity when time is elapsed?
Thanks
One way to solve this problem is to define a BroadcastReceiver inside the Activity. When the Service needs to notify the Activity that the time is up, send a broadcast and receive it in the BroadcastReceiver. Then, inside the onReceive() call finish() on the Activity to kill it. Hope this helps.
Okay here's my final code if it can help, thanks to Egor.
Note: Two solution are possible to force stopping the player activity:
using startActivityForResult(intent, rq) / finishActivity(rq)
using FLAG_ACTIVITY_CLEAR_TOP
Be careful using finishActivity(), some external apps won't close because of their behavior. For me it worked well when I open videos using VLC player, but not working when I open videos with Dailymotion app.
ActivityThatLaunchesPlayer.java
public class ActivityThatLaunchesPlayer extends Activity
{
private BroadcastReceiver brdreceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
System.out.println("broadcast signal received");
//either
finishActivity(57); //57 is my arbitrary requestcode
//or either :
Intent intentback = new Intent(getApplicationContext(), ActivityThatLaunchesPlayer.class);
intentback.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intentback);
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//set the brdcstreceiver to listen to the slot
getApplicationContext().registerReceiver(brdreceiver, new IntentFilter("com.example.portail10.timeElapsed"));
//here we launch the player (android opens a new appropriate activity)
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setData(Uri.parse(uri));
startActivityForResult(intent, 57); //again arbitrary rqstcode
//here we start the service that watch the time elapsed watching the video
intentServ = new Intent(this, TimeWatcher.class);
startService(intentServ);
}
}
TimeWatcher.java
public class TimeWatcher extends Service
{
//... some code is missing, but the main idea is here
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
//send the broadcast when time's up
Intent intentbrd = new Intent();
intentbrd.setAction("com.example.portail10.timeElapsed");
sendBroadcast(intentbrd);
System.out.println("Brdcast sent");
stopSelf();
}
}, 0, 600000); //in ms = 10min
return START_NOT_STICKY;
}
This is more of a doubt. Currently, my code works fine, but I want to make sure I'm doing it the right way.
I have a service, which checks if the activity is running on the foreground. If it is, it sends a broadcast to the activity, so the activity updates some stuff on the screen.
I created an IntentFilter on the service:
com.harkdev.ServerStatus.SERVER_UPDATED
Here the service needs to know if the activity is on the foreground, so it uses the IsActivityRunning() method, which reads the running tasks from the ApplicationManager. This means that I need to set the GET_TASKS permission.
Being that both, the SERVICE and the ACTIVITY are on the same package, is there a better way to get this info?? And maybe try and avoid setting the GET_TASKS permission??
This is the code in my service:
if (IsActivityRunning()) {
Intent localIntent = new Intent(SERVER_UPDATED);
SendBroadcast(localIntent, null);
}
The IsActivityRunning() Method:
public bool IsActivityRunning() {
ActivityManager manager = (ActivityManager) GetSystemService(ActivityService);
IList<ActivityManager.RunningTaskInfo> runningTaskInfo = manager.GetRunningTasks(1);
ComponentName componentInfo = runningTaskInfo[0].TopActivity;
if (componentInfo.PackageName == "com.harkdev.ServerStatus")
return true;
return false;
}
And this is the code in my activity:
protected override void OnCreate (Bundle bundle) {
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
IntentFilter filter = new IntentFilter(ServerStatusCheckService.SERVER_UPDATED);
_receiver = new ServiceBroadcastReceiver ();
_receiver.Received += Receiver_Received;
RegisterReceiver(_receiver, filter);
}
First you're doing the wrong way to compare strings:
if (componentInfo.PackageName == "com.harkdev.ServerStatus")
It should be:
if ("com.harkdev.ServerStatus".equals(componentInfo.PackageName))
Second, if the service and the activity are in your app then I think the requirement to check for "same package" is not necessary.
To send information from the service to the activity, you can use ResultReceiver (available in API 3+):
When starting your service from the activity, you create a ResultReceiver, put it into the intent which starts the service.
In the service, extract the ResultReceiver and keep it. When you want to send information, use send().
In the activity, for example in onDestroy() you can trigger a command to notify the service that the ResultReceiver is invalid and it should be removed.
Edied
For example:
In your activity:
// Global variable.
private ResultReceiver mResultReceiver = new ResultReceiver() {
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Update the UI here...
}
}
When you start the service:
Intent i = new Intent(this, TheService.class);
// You can use different action names for different commands.
i.setAction("REGISTER_RECEIVER");
i.putExtra("ResultReceiver", mResultReceiver);
i.putExtra("ResultReceiver_ID", hashCode());
startService(i);
And in onDestroy():
Intent i = new Intent(this, TheService.class);
i.setAction("UNREGISTER_RECEIVER");
i.putExtra("ResultReceiver_ID", hashCode());
startService(i);
In your service:
import android.util.SparseArray;
// ...
private SparseArray<ResultReceiver> mReceiverMap = new SparseArray<ResultReceiver>();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if ("REGISTER_RECEIVER".equals(intent.getAction())) {
// Extract the ResultReceiver and store it into the map
ResultReceiver receiver = intent.getParcelableExtra("ResultReceiver");
int id = intent.getIntExtra("ResultReceiver_ID", 0);
mReceiverMap.put(id, receiver);
} else if ("UNREGISTER_RECEIVER".equals(intent.getAction())) {
// Extract the ResultReceiver ID and remove it from the map
int id = intent.getIntExtra("ResultReceiver_ID", 0);
mReceiverMap.remove(id);
}
// ...
}
seeing many questions about this but im unable to fix this.
I have this code
public class myBroadcastReceiver extends BroadcastReceiver {
private final String TAG = "myBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Consts.ANDROID_INTENT_ACTION_BOOT_COMPLEATE)){
Intent newinIntent = new Intent(context, ServiceBootCompleated.class);
context.startService(newinIntent);
}
}
}
It starts a Service and i can debug it using this line
android.os.Debug.waitForDebugger();
I see that return START_NOT_STICKY; is executed but still
the service is visible as a "running" service in the
Setttings>programs>Running Services
the onDestroy() is never called unless i stop it manually.
What do i have to do to stop it,
remove it from "Setttings>programs>Running Services " window?
Once you have completed the work you wanted to do in the background call stopSelf()
Be sure that any real work you do in the Service is done as a background thread and not in onCreate or onStartCommand.
See http://developer.android.com/reference/android/app/Service.html#ServiceLifecycle for more details on the Service Lifecycle.
Example:
public int onStartCommand(final Intent intent, final int flags, final int startId)
{
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
//do work
stopSelf();
}
},"MyWorkerThread");
thread.start();
return Service.START_NOT_STICKY;
}
on completion of task, you have to do context.stopService() for stopping this type of unbound service.
Regards,
SSuman185
I have a method in a service that I created, and I want to access this method from an Activity that implements a Progress Dialog. This method simply update my database, and it was returning an ANR problem, so I created a Thread and in this thread I want to call this method that is in my Service. I tried instantiating the Service, but the object is null
So, how to create an 'object' in my activity where I can access this method. Someone could help me with that implementation??
Thanks.
The code:
public class UpdateDBProgressDialog extends Activity {
private String LOG_TAG = "UpdateDBProgressDialog";
private TextView tv;
private ProgressDialog pd;
private Handler handler;
private RatedCallsService rcs;
private Intent intent;
public boolean mIsBound = false;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
pd = ProgressDialog.show(this, "Updating Database", "The application is updating the database. Please wait.", true, false);
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
pd.dismiss();
}
};
Thread thread = new Thread(){
public void run() {
try{
rcs.updateDB();// Here I'm trying to call the method that is from the service class. But it says 'rcs' is null.
handler.sendEmptyMessage(0);
}catch(Exception e){e.printStackTrace();}
}
};
thread.start();
new Thread(){
public void run(){
try{
Thread.sleep(10000);
if(!RatedCallsService.RUNNING){
Intent i = new Intent(UpdateDBProgressDialog.this, RatedCallsService.class);
UpdateDBProgressDialog.this.startService(i);
}
}catch(Exception e){e.printStackTrace();}
}}.start();
}
}
I just want an object of the service so I can call the method I created there.
When you start or bind a Service its onCreate method calls and whenever you Start/Bind it again, its onStartCommand method will call. Because service is already created.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent.getAction();
if (action.equals(ACTION_PLAY)) // where ACTION_PLAY="any.unique.name.play"
processPlayRequest();
else if (action.equals(ACTION_PAUSE)) // where ACTION_PAUSE="any.unique.name.pause"
processPauseRequest();
else if (action.equals(ACTION_SKIP))
processSkipRequest();
else if (action.equals(ACTION_STOP))
processStopRequest();
else if (action.equals(ACTION_REWIND))
processRewindRequest();
else if (action.equals(ACTION_URL))
processAddRequest(intent);
return START_NOT_STICKY; // Means we started the service, but don't want
// it to
// restart in case it's killed.
}
And call it like:
Intent serviceIntent = new Intent(this, ServiceToStart.class);
serviceIntent.setAction("any.unique.name.play"); // onClick of play button
startService(serviceIntent);
If you want to invoke an operation on a Service from an Activity, there are two options. One is to create an Intent with any data set as extras on the Intent, and then start the Service kind of like you have done in the code. Then in the Service's onStartCommand, pull out the extras and invoke the appropriate method on your Service. For this option, you probably want to use an IntentService. The other option is to bind to the Service and directly invoke methods on it. To do this you will need to declare your Service's operations using AIDL. See the API documentation on Service for details.