I am trying to bind an activity to a service and here is my code for that
The below one is the code for activity
Button start = (Button) findViewById(R.id.button1);
Button stop = (Button) findViewById(R.id.button2);
start.setOnClickListener(this);
stop.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v.getId() == R.id.button1)
{
Intent i = new Intent(Intent.ACTION_MAIN);
i.setClassName("org.example","org.example.ServicesActivity");
bindService(i, conn, 0);
}
else if(v.getId() == R.id.button2)
{
unbindService(conn);
counter.setText("Number of Binding issss");
}
}
public ServiceConnection conn = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("Service is disconnected");
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("Service is connected");
}
};
and this is the code for my service
IBinder mBinder = new LocalBinder();
#Override
public IBinder onBind(Intent intent) {
System.out.println("came to onBind in service");
return mBinder ;
}
#Override
public void onCreate(){
super.onCreate();
System.out.println("came to oncreate in service");
}
#Override
public void onStart(Intent intent,int startId){
super.onStart(intent, startId);
System.out.println("came to onstart in service");
}
public class LocalBinder extends Binder{
ServicesActivity getService(){
System.out.println("came to Localbinder getservice in service");
return ServicesActivity.this;
}
}
My service and activity are two different apps
My problem is that when i am pressing start button then the activity should bind to service but it not binding and it is not even showing any errors either
can you plz tell me where i am doing error???
Thanks
Did you run an activity from within the apk that contains the Service since it was installed? You can't install a stand-alone service and expect it to run before there is user interaction. The user has to run it at least once to get it out of the "stopped" state. Then the service can react to intents. This security feature was introduced in Android 3.1.
http://developer.android.com/about/versions/android-3.1.html#launchcontrols
Related
My app use a background music service.
I have a button to quit my app but I can't find anything to close my app and my service.
I bind my service to my activity.
I tried:
unbindService(serviceConnection);
myService().stopSelf();
stopService(new Intent(this, MediaPlayer.class));
and absolutely nothing works !!! The service continues.
How can I do to destroy my service and how can I do to close my app ??
Tx
EDIT:
I use this in the onCreate method
Intent intent = new Intent(this, serviceClass);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
And in the MediaPlayer class
public class LocalBinder extends Binder {
public MediaPlayer getService() {
return MediaPlayer.this;
}
}
public IBinder onBind(Intent intent) {
Log.i(TAG, "service bound");
init();
return mBinder;
}
And that...
But I dont know if I really need to start the service. Bind the service already starts it
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
Now I did this
#Override
public void onDestroy() {
player.stop();
super.onDestroy();
}
The onDestroy method works only if i unbind the service !
This doesnt work at all:
getService().stopSelf();
this.stopService(new Intent(this, MediaPlayer.class));
So, how can I stop the service and how can I close the app ?
This is what I do in my app. onDestroy() method from the activity will be called when you close your app.
private ServiceConnection musicServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.LocalBinder binder = (MusicService.LocalBinder) service;
musicService = binder.getService();
musicService.setCallbacks(MainActivity.this);
musicServiceBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "MusicService service disconnected (unbinded)");
musicServiceBound = false;
}
};
#Override
protected void onStart() {
super.onStart();
Intent intent1 = new Intent(this, MusicService.class);
bindService(intent1, musicServiceConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onDestroy() {
super.onDestroy()
if(musicServiceBound){
musicService.stopSelf();
unbindService(musicServiceConnection);
}
}
You wrote myService(), where you are creating another service using ().
For closing your app programmatically you can refer to this question.
I am currently working on a Pedometer application. At first, I started with one activity, the PedometerActivity. This activity started the service that is supposed to run in the background, and binds to it. The code is long so I'll just give sections of what I think will help in my question.
//Bind service
private ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
//binder to communicate with the service
PedometerService.PedometerBinder mBinder = (PedometerService.PedometerBinder)service;
mPedometerService = mBinder.getService();
mPedometerService.registerCallback(mCallback);
}
public void onServiceDisconnected(ComponentName className) {
mPedometerService = null;
}
};
private void startPedometerService() {
if (!isPedometerService) {
Log.v(TAG, "Start service");
isPedometerService = true;
//start service
Intent intent = new Intent(getApplicationContext(),
PedometerService.class);
startService(intent);
}
}
//Bind to the service
private void bindPedometerService() {
Log.i(TAG, "Bind service");
Intent intent = new Intent(PedometerActivity.this, PedometerService.class);
bindService(intent, mServiceConnection,
Context.BIND_AUTO_CREATE + Context.BIND_DEBUG_UNBIND);
}
//close connection with service
private void unbindPedometerService() {
Log.i(TAG, "Unbind service");
unbindService(mServiceConnection);
}
//Stop the service that had been started
private void stopPedometerService() {
Log.i(TAG, "Stop service");
if (mPedometerService != null) {
//stop service
Intent intent = new Intent(PedometerActivity.this, PedometerService.class);
stopService(intent);
isPedometerService = false;
}
}
#Override
public void onResume() {
Log.i(TAG, "onResume");
super.onResume();
startPedometerService();
bindPedometerService();
}
#Override
public void onStop() {
super.onStop();
Log.i(TAG, "onStop");
stopPedometerService();
}
public void onDestroy() {
super.onDestroy();
unbindPedometerService();
stopPedometerService();
}
In the service class that extends Service
/*Local service binding*/
public class PedometerBinder extends Binder {
public PedometerService getService() {
return PedometerService.this;
}
}
/*A client is binding to the service with bindService()
* Returns the IBinder object received in
* ServiceConnection.onServiceConnected(ComponentName,IBinder)*/
#Override
public IBinder onBind(Intent intent) {
return new PedometerBinder();
}
I then modified my application to have tablayout with 3 tabs hence 3 fragments. I pasted the code from PedometerActivity into PedometerFragment and modified it
//Bind service
private ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
//binder to communicate with the service
PedometerService.PedometerBinder mBinder = (PedometerService.PedometerBinder)service;
mPedometerService = mBinder.getService();
mPedometerService.registerCallback(mCallback);
}
public void onServiceDisconnected(ComponentName className) {
mPedometerService = null;
}
};
private void startPedometerService() {
if (!isPedometerService) {
Log.v(TAG, "Start service");
isPedometerService = true;
//start service
Intent intent = new Intent(getActivity().getApplicationContext(),
PedometerService.class);
getActivity().startService(intent);
}
}
//Bind to the service
private void bindPedometerService() {
Log.i(TAG, "Bind service");
Intent intent = new Intent(getActivity(), PedometerService.class);
getActivity().bindService(intent, mServiceConnection,
Context.BIND_AUTO_CREATE + Context.BIND_DEBUG_UNBIND);
}
//close connection with service
private void unbindPedometerService() {
Log.i(TAG, "Unbind service");
getActivity().unbindService(mServiceConnection);
}
//Stop the service that had been started
private void stopPedometerService() {
Log.i(TAG, "Stop service");
if (mPedometerService != null) {
//stop service
Intent intent = new Intent(getActivity(), PedometerService.class);
getActivity().stopService(intent);
isPedometerService = false;
}
}
#Override
public void onResume() {
Log.i(TAG, "onResume");
super.onResume();
startPedometerService();
bindPedometerService();
}
#Override
public void onStop() {
super.onStop();
Log.i(TAG, "onStop");
stopPedometerService();
}
public void onDestroy() {
super.onDestroy();
unbindPedometerService();
stopPedometerService();
}
The problem is am having trouble keeping the service running when I switch between tabs. I am using FragmentStatePagerAdapter and therefore when I navigate to the last tab, the first fragment (PedometerFragment) is unloaded. I have been able to save other variables in onSaveInstanceState but this does not seem to help since everything is restarted all over again.
You're using startService, so even if your bound components get destroyed, the service shouldn't be stopped. However, you're explicitly calling stopPedometerService() in onStop(), which is called when your fragment is no longer started.
Try simply removing stopPedometerService() from onStop() andonDestroy() in your fragments.
See: https://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html
This version of the pager is more useful when there are a large number
of pages, working more like a list view. When pages are not visible to
the user, their entire fragment may be destroyed, only keeping the
saved state of that fragment.
You need to bind service in the Activity class. Then you can use it from any attached Fragment via interface or public methods.
I have Problem understanding the Binding to a service
I've created a simple song player, with a service to play the song.
I've created a log to track the binding and unbinding.
the problem is when i exit the app Unbinding log appears but when i go back to the app there is no binding log message ,i'm able to control play and pause of the song though
public class PlayService extends Service {
MediaPlayer mPlayer;
public IBinder mBinder=new LocalBinder();
#Override
public void onCreate() {
super.onCreate();
Log.i("TAG","Create");
mPlayer=MediaPlayer.create(this,R.raw.askme);
}
//since we want the song to be played in the background then we need to start the service
#Override
public int onStartCommand(Intent intent,int flags, int startId) {
Log.i("TAG","Start");
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
stopSelf();
}
});
return Service.START_NOT_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.i("TAG","Bind");
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
Log.i("TAG","Unbind");
return super.onUnbind(intent);
}
#Override
public void onRebind(Intent intent) {
Log.i("TAG","ReBind");
super.onRebind(intent);
}
#Override
public void onDestroy() {
Log.i("TAG","Destroy");
mPlayer.release();
super.onDestroy();
}
//here are the play and pause methods frm the user
public void playSong(){
mPlayer.start();
}
public void pauseSong(){
mPlayer.pause();
}
public boolean isPlaying(){
return mPlayer.isPlaying();
}
//since Binder already Extends IBinder so
//we can create LocalBinder Class which extends IBinder Interface
public class LocalBinder extends Binder{
//this method for returning an instance of our service in the MainActivity
public PlayService getService(){
return PlayService.this;
}
}
}
and main Activity as following
public class MainActivity extends AppCompatActivity {
public static final String TAG ="TAG" ;
public PlayService mPlayService;
private Button mDownloadButton;
private Button mSongButton;
private boolean mBound=false;
private ServiceConnection mServiceConnection=new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//the iBinder object is the returned value from onBind() method in our service
mBound=true;
//we need to get an instance of our service PlayerService so we can play or Pause the song
PlayService.LocalBinder binder = (PlayService.LocalBinder) iBinder;
//and here finally we are getting an instance of our service
mPlayService= binder.getService();
if (mPlayService.isPlaying()){
mSongButton.setText("Pause");
}
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBound=false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDownloadButton=(Button) findViewById(R.id.download_button);
mSongButton=(Button) findViewById(R.id.song_button);
mDownloadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"downloading",Toast.LENGTH_LONG).show();
for (String song:Playlist.songs){
Intent intent=new Intent(MainActivity.this,StartDownloadService.class);
intent.putExtra(TAG,song);
startService(intent);
}
}
});
mSongButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//here we can play or Pause the song
//but first we need to know if we are already bound to the service
if (mBound){
if (mPlayService.isPlaying()){
mPlayService.pauseSong();
mSongButton.setText("Play");
}else {
//but here we need the service to be started and keep playing in the background
//even if we unbound from the service when we exit the App
Intent intent=new Intent(MainActivity.this,PlayService.class);
startService(intent);
mPlayService.playSong();
mSongButton.setText("Pause");
}
}
}
});
}
#Override
protected void onResume() {
Intent intent=new Intent(this,PlayService.class);
bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
super.onResume();
}
#Override
protected void onStop() {
super.onStop();
if (mBound){
unbindService(mServiceConnection);
mBound=false;
}
}
}
if someone can explain
You are starting your service twice in your code.
Once as a started service and then as a bind service. Remove the started service code and most probably it should work as intended.
Remove this from your code
Intent intent=new Intent(MainActivity.this,PlayService.class);
startService(intent);
mPlayService.playSong();
mSongButton.setText("Pause");
as you are binding service in on Resume() method.
Intent intent=new Intent(this,PlayService.class);
bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
You should start and bind your music service like this:
#Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart invoked !");
// Start/Bind to play back service
Intent serviceIntent = new Intent(this, PlayService.class);
if (isMyServiceRunning(PlayService.class)
&& mBound== false) {
this.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
} else {
this.startService(serviceIntent);
this.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
Log.i(TAG, "Media Player service is created new -------------------");
}
}
#Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop invoked !");
if(mBound) {
Log.i(TAG, "unbinding service !");
unbindService(mServiceConnection);
mBound= false;
}
}
To Check service is running or not:
/**
* Utility function to check if a service is running.
*/
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Hope this will help you !
I found the Reason
the system calls your service's onBind() method to retrieve the IBinder only when the first client binds. The system then delivers the same IBinder to any additional clients that bind, without calling onBind() again.
that's why i'm not getting the Log message from onBind() and onUnbind() method, but I've used a log message in onServiceConnected() and i got it when i ran the App again.
I'm trying to add background music to my game and I thought I could persist it across activities by starting the service and then just connecting and binding to it in different activities in order to control it. But my music stops playing when I try to establish a connection from my second activity. I'm very new to working with services, so I apologize for any simple mistakes.
From my MusicService class (extends Service)
private final IBinder mBinder = new ServiceBinder();
MediaPlayer mPlayer;
private int length = 0;
public static boolean STOP_ON_DESTROY = true;
// Binder subclass. Allows access from clients to the server
public class ServiceBinder extends Binder {
MusicService getService(){
return MusicService.this;
}
}
public MusicService() {}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate(){
super.onCreate();
}
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
return START_STICKY;
}
public boolean isPlaying(){
if(mPlayer != null){
return mPlayer.isPlaying();
}
return false;
}
public void stopMusic()
{
if(mPlayer != null){
if(mPlayer.isPlaying()) {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
System.out.println("stopMusic service fn");
}
}
This is the code I call in both my Main and secondary activities in order to interact with the service. The music stops during the connectToMusicService function in the secondary activity. The Main activity works great.
onCreate(){....
startMusicService();
MusicService.STOP_ON_DESTROY = true;
}
private void startMusicService() {
Intent musicIntent = new Intent();
musicIntent.setClass(getApplicationContext(), MusicService.class);
startService(musicIntent);
}
#Override
public void onStart(){
super.onStart();
// establish connection for binding to the service
connectToMusicService();
// bind to the service
bindToMusicService();
}
private void bindToMusicService() {
Intent intent = new Intent(this, MusicService.class);
bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);
MusicService.STOP_ON_DESTROY = true;
}
private void connectToMusicService() {
myServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.ServiceBinder binder = (MusicService.ServiceBinder) service;
mService = binder.getService();
if(!mService.isPlaying())
mService.startMusic();
isServiceBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("Service disconnected from main");
isServiceBound = false;
}
};
}
The only thing I do during my Main activity's onStop is
#Override
public void onStop(){
super.onStop();
if(mService != null) {
if (MusicService.STOP_ON_DESTROY) {
mService.stopMusic();
}
}
}
UPDATE: I got it working. My issue wasn't with service binding at all. It was with static STOP_ON_DESTROY variable I was using to manage whether the music should stop when leaving an activity. I cleaned that up and all is good now. Thanks!
First of all, do you need to bind at all? Or could starting the service be enough? Started services run until you stop them (except if killed by the system when resources are scarce). I am not sure there's any point binding from each of your activities.
Btw if your service should run and play music also when your activities are closed, consider making it a foreground service.
I have an aidl file defined as follows:
package com.erbedo.callalert;
interface RemoteCallAlert {
void notifyCallEnded();
}
The service is:
package com.erbedo.callalert;
public class CallAlert extends Service {
Filter callListener;
private final RemoteCallAlert.Stub mBinder = new RemoteCallAlert.Stub() {
#Override
public void notifyCallEnded() throws RemoteException {
// TODO
}
};
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "CallAlert Created", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "CallAlert Destroyed", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(this, "CallAlert Started", Toast.LENGTH_LONG).show();
callListener = new Filter();
TelephonyManager tm =
(TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(this.callListener, PhoneStateListener.LISTEN_CALL_STATE);
}
public void callEnded() {
// TODO
}
}
and the Activity that has to bind to the service is:
package com.erbedo.callalert;
public class DummyStart extends Activity {
Filter callListener;
RemoteCallAlert mService;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
Log.d("CONNECT","OK");
}
public void onServiceDisconnected(ComponentName className) {
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout l = new LinearLayout(this);
setContentView(l);
this.startService(new Intent(this, CallAlert.class));
}
}
The onServiceConnected isn't called. Am I missing something obvious?
startService() does not use a ServiceConnection. bindService() does.
Intent intent = new Intent(CallAlert.class.getName());
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
The onServiceConnected isn't called.
For binding with the service you need to call bindService(). It provide the persistence connection, and after connection establishment onServiceConnected() is called.
Second point:-
If you are using AIDL IPC mechanism then I think you need the communication between 2 diff processes/Application. Here you need to have same copy of .aidl file in both service and Activity side in same PACKAGE. Then you need to modify little bit in your Activity side..
you can find here
http://www.zestofandroid.blogspot.com/