Service gets killed in Jelly Bean - android

I'm trying to fetch application's name when it hits foreground. I've accomplished this by running a background service in which I've implemented Runnable for running this service every second. This is working fine in all OS except in Jelly Bean. My service gets killed. I know that if an app consumes more RAM then it kills available background services to manage the required space. For example high resolution games. But I'll be loosing data. I implemented Foreground Services. Its working fine. My doubt is, does this effect any way in the matter efficiency or battery consumption?? Is there any other method other than foreground??
This is the service which I have made foreground.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
ReceiverRunning = true;
context = this;
Intent intent1 = new Intent(this, ComponentSelector.class);
PendingIntent pendingIndent = PendingIntent.getActivity(this, 1, intent1, 0);
Notification mNotification = new Notification(R.drawable.ic_launcher, "BackgroundApp", System.currentTimeMillis());
mNotification.setLatestEventInfo(this, "BatteryUSage", "Click to open to app", pendingIndent);
mNotification.flags = mNotification.flags|Notification.FLAG_ONGOING_EVENT;
startForeground(1000, mNotification);
// Start service if not started.
if (!ForegroundApp.isRunning == true) {
context.startService(new Intent(context, Brightness.class));
}
boolean has_tele = getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY);
if (has_tele == true) {
TelephonyManager teleman = (TelephonyManager) getBaseContext()
.getSystemService(Context.TELEPHONY_SERVICE);
if (teleman != null)
deviceId = teleman.getDeviceId();
}
uId = deviceInfo();
try {
NetworkInfo info = (NetworkInfo) ((ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE))
.getActiveNetworkInfo();
if (info != null) {
Log.d("wifiRun", "Network available");
ConnectivityManager conMan = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo.State wifi = null;
if (conMan.getNetworkInfo(1).isAvailable())
wifi = conMan.getNetworkInfo(1).getState();
if (wifi == NetworkInfo.State.CONNECTED
|| wifi == NetworkInfo.State.CONNECTING) {
wifiCheck = true;
context.startService(new Intent(context, WiFi.class));
Log.d("wifiRun","wifiCheck: " +wifiCheck);
} else {
Log.d("wifiRun","wifiCheck: " +wifiCheck);
}
}
} catch (Exception e) {
e.printStackTrace();
}
// Register for Screen On and Screen Off.
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
sReceiver = new ServiceDefinition();
registerReceiver(sReceiver, intentFilter);
//return super.onStartCommand(intent, flags, startId);
return START_STICKY;
}

I think, no other way. You can also make your service sticky (http://developer.android.com/reference/android/app/Service.html#START_STICKY) but making service foreground is more right way in this situation. Of course, your service will drain battery, so try do not use "heavy" operations in your service.
If you will provide source code of your service we will check that you implement all optimal.

Related

Send a notification only when my app is not running

I want to send a notification when an alarm starts the broadcastreceiver and my App is closed. On the Receive method, Works fine detecting when the app is running. But the else part is not working. The "send_notification" method only works if it is not inside the else. Even the System.Out is not working when app is closed.
public void onReceive(Context context, Intent intent) {
if (App_status.isAppRunning(context, "com.example.app")) {
System.out.println(TAG + " APP IS RUNNING");
} else {
System.out.println(TAG + " APP IS NOT RUNNING");
send_notification(context);
}
}
public static boolean isAppRunning(final Context context, final String packageName) {
final ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
final List<ActivityManager.RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
if (procInfos != null) {
for (final ActivityManager.RunningAppProcessInfo processInfo : procInfos) {
if (processInfo.processName.equals(packageName)) {
return true;
}
}
}
return false;
}
}
Why doesn't work the else part?
I tried also to create a String variable. Being null at the begining the activity and changing to "no" if app is running. Inside the if(App_status.isAppRunning(context, "com.example.app")).
So at the end asking if the variable is diferent of no send the notification. But also doesn't work.
Use alarm manager, for this :
AlarmManager alarmManager =
(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent =
PendingIntent.getService(context, requestId, intent,
PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null && alarmManager != null) {
alarmManager.cancel(pendingIntent);
}
For full guidance visit this developer android page

Android perform function while lock screen

I am writing an app that when battery reach some level the wifi will automatically shut done, my app works fine while screen is on, but it not do anything when the screnn is lock.
My app is like, start activity, user click the button to start the Service, the service will register the broadcastreceiveer to get the current level of battery, and braodcastreceiver will see if battery level reach the limit and decide to shut done wifi or not
I have try use isScreenOn() to find whether screen is on or off, but this also not work
here is my code
public class BatteryMonitor extends Service {
/*declear variables*/
private BroadcastReceiver batteryReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent){
/* get battery level*/
//Check is screen is on or not
boolean isScreenOn = powermanager.isScreenOn();
//set as 90 just for test function//
if(batteryLevel<=90){
if(isScreenOn==true){
if(isCharging == true && wifimanager.isWifiEnabled()){
//not do anything
}else if(isCharging == false && wifimanager.isWifiEnabled()){
wifimanager.setWifiEnabled(false);
}
}else{
if(isCharging == true && wifimanager.isWifiEnabled()){
//not do anything
}else if(isCharging == false && wifimanager.isWifiEnabled()){
wifimanager.setWifiEnabled(false);
}
}
}
}
};
public void onStart(Intent intent, int startId) {
wifimanager = (WifiManager)this.getSystemService(Context.WIFI_SERVICE);
powermanager = (PowerManager) getSystemService(Context.POWER_SERVICE);
registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
};
#Override
public IBinder onBind(Intent i) {
// TODO Auto-generated method stub
return null;
}
}
Create a Separate class for Receiver, register it into Manifest file for Battery change action. Then it will work even when screen is off.
Broadcast Receiver
read this link.
You need to sendBroadcast when you want to send a message to Receiver, make sure that you added proper Action String , in manifest for Receiver ,

