I have a strange problem with my app. The App consists of one Service and one Activity, the service has to run "always" while the Activity is just an interface to control the service, and doesnt need to run a lot.
So I want to create the service in my Activity's onCreate() if it doesn't run yet, and then bind to it. The code looks like this:
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
mService= ((MyService.LocalBinder) binder).getService();
mService.setView(ChatdroidActivity.this);
}
public void onServiceDisconnected(ComponentName className) {
Controler = null;
}
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initUI();
if(!MyService.isRunning()){
Intent s= new Intent(this, MyService.class);
startService(s);
}
bindService(new Intent(this, MyService.class), mConnection,
Context.BIND_AUTO_CREATE);
while(mService == null){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mService.doSomeStuff();
}
The problem is the Service doesn't seem to start. The app is in the while loop till i disconnect the debugger, after the Android message, that my app freezed.
And while I was searching the Web for a solution, suddenly my Eclipse came up, with an active breakpoint in my Service's onCreate()-method, for like 2 seconds, then it terminates.
Logcat doesn't display any errors until I disconnect the debugger.
And the first line of my Services onCreate() is android.os.Debug.waitForDebugger();
Before I added that call, the debugger never attached to the service.
Does anyone know this problem or better, a solution?
What happens if you move the mService.doSomeStuff() to the onServiceConnected() ? You don't need to do a while() loop to wait for it
what does bindService return? It should return true in case nothing wrong happened
put some logging in onServiceConnected() to see when it gets called
what does your service do in the contructor? Is it hanging somewhere there?
Related
I want to be able to trigger an event when a user connects or disconnects a USB device. I have the following code:
public static boolean isConnected(Context context) {
Intent intent = context.registerReceiver(null, new IntentFilter("android.hardware.usb.action.USB_STATE"));
return intent.getExtras().getBoolean("connected");
}
The above is from another StackOverflow question.
How can I go about the problem I'm facing? I don't think it would be practical to check every x second if the state has changed. So, I checked online for an event listener about USB_CONNECTION, but I can't seem to find any. Actually, I did find a few but they were confusing and quite old. (A year or two ago.)
TRIED CODE
while(notFinished) {
if (!isConnected(this)) {
pause();
} else if (!mediaPlayer.isPlaying() && isConnected(this)) {
play();
} else {
Log.e("[ERROR]: ", "An error has occured at startSong!");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
^^^ Clearly not efficient, but it does work (somewhat). So, that's why I came over here to know if there was a listener for USB_CONNECTION_STATUS. I think this would be a lot faster.
You can use BroadcastReceiver for receiving connected and disconnected actions:
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getExtras().getBoolean("connected")) {
//start doing something for state - connected
} else {
//start doing something for state - disconnected
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction("android.hardware.usb.action.USB_STATE");
registerReceiver(receiver, filter);
This BroadcastReceiver will receive actions every time wen usb connected or disconnected.
Whenever my application is minimized I start a service that is sending pull requests to my HTTP server to check for notifications, when the application is brought back up the service gets terminated (along with the scheduled runnable). All works well until I decided to kill the application (slide it off the screen from the running apps list). Then for some reason the properties of the service get reset (even the static ones) and onStartCommand gets called again with it's first parameter Intent as null which is weird for me.
Here are some parts of the code
public class DnActivity extends Activity {
protected String cookieString = "";
protected String userAgent = "";
protected WebView webview;
#Override
protected void onStop() {
super.onStop();
try {
Intent mServiceIntent = new Intent(this, PullService.class);
mServiceIntent.putExtra("cookieString", cookieString);
mServiceIntent.putExtra("userAgent", userAgent);
startService(mServiceIntent);
} catch (Exception e) {
Log.d("DNev", e.getMessage());
}
}
#Override
protected void onStart() {
super.onStart();
Intent mServiceIntent = new Intent(this, PullService.class);
stopService(mServiceIntent);
}
#Override
public void onCreate(Bundle savedInstanceState) {
...
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
try {
cookieString = getCookieFromAppCookieManager(url);
} catch (Throwable e) {
Log.e("DNev", e.getMessage());
}
}
});
}
}
And the service
public class PullService extends Service {
protected static String cookieString;
protected static String userAgent = "Mobile APP for Android";
protected Service PullService = this;
protected ScheduledFuture interval;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
if (intent.hasExtra("cookieString")) {
cookieString = intent.getStringExtra("cookieString");
}
if (intent.hasExtra("userAgent")) {
userAgent = intent.getStringExtra("userAgent");
}
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
interval.cancel(true);
}
#Override
public void onCreate() {
super.onCreate();
Log.d("DNev", String.valueOf(cookieString));
Log.d("DNev", String.valueOf(userAgent));
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
interval = scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
public void run() {
Log.d("DNev", "1");
Log.d("DNev", String.valueOf(cookieString));
Log.d("DNev", String.valueOf(userAgent));
...
As I said, everything works fine until I destroy the activity, then the interval keeps running but cookieString and userAgent become their default values.
I need to be able to persist these values when the activity gets destroyed, how can I do that?
I'm not experienced in neither android nor java development, and I want to apologize if my code made anyone cry blood.
Here is the manifest entry for the service, it resides in <application
<service android:name=".PullService" android:exported="false"/>
All works well until I decided to kill the application (slide it off the screen from the running apps list).
When you kill the app (which I assume Force Stop from i.e. Settings -> Apps) then WHOLE app gets terminated, including its services. Everything stored in variables will go away with the process. If you want it to survive, you need to store it in persistent storage (i.e. in database or shared preferences).
Also I'd save this data once I received it, in onStartCommand() because if onDestroy() will not be called (which is not unlikely for abruptly killed process) then your data would be lost.
I start a service that is sending pull requests to my HTTP server to check for notifications
Don't. Use GCM to actually push notification to the app. Do not pull.
in the DnActivity.onDestroy() method, save the info somewhere, you could have the "shutting down" of the activity control the mServiceIntent and do alterations to it (like shutting it down as well)
For instance:
DnActivity.onDestroy(){
super.onDestroy();
stopService(mServiceIntent);
Intent mServiceIntent = new Intent(this, PullService.class);
mServiceIntent.putExtra("some_value", the_value);
mServiceIntent.putExtra("some_other_value", the_other_value);
startService(mServiceIntent);
}
I have a service that I am trying to run constantly as long as the user has it on. The problem is the service uses a ton of memory; I'm guessing because it notifies the users and displays images constantly. So I put the bulk of my code in another activity. The service just calls the activity.
The issue is that I'm trying to use the return Start_Sticky to restart the service when it needs to. It takes about 2 hours before it uses up enough memory to need to restart. When it does restart it doesn't do the onStartCommand am I missing something?
public class AUTOAlarmService extends Service {
#Override
public void onCreate() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent DI = new Intent(getBaseContext(), AUTOSERVICES.class);
DI.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(DI);
return START_STICKY;
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
I think you should reconsider some work done because your service is taking too much resources and that shouldnt be happening any way. There are many applications with a lot of services but non have problem of restarting the device for that matter.
However if you want to restart a service you have to stop and then start the service again.
stopService(new Intent(this, YourService.class));
startService(new Intent(this, YourService.class));
Hope it helps.
Is there anyway to check if onResume was called from the device waking up from sleep state in Android?
The reason why I need to check that is I don't want it to call a particular method if resumed from sleep state:
#Override
public void onResume() {
super.onResume();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())
&& !SomeCrazyMethodOrPropertyCheckingIfDeviceWakedUpFromSleep) {
processIntent(getIntent());
}
}
You might say "Take that processintent method out of onResume"... It's not an option, NFC P2P mode requires you to process the received NDEF message inside onResume.
I would recommend overriding onNewIntent() to handle the NFC intents:
#Override
public void onNewIntent(final Intent intent) {
setIntent(intent);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
processIntent(intent);
}
}
In processIntent() you can check whether the intent was handled already:
private void processIntent(final Intent intent) {
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
// Log.v(TAG, "Ignoring intent; already treated this intent.");
return;
}
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
// new intent; process it
...
}
Likely this will solve your problem.
I think you can try to do something with ACTION_SCREEN_ON :
register a receiver for it (you need to it in code, it won't work in manifest).
in the onReceive do something like:
MY_FLAG_JUST_WAKE_UP = true;
and in the onResume() :
if(!MY_FLAG_JUST_WAKE_UP){
doStuff();
}
MY_FLAG_JUST_WAKE_UP = false;
But, it need to be tested, I don't know if you will always receive the intent before the onResume() get called.
The client code for binding to a service, which is normally in the activity class; I'm trying to move it to the service class, so that the activity class would be as clean and small as possible.
i.e. basically trying to merge the code in the second box here into the first box = as much of it into the service class as possible
Single Line in Activity for Binding to Service
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Bind to service with this line only:
AService.bindService(this);
}
}
Static bindService and ServiceConnection Moved to Service
public class AService extends Service {
public String test = "I want to see this";
public static AService aService;
private static boolean isBound;
private static Context context;
// ... IBinder, onBind etc also here on service side
public static void bindService(Context context) {
try {
Log.i(TAG, "bindService Start");
if (!isBound && context != null) {
Log.i(TAG, "Binding");
context.bindService(new Intent(context, AService.class),
serviceConnection, Context.BIND_AUTO_CREATE);
isBound = true;
Log.i(TAG, "Bound");
}
} catch (Exception e) {
Log.e(TAG, "bindService", e);
}
}
private static ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
try {
Log.i(TAG, "onServiceConnected Start");
aService = ((AService.LocalBinder) service).getService();
if (aService != null)
Log.i(TAG, aService.test);
Log.i(TAG, "onServiceConnected Finish");
} catch (Exception e) {
Log.e(TAG, "onServiceConnected", e);
}
}
public void onServiceDisconnected(ComponentName className) {
try {
Log.i(TAG, "onServiceDisconnected");
aService = null;
} catch (Exception e) {
Log.e(TAG, "onServiceDisconnected", e);
}
}
};
public static void unbind() {
try {
Log.i(TAG, "unbind start");
if (isBound && context != null) {
Log.i(TAG, "Unbinding");
context.unbindService(serviceConnection);
isBound = false;
context = null;
Log.i(TAG, "Unbound");
}
} catch (Exception e) {
Log.e(TAG, "unbind", e);
}
}
}
But onServiceConnected is Never Called?
The log shows everything up to:
...
Bound
But NOT onServiceConnected Start or beyond
and no exceptions.
Note that when the same code was in the Activity, it works (when called with MyActivity.this)
What am I doing wrong?
Is this
AService.bindService(this);
much better than this?
bindService(new Intent(context, AService.class),
serviceConnection, Context.BIND_AUTO_CREATE);
And does ServiceConnection implementation sit in Activity really annoying your so much? I doubt that.
I don't see any point centralize everything into Service and then call a static method in the actual Service to start this Service from Activity. The best practice is to follow the standard way that Google's recommended to do things, by doing this in your way, you make your code obscure and confuse other people when reading your code (if you work in a team). It doesn't make any sense IMO.
Instead of put all your effort into isolate every single bit of service from activity, I would rather consider more on how to isolate business logic from activity and centralize them into service, and let Activity mostly focus on UI stuff.
Really hope that would help you.