I have a service that has various methods and all they do is give a logcat message but these methods doesn't seem to be called even though I have created a instance of that service in my activity class.
My service class code is-
public class service extends Service {
IBinder ob=new My_Ibinder();
public class My_Ibinder extends Binder{
public service get_MyService(){
return service.this;
}
}
#Override
public void onCreate() {
super.onCreate();
Log.e("SERVICE CREATED","");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("SERVICE OnStartCommand","");
return super.onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
Log.e("SERVICE onBind","");
return ob;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("SERVICE DESTROYED","");
}
String data(){
Log.e("SERVICE data method","");
return "DATA SUCCESSFULLY TRANSFERRED";
}
public void ok(){
Log.e("SERVICE ok method","");
}
}
Here the methods I call are data() and ok().My activity class is-
Button start,stop,data,check;
TextView tv;
service ser;
Boolean flag=false;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start=(Button)findViewById(R.id.start);
check=(Button)findViewById(R.id.check);
stop=(Button)findViewById(R.id.stop);
data=(Button)findViewById(R.id.data);
tv=(TextView)findViewById(R.id.tv);
start.setOnClickListener(new OnClickListener(){public void onClick(View v){ bindService(new Intent(MainActivity.this,service.class),sc,Context.BIND_AUTO_CREATE); }});
stop.setOnClickListener(new OnClickListener(){public void onClick(View v){ unbindService(sc); flag=false; }});
data.setOnClickListener(new OnClickListener(){public void onClick(View v){ ser.ok();tv.setText(ser.data()); }});
check.setOnClickListener(new OnClickListener(){public void onClick(View v){ Log.e(""+flag,"sfsfsdfdssfsdffsdfs"); }});
}
private ServiceConnection sc=new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
My_Ibinder ob=(My_Ibinder)service;
ser=ob.get_MyService();
flag=true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
flag=false;
ser=null;
}
};
On clicking the button I don't get any logcat message. Neither from the methods I need to call, nor from the onCreate(),onBind() and onDestroy() methods which should have been called if the service is successfully created.
I've checked running processes in settings and this service doesn't exist over there.Strangely, if I start the service with startService(intent) then it seems to work fine(although I'm not able to communicate with it). I guess there is some problem with Binding the service.
Kindly Help.
Finally got it... Such a silly silly mistake I've done. While giving logcat message I didn't added a text attribute to it and it just had a tag. Now that I've added a text to it, it works perfectly. Such a small yet important point to be noted. Certainly we all use logcat messages to DEBUG our program but this time the PROBLEM was LOGCAT itself. Never gonna forget this one !!!
Refer http://developer.android.com/guide/components/aidl.html to communicate service from activity.
Related
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.
To know the difference between IntentService and Service in Android, I created the below posted small test of a Service class. The MainActivity has a Button, when pressed, the
service will be started using startService() as shown below in the code, which will result in a call to onStartCommand(). In onStartCommand(), i run a loop for 10 seconds, and I
expected that, that loop will block the UI "the butoon". Actually that what happened exactly when I first time start the Service, but when I press the button after the 10 seconds
elapsed, it will result in a call to onStartCommand() but the log message inside the onStartCommand() never get displayed plus the UI is never blocked.
can anyone please explain what the body of the onStartCommand() is executed and blocks the UI only when the Service first started and never afterwards?
MainActivity
public class MainActivity extends AppCompatActivity {
private Button mbtnSend = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.mbtnSend = (Button) findViewById(R.id.btn_send);
this.mbtnSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MyService.class);
startService(intent);
}
});
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(this.mBCR_VALUE_SENT, new IntentFilter(MyIntentService.INTENT_ACTION));
this.mbtnSend = (Button) findViewById(R.id.btn_send);
this.mbtnSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MyIntentService.class);
intent.putExtra("intent_key", ++i);
startService(intent);
}
});
}
}
MyIntentService:
public class MyService extends Service{
private final String TAG = this.getClass().getSimpleName();
private long mStartTime;
#Override
public void onCreate() {
super.onCreate();
Log.w(TAG, SubTag.msg("onCreate"));
this.mStartTime = TimeUtils.getTSSec();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w(TAG, SubTag.msg("onStartCommand"));
while ( (TimeUtils.getTSSec() - this.mStartTime) <=10) {
Log.w(TAG, SubTag.msg("time: " + (TimeUtils.getTSSec() - this.mStartTime)));
SystemClock.sleep(1000);
}
return Service.START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.w(TAG, SubTag.msg("onBind"));
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.w(TAG, SubTag.msg("onDestroy"));
}
}
You are setting mStartTime to TimeUtils.getTSSec() in onCreate(), which means that it will get intialized only once.
Afterwards, onStartCommand() is called, but the mStartTime timestamp is not being updated, so the while loop never runs.
I believe that moving the line where you initialize mStartTime to onStartCommand() before the while loop will make your thread hang again.
For a demo I print a Toast after Evert 10 sec. using Service class.
It works fine, I'm getting the Toast after every 10 sec if I am on the Activity when I leave the app, Service is not giving the o/p.
But I want to that toast either I'll kill the App or back press Here is code snippet :
ServiceDemo.java
public class ServiceDemo extends Activity {
private Handler myHandler = new Handler();
private Runnable drawRunnable = new Runnable() {
#Override
public void run() {
as();
myHandler.postDelayed(this, 10000);
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_demo);
myHandler.postDelayed(drawRunnable, 10000);
startService(new Intent(this, MyService.class));
}
public void as(){
startService(new Intent(this, MyService.class));
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
}
Service.java
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "HOHO Service Created...", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "Service Started...", Toast.LENGTH_LONG).show();
}
}
Edit 1
moveTaskToBack(true);
I put this into the onBackPressed method I Service give the o/p if I am not on the screen but When I kill the App, Service not responding
I think you need to override onStartCommand instead of onStart()
like:
public int onStartCommand(Intent intent, int flags, int startid)
{
Toast.makeText(this, "Service Started...", Toast.LENGTH_LONG).show();
return Service.START_STICKY;
}
i think AlarmManager is what you want.
You have to user AlarmManager, here's an example : Alarm Manager Example
Your task will be executed even if the application is terminated.
But if the application is killed by the user, the Alarm will be canceled. See this discussion How to create a persistent AlarmManager
I've got a service:
public class FileObserverService extends Service {
private FileObserverForNewFirFiles fObs;
#Override
public void onCreate() {
Log.i("FILE_OBSERVER_SERVICE: ", "INSIDE ONCREATE()");
File f = new File("/mnt/sdcard/Bluetooth");
createFileObserver(f);
}
public void createFileObserver(File f) {
if(!f.isDirectory()) {
Log.i("FILEOBSERVER: ", "FILE NOT A DIRECTORY!");
}
else {
fObs = new FileObserverForNewFirFiles(f.getAbsolutePath());
}
}
#Override
public void onStart(Intent i, int startid) {
fObs.startWatching();
Toast.makeText(this.getApplicationContext(), "start monitoring file modification", Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
fObs.stopWatching();
Toast.makeText(this.getApplicationContext(), "stop monitoring file modification", Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
From my Main Activity, I call this class this way:
startService(new Intent(ThisClass.this, FileObserverService.class));
I thought that the onCreate method would print out something to the LogCat, referring to the first line of this method. But it doesnt seems to do it. Any hit?
I think what you really want is an IntentService
http://developer.android.com/reference/android/app/IntentService.html
just replace your method signature of onCreate
with onStartCommand
Basically you haven't done everything you need to do to get a regular old service going and IntentService will do all that work without any more effort from yourself.
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