Long running ADK Accessory (Service?)

I've spent days trying to get the android ADK connection running in a service rather then activity..... Anyone know if its even possible?
I would like to have the service handled inputStream and outputStream so I can read my Arduino for extended periods in the background.
When the activity returns to focus I will bind with the service and update the GUI. If this is possible I would eventually like to update a website with the live data from the service for remote monitoring.
Any help if appreciated. I'm new to programming and can't seem to find much info on this topic.
Thank you in advace for the help.
I'm also trying it and I've found out this.
http://robotgrrl.com/blog/2011/11/29/android-adk-background-service/
I was able to get a ADK connection running in the following way (not complete code. Only the basic building blocks):
First I have an activity that the receives adk intent broadcasts (android system service bases on the adk meta data and the manifest).
private static final String USB_ACCESSORY_ATTACHED = "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getIntent().getAction() != null && getIntent().getAction().equals(USB_ACCESSORY_ATTACHED)) {
Intent service = new Intent(this, ADKservice.class);
service.putExtras(getIntent());
startService(service);
Intent launch = new Intent(this, MainActivity.class);
launch.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(launch);
}
this.finish();
}
If the intent matches the adk string it will start the adk service and pass the intent information to the service, launch the user interface activity and finish itself.
The user interface (MainActivity) now binds to the service just like any other service so it can call public methods and/or receive data via the service callbacks (local broadcast's can also be used).
The ADKservice extends Runnable to monitor the usb connection. It also registers a receiver for adk disconnect so it can stop if the device gets disconnected:
#Override
public void onCreate() {
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver, filter);
mNotificationManager =(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("ADK Service")
.setContentText("Started");
startForeground(notifyID, mBuilder.build());
super.onCreate();
}
After onCreate has finished the service will call onStartCommand where the adk initialization starts.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartup " + mAccessory );
mAccessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (mAccessory != null) {
openAccessory(mAccessory);
}
return super.onStartCommand(intent, flags, startId);
}
private void openAccessory(UsbAccessory accessory) {
Log.d(TAG, "openAccessory: " + accessory);
UsbManager mUsbManager = (UsbManager) getApplicationContext().getSystemService(Context.USB_SERVICE);
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null) {
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
thread = new Thread(null, this, "ADKserviceThread");
thread.start(); // start runnable
}
public void run() {
// handle adk "usb" messages here
}
#Override
public void onDestroy() {
closeAccessory();
stopForeground(true);
super.onDestroy();
}
private void closeAccessory() {
try {
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
} catch (IOException e) {
} finally {
mFileDescriptor = null;
mAccessory = null;
}
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
closeAccessory();
stopSelf();
}
}
};
The handling of the connection might need some tweaks but the overall concept seems to work. I hope that helps everyone! It seems easy now but it took me a long time to here (I'm repetitively new to programming)
You should handle the loading of the accessory in the main activity like here, and then pass a reference to the accessory object to a service.
You can now bind the service from any activity and get access to the input/output streams.
You can also close the activity, and when you disconnect the accessory, the activity should catch the intent broadcast and relaunch to perform the closeAccessory routine.

How to execute a task every 6h or when net is available for Android?

Well, I want to check the version of a site (this part I know how) every 6h or so.
So, I was thinking about making a service for this and use AlarmManager for it.
Since I need Internet to check the version of the site, I need something to see if the internet is on or to see when it's turned on. After the time passed I'll
So my questions (yep, not just one!) are:
Does AlarmManager works even if the display goes to sleep? When the device wakes up it knows how many time as passed and if passed more that 6h it executes the task?
How to check when internet is available?
How to know when internet is turned on? (some kind of broadcast?)
Is this a good solution?
Alarm Manager:
The alarm manager does not have anything to do with the display state, so Yes it can work even if the screen is off.
Network Avaiability snippet:
public boolean isNetworkAvailable() {
Context context = getApplicationContext();
ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
boitealerte(this.getString(R.string.alert),"getSystemService rend null");
} else {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
return false;
}
This function will return true if the network is available, false if it is not (airplane mode, out of reach, etc.)
Don't forget to add permission in your manifest
A possible solution
Have broadcast receiver for the screen off & screen on events like below,
public class ScreenReceiver extends BroadcastReceiver {
public static boolean wasScreenOn = true;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// do whatever you need to do here
wasScreenOn = false;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// and do whatever you need to do here
wasScreenOn = true;
}
}
}
In this receiver give the logic for requesting if network is available..
About the alarm manager. Here is a possible code:
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis() + 10000, 6*60*60*1000, pendingIntent);
The first parameter influence how device behave:
RTC - alarm does not wake the device up; if it goes off while the device is asleep, it will not be delivered until the next time the device wakes up
RTC_WAKEUP - wake up the device when it goes off

