How can I detect when and how long the charger is plugged?
I have class which extends BroadcastReceiver and override onReceive. I need to check start and end charging and duration time, but I don't know where to start. Could you please help me?
I have class which extends BroadcastReceiver and override onReceive. I
need to check start and end charging and duration time, but I don't
know where to start.
At first you need to create correct BroadcastReceiver that will listen for Battery charging changes. You can create it statically via Manifest:
<receiver android:name=".BatteryReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
</intent-filter>
</receiver>
Then your Java class must match it's name:
public class BatteryReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// do your stuff
}
}
Or you can create BoadcastReceiver dynamically and you can bound it into Service or Activity (it depends on your needs):
private void registerChargingReceiver() {
if (intentFilter == null) {
intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
}
if (receiver == null) {
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent i) {
// changer is connected
if (i.getAction().equals(Intent.ACTION_POWER_CONNECTED)) {
// do proper actions
}
// changer is disconneted
if (i.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
// do proper actions
}
}
};
}
// registering receiver
registerReceiver(receiver, intentFilter);
}
How can I detect when and how long the charger is plugged?
It can be achieved in more possible ways. For sure you need to save somewhere time when charger is connected and disconnected and then substract times:
long chargingTime = endChargingTime - startChargingTime;
And you can use SharedPreferences where you'll save your times (pseudo-code):
if (intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)) {
// remove time when charger was diconnected (last before)
prefs.edit().remove("chargingEndTime");
// save time when charged is connected
prefs.edit().putLong("chargingStartTime", System.currentTimeMillis());
prefs.edit().commit();
}
if (intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)) {
// save time when charger is disconnected
prefs.putLong("chargingEndTime", System.currentTimeMillis()).commit();
}
Hope it'll help to solve your problem you're facing.
Related
I'm trying to create an application that has a constant running service which will log and display to the user everytime they unlock or change the phones state from screen off to screen on.
Is this possible without using the Log cat through the P.C?
Yes you can do it using Broadcast Receiver. Android system sends always broadcasts for specified changes. You can handle this broadcasts using Broadcast Receiver.
Example:
We will create a new Broadcast Receiver to handle the Screen On and Screen Off state:
public class PhoneStateBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//we will handle here the activities which will tell us that
// the screen state has changed
if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)){
//write log that the screen is off
}else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
//write log that the screen is on
}
}
}
All what you need is to declare this BroadcastReceiver in Android Manifest.xml
file:
<receiver android:name="yourpackage.PhoneStateBroadcastReceiver">
<intent-filter>
</intent-filter>
</receiver>
And after that you should start your PhoneStateBroadcastReceiver on yout
Service onCreate Method:
//...
public void onCreate(){
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
PhoneStateBroadcastReceiver pSReciever = new PhoneStateBroadcastReceiver();
registerReceiver(pSReciever, filter);
}
My app has a service that add a floating button to WindowManager.
I want to remove my floating button from WindowManager When user press the power key and turn screen off. So when user turn screen on my floating button does not conceal (mask) android pattern screen lock.
I add following code to my Service but it doesn't work !
Should I add any permission or my service must run in background?!
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
try{
// Remove Floating Button from Window Manager
MyWindowManager.removeView(floating_btn);
// Stop Service
stopSelf();
}
catch (Exception e)
{
//Log Error
}
}
}
}
Normally you would declare a receiver in your manifest. Something like this
<receiver android:name="com.whatever.client.Receiver"
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF" />
</intent-filter>
</receiver>
For some reason (not sure why), you don't seem to be able to do this for SCREEN_OFF or SCREEN_ON. So you have to register it programmatically.
As a test, I made a simple app.
public class App extends Application {
#Override
public void onCreate() {
super.onCreate();
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
startService(new Intent(context, MyService.class));
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(receiver, filter);
}
}
With a simple service.
public class MyService extends IntentService {
public MyService() {
super("MyService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.e("MyService", "Screen was turned off!");
}
}
I've got the same problem and I'm working on it now. In your case it didn't work because 1) your "stopSelf()" have to in class extended by Service, not by BroadcastReceiver. 2) if you want to remove a view from window manager you have to somehow pass(the information of view) that view from that method where you'd declared it to method where you want to remove that view
First,I have searched for the question and found about 2-3 stackoverflow links but I dont get a definite answer.Basically,my app needs to start a activity when the phone is docked (any type of dock) or when screen is off.I registered a broadcast receiver in manifest:
<receiver android:name=".BootReciever">
<intent-filter >
<action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
<action android:name="android.intent.action.SCREEN_OFF"/>
</intent-filter>
</receiver>
And in my class:
public class BootReciever extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(Intent.ACTION_DOCK_EVENT)){
//work for dock
}
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
//work for screen off
}
}
}
But both doesnt work.My work is not done is both the cases.I read about I have to do it in services but since I have never worked with my own service and I fell android.developers.com is a bit of pro friendly,I have difficulty getting it to work.Can somebody say me how to I achieve the above?And my app has to listen for it as long service.So even when my app isnt in foreground.Thanks for your help.
The SCREEN_OFF has definitely to be registered programatically (see this link for instance, it'a a protected intent):
public class MainActivity extends Activity {
BroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TAG", "on or off");
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
Log.d("TAG", "Register receiver");
registerReceiver(receiver, filter);
} catch (Exception e) {
Log.d("TAG", "Caught: " + e.getStackTrace());
}
}
#Override
public void onDestroy() {
super.onDestroy();
try {
Log.d("TAG", "Unregister receiver");
unregisterReceiver(receiver);
} catch (Exception e) {
Log.d("TAG", "Caught: " + e.getStackTrace());
}
}
}
For the ACTION_DOCK_EVENT I would assume something else being wrong. May be it doesn't work due to the combination with ACTION_SCREEN_OFF, may be it's due to a naming issue (I wouldn't expect a relative path for .BootReciever, for instance; check, if a full qualified class name works).
Hope this helps .... Cheers!
Receivers for these kinds of intents need to be registered dynamically in the code.
this.receiver = new BootReceiver();
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_DOCK_EVENT);
this.registerReceiver(receiver, filter);
You could do this in any activity (register in onStart(), un-register in onStop(), see visible lifetime section) or in you application object.
The problem with dynamic registration though is your application has to be started before BootReceiver can receive intents.
I'm using C2DM, my BroadcastReceivers propagate the C2DM events to a local service. the service complete the registration by sending the id to my webserver pus it's responsible for letting the device know about new messages, however if the application (one of the activities) is up we want to send an intent to that activity with the new data so it can be updated, if not than the NotificationManager is used to notify the user.
The issue is, how to know the activity is running ? the Application object is not an option since the Service is part of the application it's obviously going to be present. unregister in the onDesroy of each application is also not an option since it may occur in orientation change...
Any standard way to get it done ?
Solution 1:
You can use ActivityManager for Checking if Activity is Running or not:
public boolean isActivityRunning() {
ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> activitys = activityManager.getRunningTasks(Integer.MAX_VALUE);
isActivityFound = false;
for (int i = 0; i < activitys.size(); i++) {
if (activitys.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfo{com.example.testapp/com.example.testapp.Your_Activity_Name}")) {
isActivityFound = true;
}
}
return isActivityFound;
}
need to add the permission to your manifest..
<uses-permission android:name="android.permission.GET_TASKS"/>
Solution 2:
Your can use an static variable in your activity for which you want to check it's running or not and store it some where for access from your service or broadcast receiver as:
static boolean CurrentlyRunning= false;
public void onStart() {
CurrentlyRunning= true; //Store status of Activity somewhere like in shared //preference
}
public void onStop() {
CurrentlyRunning= false;//Store status of Activity somewhere like in shared //preference
}
I hope this was helpful!
The next approach would work well if you want to handle incoming Google Cloud message (C2DM) by your activity (if any is running) or issue a notification if no activities are running.
Register one BroadcastReceiver in the manifest file. This receiver will handle C2D messages whenever application not running. Register another BroadcastReceiver programmatically in your activity. This receiver will handle C2D messages whenever activity is running.
AndoroidManifest.xml
<receiver
android:name=".StaticReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.mypackage" />
</intent-filter>
</receiver>
MyReceiver.java
public class StaticReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Trigger a Notification
}
}
MyActivity.java
public class MyActivity extends ActionBarActivity {
#Override
protected void onResume() {
super.onResume();
final IntentFilter filter = new
IntentFilter("com.google.android.c2dm.intent.RECEIVE");
filter.addCategory("com.mypackage");
filter.setPriority(1);
registerReceiver(dynamicReceiver, filter,
"com.google.android.c2dm.permission.SEND", null);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(dynamicReceiver);
}
private final BroadcastReceiver dynamicReceiver
= new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Handle C2DM
// blocks passing broadcast to StaticReceiver instance
abortBroadcast();
}
};
}
Note! To catch broadcasts first, the priority of dynamicReceiver IntentFilter must be higher than priority of StaticReceiver instance IntentFilter (default priority is '0').
PS. It looks like broadcasts issued by Google Cloud Messaging Service are ordered broadcasts. Original idea author: CommonsWare
Copied from here.
you can use a static variable within the activity.
class MyActivity extends Activity {
static boolean active = false;
public void onStart() {
active = true;
}
public void onStop() {
active = false;
}
}
Easiest way to check that whether an Activity is running or not is:
Context context = MyActivity.this;
if (! ((Activity) context).isFinishing()) {
// Activity is running
} else {
// Activity has been finished
}
Note: If activity is not running you should not perform any UI related operation.
I've found a lot of pages about this in the web, but none of them helped me. I've been for hours stucked in this problem. That's why i decided to make my own question.
What I want to do is an application that receives an intent of the type ACTION_MEDIA_BUTTON and the method onReceive() of the Broadcastreceiver does something.
My Activity is like this:
public class MusicControlActivity extends Activity {
private MediaButtonIntentReceiver receiver = new MediaButtonIntentReceiver();
#Override
public void onCreate(Bundle p_SavedInstanceState) {
super.onCreate(p_SavedInstanceState);
setContentView(R.layout.main);
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
filter.setPriority(1000);
registerReceiver(receiver,filter);
}
#Override
public void onDestroy()
{
unregisterReceiver(receiver);
}
And my broadcastreceiver as follow:
public class MediaButtonIntentReceiver extends BroadcastReceiver {
public MediaButtonIntentReceiver()
{
super();
}
#Override
public void onReceive(Context context, Intent intent)
{
String v_IntentAction = intent.getAction();
if (!Intent.ACTION_MEDIA_BUTTON.equals(v_IntentAction)) {
return;
}
KeyEvent v_Event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (v_Event == null) {
return;
}
int v_Action = v_Event.getAction();
if (v_Action == KeyEvent.ACTION_DOWN) {
// do something
Toast.makeText(context, "BUTTON PRESSED!", Toast.LENGTH_SHORT).show();
}
abortBroadcast();
}
}
The problem is that it doesn't work, no matter what I do. I've tried registering it dynamically with registerReceiver as in the code above. Also I've tried statically in the AndroidManifest.xml like this:
<receiver android:name=".MediaButtonIntentReceiver" android:enabled="true">
<intent-filter android:priority="10000000">
<action android:name="android.intent.action.ACTION_MEDIA_BUTTON" />
</intent-filter>
</receiver>
And as you can see I've set the priority to a high level and even though it doesn't work.
I've been on this for the whole day and I don't know what to do. The method onReceive from the broadcastreceiver isn't called anytime.
Does anyone know what should I do?
Use android.intent.action.MEDIA_BUTTON Instead in your manifest. Check : http://developer.android.com/training/managing-audio/volume-playback.html
First, you should stop using Toast as your diagnostic test. Use the Log class to log to LogCat, or breakpoints, or something.
Next, you should get rid of your MediaButtonIntentReceiver constructor, as it is not needed.
Then, I would dump the if (!Intent.ACTION_MEDIA_BUTTON.equals(v_IntentAction)) block, since it is also not needed.
Next, I would make sure that your media button actually works. Does it control other applications, like a music player? It may be that your media button is not Android-compliant or something.