Why Service is active only on MainActivity? - android

I start a Service this way on MainActivity:
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
boolean playerServiceBounded;
PlayerService playerService;
ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
playerServiceBounded = true;
LocalBinder localBinder = (LocalBinder)service;
playerService = localBinder.getServerInstance();
}
#Override
public void onServiceDisconnected(ComponentName name) {
playerServiceBounded = false;
playerService = null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intentPlayerService = new Intent(this, PlayerService.class);
bindService(intentPlayerService, serviceConnection, BIND_AUTO_CREATE);
buttonPrev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
playerService.prevSong();
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
if(playerServiceBounded) {
unbindService(serviceConnection);
playerServiceBounded = false;
}
}
}
and it seems to works perfect. Now, when I do the same on another Activity (i.e. PlayerActivity), which load from MainActivity:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String songName = (String) listView.getItemAtPosition(position);
startActivity(new Intent(getApplicationContext(), PlayerActivity.class)
.putExtra("intent_songs", mySongs)
}
});
It seems playerService on the PlayerActivity is always null:
public class PlayerActivity extends AppCompatActivity {
boolean playerServiceBounded;
PlayerService playerService;
ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
playerServiceBounded = true;
LocalBinder localBinder = (LocalBinder)service;
playerService = localBinder.getServerInstance();
}
#Override
public void onServiceDisconnected(ComponentName name) {
playerServiceBounded = false;
playerService = null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intentPlayerService = new Intent(this, PlayerService.class);
bindService(intentPlayerService, serviceConnection, BIND_AUTO_CREATE);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
playerService.mySongs = (ArrayList) bundle.getParcelableArrayList("intent_songs");
}
#Override
protected void onDestroy() {
super.onDestroy();
if(playerServiceBounded) {
unbindService(serviceConnection);
playerServiceBounded = false;
}
}
}
Basically:
playerService.mySongs = (ArrayList) bundle.getParcelableArrayList("intent_songs");
fails because playerService is null.
Where am I wrong?

Related

why public variables change in Binding Service after run App?

I use bind service in Android .I start Service and stop Service with button and it work correctly.The story: I press start service button so Service start then,I increase x with showint button and x increase well, then I close App without stopping service then run App again , but public x turn to zero and initial again.I need service without re-initial public variable.How can i do that? How can bind .
public class MainActivity extends AppCompatActivity {
BoundService mBoundService;
boolean mServiceBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView timestampText = (TextView) findViewById(R.id.timestamp_text);
Button shownum = (Button) findViewById(R.id.shownum);
Button stopService= (Button) findViewById(R.id.stop_service);
Button start = (Button) findViewById(R.id.start);
shownum.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (mServiceBound) {
timestampText.setText(mBoundService.shownum());
}
}
});
stopService.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (mServiceBound) {
unbindService(mServiceConnection);
mServiceBound = false;
}
Intent intent = new Intent(MainActivity.this,
BoundService.class);
stopService(intent);
}
});
start.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, BoundService.class);
startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
});
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
BoundService.MyBinder myBinder = (BoundService.MyBinder) service;
mBoundService = myBinder.getService();
mServiceBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
mServiceBound = false;
}
};
}
and BoundService class:
public class BoundService extends Service {
private IBinder mBinder = new MyBinder();
public int x;
#Override
public void onCreate() {
// super.onCreate();
Toast.makeText(this,"onCreate",Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
Toast.makeText(this,"onBind",Toast.LENGTH_SHORT).show();
return mBinder;
}
#Override
public void onRebind(Intent intent) {
Toast.makeText(this,"onRebind",Toast.LENGTH_SHORT).show();
super.onRebind(intent);
}
#Override
public boolean onUnbind(Intent intent) {
Toast.makeText(this,"UUUUnbind",Toast.LENGTH_SHORT).show();
return true;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this,"onDestroy",Toast.LENGTH_SHORT).show();
}
public String shownum()
{
x++;
return String.valueOf(x);
}
public class MyBinder extends Binder {
BoundService getService() {
return BoundService.this;
}
}
}
Starting from Android 8 (Oreo) all Services that should stay alive when the App is closed should be started using startForegroundService() and should show a statusbar icon while running.
If you don't do that the Service is killed when the App is closed.
However you should see some log in Logcat regarding WHY the Service is killed.