How to implement Android Open Accessory mode as a service?

I've been playing around with the Android Open Accessory Development Kit. By following the DemoKit example provided by Google, I've had no trouble in adapting the solution to my application. I can detect, communicate, and detach the accessory just fine.
However, I would need to run the whole thing as a service. I have a base activity which is launched by the USB_ACCESSORY_ATTACHED intent (that is, when the accessory is connected), and that works fine. But as soon as I start my service and run identical code in it compared to my working solution within a regular activity, I'm receiving an IOException ("no such device") whenever I'm trying to communicate with the accessory (monitoring arduino side shows a successful USB connection). This happens even though I've specified the correct BroadcastReceiver within the service, registered it in the onStartCommand callback method, and set up the communication endpoints with openAccessory(). Relevant code is as follows.
#Override
public void onCreate() {
Log.d(TAG, "ONCREATE");
manager = UsbManager.getInstance(this);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
ACTION_USB_PERMISSION), 0);
// Register broadcastreceiver for filtering accessory events
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver,filter);
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "ONSTARTCOMMAND METHOD ACCESSED");
if (mInputStream != null && mOutputStream != null) {
return START_NOT_STICKY;
}
UsbAccessory[] accessories = manager.getAccessoryList();
mAccessory = (accessories == null ? null : accessories[0]);
if (mAccessory != null) {
if (manager.hasPermission(mAccessory)) {
openAccessory();
} else {
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
manager.requestPermission(mAccessory,
mPermissionIntent);
mPermissionRequestPending = true;
}
}
}
} else {
Log.d(TAG, "mAccessory is null");
}
return START_NOT_STICKY;
}
openAccessory method:
/**
* Open the accessory
*/
private void openAccessory() {
Log.d(TAG, "openAccessory: "+mAccessory);
mFileDescriptor = manager.openAccessory(mAccessory);
if (mFileDescriptor != null) {
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null,this,"AccessoryThread");
thread.start();
}
}
Any ideas for a possible solution?
The solution was simple.
if (intent.getAction().equals(USB_ACCESSORY_ATTACHED)) {
Intent i = new Intent(this, YourServiceName.class);
i.putExtras(intent);
startService(i);
}
Basically, copy the intent that you received when starting your activity that you use to launch the service, because the intent contains the details of the accessory that the ADK implementation needs.
Then, in the service proceed to implement the rest of ADK exactly as before.
At the moment I can't give you a matching solution to your problem. But may be this
github example shows you how to solve your problem:
I am going to analyse the code given on github to implement just the same thing you're going to do.

Categories

Resources