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

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;
}
};
}

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.

Android Studio Services onServiceConnected() never called while onBind() is

In my app, I am using bound services. However, while running the code, I start the service and bind to it(OnBind() method works), but afterwards OnStartService() is never called, and my service is equal to null.
Here is my service code:
public class MyService extends Service{
boolean toExit = false;
boolean isThreatDetectionOn;
boolean isDanger = false;
int counter;
class MyServiceBinder extends Binder {
public MyService getService()
{
return MyService.this;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.i("Bind", "thats good");
return null;
}
#Override
public void onDestroy() {
stop();
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
isThreatDetectionOn = true;
new Thread(new Runnable() {
#Override
public void run() {
start();
}
}).start();
return START_STICKY;
}
}
start() and stop() are method that run in the service that start generating random numbers and stop generating random numbers, respectively.
Here is the bind/unbind code for the service:
private MyService ListeningService;
private boolean isServiceBound = false;
private ServiceConnection serviceConnection;
bindService = (Button) findViewById(R.id.button7);
bindService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
Log.i("Great","Button Bind Clicked");
if(serviceConnection == null)
{
Log.i("Great","Service Connection is Null");
serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
MyService.MyServiceBinder myBinder = (MyService.MyServiceBinder)iBinder;
listeningService = myBinder.getService();
isServiceBound = true;
Log.i("Yes", "Service Connected");
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
isServiceBound = false;
Log.i("No", "Service DisConnected");
}
};
}
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
});
unbindService = (Button) findViewById(R.id.button8);
unbindService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (isServiceBound)
{
unbindService(serviceConnection);
isServiceBound = false;
Log.i("No", "Service DisConnected");
}
}
});
Even after onBind() is called(in the logs it says "Bind:thats good") isServiceBound still remains false when it should now become true because the service is now connected.

onDestroy() is not being called after going main->map->main->map with stopping service

onDestroy() is not being called after going main->map->main->map with stopping service in this case:
After Launching the app, the MainActivity is created which starts background tracking service. On the other hand, the user can use a checkbox list in the main activity to select his interested routes where the items of the checkbox list represents the routes.
After clicking the submit button, the alarmManager starts firing the data to the IntentService class every 30 seconds. Subsequently, connection with the server is established and retrieving data to the MapActivity is started after the user was redirected automatically to the MapActivity.
The user is able to stop and start the background service by using an icon in the menu of the both activities. I am facing problem to destroy the app in the case describes below.
With the current code:
After launching the app I can stop the service in the mainActivity and destory the app.
after launching the app when I change from the main activity to the map activity , I can stop and start the service as well as destroy the app with opening Mapactivity.
When I go as the following (mainActivity->mapActivity->MainAtivity->MapActivity) and closed the app with opening map view the app is not being destroyed and the service is not stoped. Also the onDestroy() in MapActivity is not being invoked. Here the app opens with the map view again.
But when I do the following:
adding startService(i)(as the code snippet four lines below) to the onStart() in the MapActivity after bindService I can destroy the app as well stoping and starting the service but the problem here is I dont want to start the service every time I am going from the MainActivity to the MapActivity since if the user stops the service in the MainActivity it must stay off when he goes from the main to the map.
#Override
protected void onStart() {
super.onStart();
// Bind to TrackingService.
Intent intent = new Intent(this, TrackingService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
Intent i = new Intent(this, TrackingService.class);
startService(i);
}
How can I destroy the app in this case in the MapActivity?
MainActivity:
public class MainActivity extends ActionBarActivity implements
AsyncTaskCallback {
boolean serviceStatus = true;
TrackingService mService;
boolean mBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.route_available);
// Start the TrackingService class.
Intent i = new Intent(this, TrackingService.class);
startService(i);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
System.out.println("ABC MainActivity onOptionsItemSelected was invoked.");
switch (item.getItemId()) {
case R.id.menu_toggle:
if (serviceStatus) {
item.setIcon(R.drawable.off);
item.setTitle("OFF");
serviceStatus = false;
mService.stopTrackingService();
} else {
item.setIcon(R.drawable.on);
item.setTitle("ON");
serviceStatus = true;
Intent i = new Intent(this, TrackingService.class);
startService(i);
System.out.println("ABC MainActivity onOptionsitemSelected ON");
}
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onStart() {
super.onStart();
// Bind to TrackingService.
Intent intent = new Intent(this, TrackingService.class);
//To start the onPrepareOptionsMenue() after returning from the map activity to change the icon of the toggle button.
invalidateOptionsMenu();
}
#Override
protected void onStop() {
super.onStop();
//13.08.15
// Unbind from the service
if (mBound) {
unbindService(mConnection);
System.out.println("ABC MainActivity onStop() - unbindService(mConnection) was invoked. " + mBound);
mBound = false;
}else{
System.out.println("ABC MainActivity onStop() - unbindService(mConnection) was invoked. " + mBound);
}
}
#Override
protected void onDestroy() {
Intent i = new Intent(this, TrackingService.class);
stopService(i);
mService.stopTrackingService();
}
private ServiceConnection mConnection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
}
};
}
MapActivity
public class MapActivity extends ActionBarActivity implements OnMapReadyCallback,
ConnectionCallbacks, OnConnectionFailedListener {
boolean serviceStatus;
TrackingService mService;
boolean mBound = false;
#Override
protected void onStart() {
super.onStart();
serviceStatus = getIntent().getExtras().getBoolean("ServiceStatusExtras");
if (serviceStatus) {
Intent i = new Intent(this, TrackingService.class);
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
startService(i);
System.out.println("ABC MapActivity onStart serviceStatus = " + serviceStatus);
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
//System.out.println("ABC Map onServiceConnected() - " + mBound);
}
#Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
//System.out.println("ABC Map onServiceDisconnected() - mBound");
}
};
#Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
markerMap.clear();
stopAlarm();
if(!serviceStatus){
Intent i = new Intent(this, TrackingService.class);
stopService(i);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_toggle:
if (serviceStatus) {
item.setIcon(R.drawable.off);
item.setTitle("OFF");
serviceStatus = false;
if(mService!=null){
mService.stopTrackingService();
}
} else {
item.setIcon(R.drawable.on);
item.setTitle("ON");
serviceStatus = true;
Intent i = new Intent(this, TrackingService.class);
startService(i);
}
}
return super.onOptionsItemSelected(item);
}
}
TrackingService class:
public class TrackingService extends Service implements AsyncTaskCallback,
LocationListener {
LocationManager lm;
private final IBinder mBinder = new LocalBinder();
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
detectLocation();
return START_NOT_STICKY;
}
private void detectLocation() {
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 12 * 1000, 0,
this);
}
public class LocalBinder extends Binder {
TrackingService getService() {
return TrackingService.this;
}
}
public void stopTrackingService(){
if(lm != null){
lm.removeUpdates(this);
}
}
}
}