Service killed before starting loop

I am new in android development. My service killed before starting loop..
I started service from another activity like MainActivity
package com.example.ch_m_usman.sharedtasklist.Services;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
public class ReminderService extends IntentService {
public ReminderService() {
super("Reminder Service");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.e("check","")
//Loop does not start.
for (int i=0;i<5;i++){
Log.e("Inside for","");
}
}
}
//How to use loop in intent service
Use below code:
public class TaskConfirm extends IntentService {
private final IBinder mBinder = new LocalBinder();
public TaskConfirm() {
super("TaskConfirm");
setIntentRedelivery(true);
}
#Override
public void onCreate() {
super.onCreate();
//Initilise your objects here like below...
taskIdList=new ArrayList<String>();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return super.onStartCommand(intent, flags, startId);
}
#Override
protected void onHandleIntent(Intent intent) {
// get intent data here like below if required......
if (intent != null) {
String taskId=intent.getStringExtra("taskId");
}
// apply your loop here .......
for (int i=0;i<5;i++){
Log.e("Inside for","");}
}
public class LocalBinder extends Binder {
public TaskConfirm getService() {
return TaskConfirm.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
Start service like below from your activity :
Intent serviceIntent = new Intent(context, TaskConfirm.class);
// put some extra data if required
serviceIntent.putExtra("taskId","1");
startService(serviceIntent);
If you want to access this service in other activity then bind that activity to service:
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, TaskConfirm.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
TaskConfirm.LocalBinder binder = (TaskConfirm.LocalBinder) service;
mService = binder.getService();
mBound = true;
// do your task on service-connected...
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};

Android service pausing on certain device

My app uses a service which I have designed. Problem is the app works fine on some phones (like Gionee, Asus phones) but does not work on Nexus, One Plus or Moto. On theses devices the service pauses on minimising the app. These are my corresponding classes.
public class Sync extends AppCompatActivity {
Button listen;
Button stopListen;
SyncService syncService;
boolean syncServiceBound = false;
/* CreateActivity */
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_discoverer);
/*
Initialise
*/
listen = (Button)findViewById(R.id.btn_listen);
stopListen = (Button)findViewById(R.id.btn_stop_listener);
/*
* Check if device is connected via wifi
*/
ConnectivityManager connectivityManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if(networkInfo.isConnected()){
displayToast("Connected via wifi");
}else{
displayToast("Not connected");
}
/**
* Start broadcasting if device is not already broadcasting
* Start listening for broadcasts if not already listening
*/
listen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Intent syncServiceIntent = new Intent(getBaseContext(), SyncService.class);
bindService(syncServiceIntent, syncServiceConnection, Context.BIND_AUTO_CREATE);
startService(syncServiceIntent);
startPeerListUIThread();
}
});
stopListen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Intent syncServiceIntent = new Intent(getBaseContext(), SyncService.class);
if(syncServiceBound) {
unbindService(syncServiceConnection);
}
syncServiceBound = false;
stopService(syncServiceIntent);
stopPeerListUIThread();
}
});
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onDestroy(){
unbindService(syncServiceConnection);
super.onDestroy();
}
private ServiceConnection syncServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
SyncService.SyncServiceBinder binder = (SyncService.SyncServiceBinder) service;
syncService = binder.getService();
syncServiceBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
syncServiceBound = false;
}
};
}
and
public class SyncService extends Service {
private final IBinder syncServiceBinder = new SyncServiceBinder();
public SyncService() {
// initialise
}
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
// do something
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return syncServiceBinder;
}
#Override
public boolean stopService(Intent name) {
// do something
return super.stopService(name);
}
#Override
public void onDestroy() {
// do something
super.onDestroy();
}
public class SyncServiceBinder extends Binder {
SyncService getService() {
// Return this instance of SyncService so activity can call public methods
return SyncService.this;
}
}
}
Initially I thought using android M was the problem (the doze feature may have been interfering) but is not the case apparently.

