My app is a video player which streams videos from a nas. Therefore the video is also playing in the background, I have running a startforeground service where the media player is hold.
So every time the activity starts I have to bind to the service, to be able to show the video. This is also required when rotation changed. Then when I want to bind to it, sometimes I don't bind to the already running service but It creates a new instance. So there are two instances of the service.
Yes, normally services should only be able to be instantiated one time, but in my case there are sometimes definitly 2 instances... :/
How can I prevent this? Had anybody already the same problem?
EDIT:
service gets started and bound with following code:
Intent serviceIntent = new Intent(getApplicationContext(), MediaPlayerService.class);
getApplicationContext().startService(serviceIntent);
Intent serviceIntent = new Intent(getApplicationContext(), MediaPlayerService.class);
getApplicationContext().bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
Sorry I wasn't clear because I was interested in which method in the activity life cycle you were doing this in. There are certain methods that are called on-orientation change. This other answer should point you in the right direction.I hope that helps.
Which activity method is called when orientation changes occur?
Related
I am currently having a really weird issue, and I don't know what could be causing it. Every time I close the app by swiping it away, and then start it again, the app seems to be duplicating its output to logcat, or in other words, it appears to be running multiple times.
This doesn't happen when I am connected to Android Studio, but without a cable connection, it does it without fail.
In my main activity I start my service like this:
Intent intent = new Intent(this, BluetoothService.class);
startService(intent);
bindService(intent, bluetoothServiceConnection, Context.BIND_AUTO_CREATE);
Stopping the service:
unbindService(bluetoothServiceConnection);
Intent intent = new Intent(MainActivity.this, BluetoothService.class);
stopService(intent);
EDIT I have made some changes in the way I stop and start my service, which seems to have solved my problem on Android 5.1.1, but not on Android 4.4.4, sadly.
I was thinking that maybe my logging process could be the problem, but destroying that process in my activity's onDestroy()-method didn't solve the issue either.
Starting the logging process:
logger = Runtime.getRuntime().exec(new String[]{"logcat", "-v", "time", "-f", logcatFile.getAbsolutePath(), " *:E"});
Stopping it:
logger.destroy();
If you start a service, depends how you define your service in the AndroidManifest.xml, if you have android:process=":yourProcess", if the process name start with ":" it will create a new process, that probably your log output multiple times.
Your code doesn't contains any logging information, nor did you provide a stacktrace with it. Your splash screen doesn't seem to be the issue, but you should replace the new thread with a delayed post to a handler to the looper thread (main thread) you're running in:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
finish();
}
}, 1500);
Instead of getApplicationContext() you could also use SplashActivity.this directly.
In your MainActivity you then need to make sure to unbind the service. Maybe also stop it, depending on what you need it for. Refer to Bound Services for more documentation and examples.
For making the Service terminate the documentation states
A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started or there are one or more connections to it with the Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's onDestroy() method is called and the service is effectively terminated.
That's why it works when the service isn't started at all. You try to stop the service in onDestroy() which is only called if the service is stopped. Your code looks like the service doesn't need to be started at all. But to do it correctly, just stop the service in the acivity's onDestroy() or utilize
onUnbind() or any other useful lifecycle event of the activity or service.
I have made the Intent service and designed it in such a way that it has capability of restart itself if killed by the OS , but if it is stopped by user it must have stop.
Every thing was going good. But Problem occured when I tried to implement message handler and Binding techniques.
What I have done
My sole purpose was getting the status from the service (which in my case is intent service) and update my views. For this I have implemented Message handler and start to bound the service .
I am binding my service in such a way
//This is my interface to get specific call back in activity
mReceiver = new DownloadResultReceiver(new Handler());
mReceiver.setReceiver(ListSuitClass.this);
serviceIntent = new Intent(DownloadService.ALARM_SERVICE);
serviceIntent.setClass(ListClass.this, DownloadService.class);
serviceIntent.putExtra("receiver", mReceiver);
serviceIntent.putExtra("requestId", 101);
startService(serviceIntent);
}
if (!mIsBound) {
bindService(serviceIntent, mConnection, BIND_DEBUG_UNBIND);
mIsBound = true;
}
Problem
I want to stop the service by stop button , But it stop for a while and starts over again .
I do not know what I am doing wrong , And what is starting again the service.
Please help me in stopping the service.
Note: I am running my service in a separate process.
As per the code, mIsBound might be the local variable of Activity. When you stop your activity and restart it, it will have the default value of boolean i.e. false and so bindService is called again and again. What you need to do is either make it static variable or store the service bind status in SharedPreferences and read value from it.
I don't know if this is possible, but I would like to do the next:
Imagine an app with 2 activities: MenuActivity and OtherPurposeActivity.
So, on the onCreate method of Menu I had run the Service. In the same Activity (Menu), I can easily "connect"(Edit: communicate) with this Service with no problems.
Then, I click the only button there is on MenuActivity, which starts OtherPurposeActivity. Here comes the question:
How can I connect to the Service I had run on MenuActivity? Is it possible? (I hadn't called stopService).
Thanks in advance.
Edit: Code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
/* Execute service */
Log.d("SERVICE", "Launching service");
Intent msgIntent = new Intent(MenuActivity.this, ServerProcessingService.class);
msgIntent.setAction(ServerProcessingService.ACTION_STATUS);
startService(msgIntent);
/* Connection to the IntentService */
IntentFilter filter = new IntentFilter();
filter.addAction(ServerProcessingService.ACTION_STATUS);
//filter.addAction(ServerProcessingService.ACTION_CONTROL);
rcv = new ProgressReceiver();
registerReceiver(rcv, filter);
}
So I can handle the communication with the ProgressReceiver class. But, what if I open another activity, and this service still running? Can I access to it?
How can I connect to the Service I had run on MenuActivity?
Another activity that wants to communicate with the service can use exactly the same method as MenuActivity. startService() will only start the service if it is not already running, and then send the intent to onStartCommand() in all cases, so it is all right to call start service from multiple activities.
As a commenter pointed out, if your activity requires ongoing communication with a service, you should bind to it.
Is it possible? (I hadn't called stopService).
An IntentService will stop itself if it has no work to do, so it doesn't matter that you did not stop it explicitly. If the service needs to continue running, don't use an intent service.
To be on the same page I will describe briefly how I understood your dilemma.
You have an IntentService perfroming some operation which provides at the end some results. You are starting this process in one activity(asynchronously of course) and switch immediately to another one. Now, you are not sure whether service will finish the work before you switch to second Activity and result will be lost.
Basically, approach with BroadcastReceiver would be a good choice but if you won't register on time the data will be lost and service will end it's work. You could let the service to store the result before it ends, in DB, file or even in memory(depending on data type). When your second Activity start you can check if there is data waiting for you, if not you can wait for BroadcastReceiver to deliver it.
You could also use Otto library which is far more advanced solution than BroadcastReceiver. It allows to return to registered observer(Activity) the last result and what is more important it will allow your service to check if any observer received the message. If not you could only then store last result.
I was playing around with services and dialogs, and I got a doubt. Within a dialog, I am starting a service like this:
Intent lock = new Intent(getActivity(),AppLockService.class);
getActivity().stopService(lock);
getActivity().startService(lock);
Now the first time I call the dialog through
dialog_name.show(getFragmentManager(), "dropbox");
Upon pressing the OK button, the intent is launched. Now later, during the same app execution, the dialog is triggered again ( which is according to my code logic -- nothing wrong here). The code in the dialog then stops the previously triggered intent and starts the new intent.
My question is this:
lock is a local intent variable as per my definition. So how does it know that it has to stop that particular service I have triggered here the first time? Would someone please explain this to me?
You don't have to keep track of the service in a variable because Android does it for you.
The way that the OS treats a service is that it will not allow more than one instance of the service be to running at any time.
So at any moment there are 0 or 1 instances of your service. If there are 0, no problem, the OS will ignore the call to StopService. If there is 1 instance, it must be the instance you started previously - so it will be stop that one.
I am conducting a background program that runs from x in x seconds to get new information. So far so good. The problem is that when I finish the application thread remains always active.
Is there any way to check if the application has ended?
thank you
You could make a Toast or AlertDialog box along with your code that finishes the activity to let you know that the application has ended.
If your task should stop when the activity stops being shown, you should not start the service but bind it to the activity. The task then will be automatically stopped as soon as the activity has finished. If multiple activities should use the service, bind it to each of them.
Here's how to bind the service:
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);