Android, why is background thread stopped?

MainActivity starts my TestService in onCreate and bind in onStart method. AsyncThread is started in TestService onStartCommand. bind and unbind methods are called in correct sequences. All things work perfectly, absolutely no issue :).
Issue starts from here: If MainActivity is terminated then running Async thread is also stopped w/o any interrupt exception but TestService is still running which I can check at Running Application Setting.
Please help me to find out why thread stops working.
PS: I cross checked with Thread/Handler but same result.
MainActivity and Service code are here:
public class MainActivity extends Activity implements IServiceInterface {
boolean mBound = false;
TestService mTestService = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
Intent serviceIntent = new Intent(this, TestService.class);
startService(serviceIntent);
}
#Override
protected void onStart() {
super.onStart();
// Bind to LocalService
NSLogger.i("service binding....");
Intent intent = new Intent(this, TestService.class);
bindService(intent, mBindConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if (mBound) {
NSLogger.i("service unbinding....");
unbindService(mBindConnection);
mBound = false;
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mBindConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
NSLogger.i("UI is connected to service");
LocalBinder binder = (LocalBinder) service;
mTestService = binder.getTestService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
NSLogger.i("UI is disconnected from service");
mBound = false;
mTestService = null;
}
};
}
public class TestService extends Service implements Runnable, Handler.Callback{
// Binder given to inproc clients
private final IBinder mBinder = new LocalBinder();
#Override
public IBinder onBind(Intent intent) {
mUIIsBound = true;
return mBinder;
}
public boolean onUnbind (Intent intent) {
mUIIsBound = false;
NSLogger.i("unbind service");
return true;
}
public class LocalBinder extends Binder {
TestService getTestService() {
return TestService.this;
}
}
public void onDestroy() {
//NEVER CALLED.
}
public int onStartCommand(Intent intent2, int flags, int startId) {
NSLogger.i("TestService start!");
new DownloadConfiguration().execute();
return START_STICKY;
}
private class DownloadConfiguration extends AsyncTask<Void, Integer, Boolean> {
#Override
protected Boolean doInBackground(Void... params) {
try {
NSLogger.i("before sleep");
Thread.sleep(5000);
NSLogger.i("After sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
}

bindService not binding to service

So I have a bound service set up, but every time I call bindService() it never calls the onBind() method of my service and onServiceConnected() is never called. There is no error I can see, nothing is thrown.
private LoggingService mService;
private boolean mBound = false;
private boolean mLogging = false;
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;
}
};
...
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if(!mBound){
Intent intent = new Intent(getActivity(), LoggingService.class);
getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
}
I put breakpoints all over this. bindService() is definately called, but no matter how long I wait nothing in onServiceConnected() or anything in my service is called.
So when I get here, it throws a nullPointerException
logging.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mLogging){
Toast toast = Toast.makeText(getActivity(),
"Service stopping", Toast.LENGTH_LONG);
toast.show();
mService.stopLogging();
mLogging = false;
} else {
Toast toast = Toast.makeText(getActivity(),
"Service Starting", Toast.LENGTH_LONG);
toast.show();
mService.startLogging("dude.jsn");
mLogging = true;
}
}
});
Logging is a Button. No idea what I missed. This is being called from a fragment, but that shouldn't matter right? The context is still valid.
public class LoggingService extends Service {
public static final int LOG_INTERVAL = 500;
LocalBinder mBinder = new LocalBinder();
LoggingThread thread;
public class LocalBinder extends Binder {
LoggingService getService() {
return LoggingService.this;
}
}
...
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
Any help pointing out what I missed would be awesome.

Categories

Resources