Service stops when activity is destroyed

I have searched a lot on stackoverflow regarding this issue but nothing seems to work.
I am developing a music player which plays music by binding to a service. I have two activities.The first activity(called as AllSongs) provides me with the list of songs.When I select a song it starts another activity(called as SongUI) which plays the song by binding to a service.
Now when I move back to my AllSongs activity the music stops.Now when I select a song again,my SongUI activity is started and when I go back to my AllSongs activity, the music does not stop and plays in the background.I am not able to understand what is causing this issue. I think I am doing something silly somewhere but am not able to figure it out. I want songs to be played in the background same as any music player does.Here is the code.
AllSongs activity:
public class AllSongs extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.allsongs_activity);
getSongList();
from = new String[]{MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.DURATION};
to = new int[]{R.id.title_entry,R.id.artist_entry,R.id.duration_entry};
listView = (ListView) findViewById(R.id.listView);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,R.layout.singlesong,myCursor,from,to,SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent songUIIntent = new Intent(getApplicationContext(),SongUI.class);
songUIIntent.putExtra("position",id);
startActivity(songUIIntent);
}
});
}
private void getSongList() {
ContentResolver myContentResolver = getContentResolver();
myCursor = myContentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null,null,null,null);
if(myCursor!=null && myCursor.moveToFirst()) {
int titleColumn = myCursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int idColumn = myCursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
int artistColumn = myCursor.getColumnIndex(android.provider.MediaStore.Audio.Media.ARTIST);
long albumID = myCursor.getLong(myCursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
do {
long ID = myCursor.getLong(idColumn);
String title = myCursor.getString(titleColumn);
String artist = myCursor.getString(artistColumn);
songList.add(new currentSong(ID,title,artist));
}while (myCursor.moveToNext());
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
SongUI activity:
public class SongUI extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.song_ui);
button = (Button) findViewById(R.id.play);
isBound = false;
Intent receivedIntent = getIntent();
position = receivedIntent.getLongExtra("position",0);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
return super.onCreateOptionsMenu(menu);
}
public void playAudio(View view) {
Intent objIntent = new Intent(this,MyService.class);
if(!isBound)
{
objIntent.putExtra("position", position);
startService(objIntent);
isBound=true;
button.setBackgroundResource(R.drawable.play);
bindService(objIntent, myConnection, Context.BIND_AUTO_CREATE);
}
else
{
myServiceObject.pauseAudio();
button.setBackgroundResource(R.drawable.play);
isBound=false;
unbindService(myConnection);
}
}
public void stopAudio(View view) {
Intent objIntent = new Intent(this,MyService.class);
if(isBound)
{
isBound=false;
unbindService(myConnection);
stopService(objIntent);
}
else {
stopService(objIntent);
}
button.setBackgroundResource(R.drawable.play);
}
private ServiceConnection myConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
myServiceObject = ((MusicBinder) service).getService();
isBound = true;
}
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
#Override
protected void onDestroy() {
super.onDestroy();
if (isBound) {
unbindService(myConnection);
isBound = false;
}
}
}
MyService class
public class MyService extends Service {
#Override
public void onCreate() {
super.onCreate();
player = new MediaPlayer();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "on startCommand is called");
long id = intent.getLongExtra("position",0);
Uri contentUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
Log.d(TAG, "Service is Started");
player = MediaPlayer.create(this,contentUri);
player.start();
Intent notIntent = new Intent(this, SongUI.class);
notIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendInt = PendingIntent.getActivity(this, 0,
notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentIntent(pendInt)
.setSmallIcon(R.drawable.play)
.setTicker(songTitle)
.setOngoing(true)
.setContentTitle("Playing")
.setContentText(songTitle);
Notification notification = builder.build();
startForeground(NOTIFY_ID, notification);
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "on Bind is called");
return myBinder;
}
#Override
public boolean onUnbind(Intent intent){
Log.d(TAG,"onUnbind is called");
player.stop();
player.release();
return false;
}
public class MusicBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
public void pauseAudio() {
if(player.isPlaying()) {
player.pause();
}
}
#Override
public void onDestroy() {
Log.d(TAG,"on destroy is called");
stopForeground(true);
}
I have figured out where I was going wrong. I was calling unbindService(myConnection) in onDestroy of my SongsUI activity which was stopping the playback.
And the reason why this was not the case the second time round was that I was returning false in onUnbind method. So the system was not calling onBind method the second time and subsequently onUnbind was also not getting called. Hence the playback was also not stopping.

Google glass: Is there a way to start speech recognition from a UI service?

I have a glass app using LiveCards. As such, I don't explicitly have running activities, but just a background service that interacts with the LiveCard for information. At some point, I'd like to bring up a voice input. The problem is that the code samples tell you to use startActivityForResult, which isn't something I can do from within a service. So - is there a different way to bring this up, or can I not do this in my current configuration?
I was having this problem too, not with speech input but I needed to run an activity to get the information to display in a "low-frequency rendering" live card without the user bringing up a menu first. I think you could use an activity to get your text input then send it back to the service.
Most of the information on how to bind the service came from http://developer.android.com/guide/components/bound-services.html
MainService
This is the service that is started by "ok glass, ..." The layout just has a single TextView with the id text.
public class MainService extends Service {
private static final String LIVE_CARD_TAG = "my_card";
private final IBinder mBinder = new LocalBinder();
LiveCard mLiveCard;
TimelineManager mTimelineManager;
RemoteViews mViews;
#Override
public void onCreate() {
super.onCreate();
mTimelineManager = TimelineManager.from(this);
}
public class LocalBinder extends Binder {
MainService getService() {
return MainService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public int onStartCommand(Intent intent, int flags, int startId) {
mLiveCard = mTimelineManager.createLiveCard(LIVE_CARD_TAG);
mViews = new RemoteViews(this.getPackageName(),R.layout.activity_main);
mLiveCard.setViews(mViews);
Intent mIntent = new Intent(this, MenuActivity.class);
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mLiveCard.setAction(PendingIntent.getActivity(this, 0, mIntent, 0));
mLiveCard.publish(LiveCard.PublishMode.REVEAL);
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
// run the test activity after the initial text has displayed
Intent testIntent = new Intent(getBaseContext(), TestActivity.class);
testIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(testIntent);
}
}, 3000);
return START_STICKY;
}
public void updateText(String textString) {
mViews.setTextViewText(R.id.text,textString);
mLiveCard.setViews(mViews);
}
#Override
public void onDestroy() {
if (mLiveCard != null && mLiveCard.isPublished()) {
Log.d("debug", "Unpublishing LiveCard");
mLiveCard.unpublish();
mLiveCard = null;
}
super.onDestroy();
}
}
TestActivity
This is run after a delay from the MainService and updates the text on the live card automatically with no user input.
public class TestActivity extends Activity {
MainService mService;
boolean mBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, MainService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
#Override
public void onResume() {
super.onResume();
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
// this crashes if run right away, so give it a little time
mService.updateText("Updated from TestActivity");
finish();
}
}, 500);
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
MenuActivity
This is the activity that is set as the pending intent for the live card. It brings up a menu to exit or update the text when the touchpad is tapped.
public class MenuActivity extends Activity {
MainService mService;
boolean mBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, MainService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
#Override
public void onResume() {
super.onResume();
openOptionsMenu();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.stop:
stopService(new Intent(this, MainService.class));
return true;
case R.id.update:
mService.updateText("Updated from MenuActivity");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onOptionsMenuClosed(Menu menu) {
finish();
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}

Categories

Resources