I am trying to register a receiver for the removal of the sdcard, but my receiver is not getting called on removal of the sd card pasting my code here. I am registering the receiver in the oncreate() and unregistering in the ondestroy function. Please let me know if i am doing any mistake.
void registerSDCardStateChangeListener() {
final String MEDIA_REMOVED = "android.intent.action.MEDIA_REMOVED";
final String MEDIA_UNMOUNTED = "android.intent.action.MEDIA_UNMOUNTED";
final String MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
// final String MEDIA_EJECT = "android.intent.action.MEDIA_EJECT";
final String MEDIA_EJECT = "android.intent.action.MEDIA_SCANNER_FINISHED";
mSDCardStateChangeListener = new BroadcastReceiver() {
#
Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase(MEDIA_REMOVED) || action.equalsIgnoreCase(MEDIA_UNMOUNTED) || action.equalsIgnoreCase(MEDIA_BAD_REMOVAL) || action.equalsIgnoreCase(MEDIA_EJECT)) {
if (mMediaPlayer != null) {
stopPlayBack();
}
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(MEDIA_REMOVED);
filter.addAction(MEDIA_UNMOUNTED);
filter.addAction(MEDIA_BAD_REMOVAL);
filter.addAction(MEDIA_EJECT);
registerReceiver(mSDCardStateChangeListener, filter);
}
Please let me know if anything is wrong in my code.
Try adding this to your intent-filter
filter.addDataScheme("file");
It appears the actions you are trying to catch send the path as the data field of the intent. If that is the case, then your intent filter must have the matching scheme.
Finally, and this is just a suggestion, but I would recommend you use the constants in the Intent class instead of typing out your actions manually. IE, use Intent.ACTION_MEDIA_REMOVED instead of you using the string directly.
Justin Breitfeller's answer worked for me, but as an alternate technique, you can also do this entirely in the AndroidManifest.xml:
<receiver android:enabled="true" android:exported="false"
android:name="SDCardStateChangeListener">
<intent-filter>
<action android:name="android.intent.action.MEDIA_UNMOUNTED" />
<action android:name="android.intent.action.MEDIA_REMOVED" />
<action android:name="android.intent.action.MEDIA_EJECT" />
<action android:name="android.intent.action.MEDIA_BAD_REMOVAL" />
<data android:scheme="file" />
</intent-filter>
</receiver>
Then make the receiver a proper class:
public class OnMediaMountedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equalsIgnoreCase(Intent.ACTION_MEDIA_REMOVED)
|| action.equalsIgnoreCase(Intent.ACTION_MEDIA_UNMOUNTED)
|| action.equalsIgnoreCase(Intent.ACTION_MEDIA_BAD_REMOVAL)
|| action.equalsIgnoreCase(Intent.ACTION_MEDIA_EJECT)) {
if(mMediaPlayer != null) {
stopPlayBack();
}
}
}
};
I have found solutions while app is running and user unmount/removed sdcard.
#Override
protected void onResume() {
super.onStart();
IntentFilter ejectFilter = new ntentFilter(Intent.ACTION_MEDIA_MOUNTED);
ejectFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
ejectFilter.addAction(Intent.ACTION_MEDIA_EJECT);
ejectFilter.addDataScheme("file");
registerReceiver(ejectReceiver, ejectFilter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(ejectReceiver);
}
In class, define method like below,
BroadcastReceiver ejectReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_MEDIA_EJECT) || action.equals(Intent.ACTION_MEDIA_UNMOUNTED))
{
Log.e("msg","Media Unmounted");
//do something on unmounted sdcard from device
}
}
};
Hope it will be helpful.
Related
I have an android application. Here whenever the user changes the device timezone, I want a event listener to notify me? How can I accomplish it?
Register a receiver with the following intent filters
filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(Intent.ACTION_TIME_CHANGED);
and register it in the OnCreate of your activity
public void onCreate() {
super.onCreate();
registerReceiver(receiver, filter);
}
Create a Broadcast receiver as follows.
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_TIME_CHANGED) ||
action.equals(Intent.ACTION_TIMEZONE_CHANGED))
{
doWorkSon();
}
}
};
and unregister it in the onDestroy of your activity:
public void onDestroy() {
super.onDestroy();
unregisterReceiver(m_timeChangedReceiver);
}
You need to create a BroadcastReceiver for intent action ACTION_TIMEZONE_CHANGED. BroadcastReceiver is described here.
In manifest file
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.TIMEZONE_CHANGED"/>
</intent-filter>
</receiver>
In myReceiver class
override fun onReceive(context: Context, intent: Intent) {
var action : String? = intent.action
var timeZone: String? = intent.getStringExtra("time-zone")
Toast.makeText(context,action+timeZone,Toast.LENGTH_LONG).show()
My issue here is more the result of the framework I'm using than Android itself. My app needs to register a ContentObserver after the user has installed a specific plugin associated with the AWARE framework. The framework has a sensor for installation of plugins, and sends a broadcast once this happens. Documentation can be found here: http://www.awareframework.com/installations/
I would like to accomplish this using a BroadcastReceiver.
I have a few questions regarding how to properly do this:
The way I interpret this documentation and Android is that if I register a BroadcastReceiver in my Manifest file with the intent filter "Installations.EXTRA_PACKAGE_NAME", every time a package is installed, it will activate my InstallationReceiver. If my understanding is still correct, I will be able to use getAction() on the received intent to parse the package name. Does this look like a correct understanding? Do intents works this way?
Is it proper to have my BrodcastReceiver in my Service class? Or should I make it a standalone class?
Did I register my receiver properly?
My MainService code:
package hcii.tracker;
public class MainService extends Service {
public static final Uri ACTIVITY_URI = Uri.parse("content://com.aware.plugin.google.activity_recognition.provider/plugin_google_activity_recognition");
public HashMap<Uri,ContentObserver> mContentObservers;
public void onCreate(){
Log.d("SERVICE", "Service created!");
Context context = this;
mContentObservers = new HashMap<Uri,ContentObserver>();
//Activate installations sensor
Aware.setSetting(context, Aware_Preferences.STATUS_INSTALLATIONS, true);
//Activate Accelerometer
Aware.setSetting(this, Aware_Preferences.STATUS_ACCELEROMETER, true);
//Set sampling frequency
Aware.setSetting(this, Aware_Preferences.FREQUENCY_ACCELEROMETER, 60);
Aware.setSetting(getApplicationContext(), "frequency_google_fused_location", 60,
"com.aware.plugin.google.fused_location");
Aware.startPlugin(getApplicationContext(), "com.aware.plugin.google.fused_location");
Aware.startPlugin(getApplicationContext(), "com.aware.plugin.google.activity_recognition");
sendBroadcast(new Intent(Aware.ACTION_AWARE_REFRESH));
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onDestroy() {
try {
ContentObserver observer = mContentObservers.get(ACTIVITY_URI);
getContentResolver().unregisterContentObserver(observer);
mContentObservers.remove(ACTIVITY_URI);
} catch (IllegalStateException ise) {
Log.d("SERVICE", "No ContentObservers registered");
}
}
public class ActivityRecognitionObserver extends ContentObserver {
public Uri CONTENT_URI = Uri.parse("content://com.aware.plugin.google.activity_recognition.provider/plugin_google_activity_recognition");
public ActivityRecognitionObserver(Handler handler) {
super(handler);
}
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// Get the latest recorded value
Log.d("OBSERVER", "Change in activity data detected");
Cursor activity = getContentResolver().query(CONTENT_URI, null, null, null,
"activity_name" + "DESC LIMIT 1");
if( activity != null && activity.moveToFirst() ) {
// Here we read the value
String activity_name = activity.getString(activity.getColumnIndex("activity_name"));
if (activity_name.equals("in_vehicle")){
Aware.setSetting(getApplicationContext(), "frequency_google_fused_location", 60,
"com.aware.plugin.google.activity_recognition");
Log.d("OBSERVER", "Recognized in vehicle");
Aware.startPlugin(getApplicationContext(), "com.aware.plugin.google.activity_recognition");
}
else {
Aware.setSetting(getApplicationContext(), "frequency_google_fused_location", 180,
"com.aware.plugin.google.activity_recognition");
Log.d("OBSERVER", "Recognized on foot");
Aware.startPlugin(getApplicationContext(), "com.aware.plugin.google.activity_recognition");
}
}
if( activity != null && ! activity.isClosed() ) activity.close();
}
}
public class InstallationReceiver extends BroadcastReceiver {
public InstallationReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null && action.equals("com.aware.plugin.google.activity_recognition")){
ActivityRecognitionObserver so = new ActivityRecognitionObserver(new Handler());
getContentResolver().registerContentObserver(ACTIVITY_URI, true, so);
mContentObservers.put(ACTIVITY_URI, so);
Log.d("SERVICE", "Observer registered");
}
}
}
}
Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="hcii.tracker" >
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
tools:replace="android:icon, android:theme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MainService"
android:exported="false" />
<receiver android:name="hcii.tracker.MainService$InstallationReceiver" >
<intent-filter>
<action android:name="Installations.EXTRA_PACKAGE_NAME" >
</action>
</intent-filter>
</receiver>
...
There are several problems here:
1) You can use an inner class for your BroadcastReceiver, but if so it must be declared static, because Android needs to be able to instantiate the class itself using new. This is not possible in your current architecture (because the class is an inner class). In general it is better (easier) to use a stand-alone class for this.
2) Your Intent filter is wrong. The linked documentation from Aware indicates that the broadcast Intent is Installations.ACTION_AWARE_APPLICATION_ADDED, so your intent filter needs to look like this:
<intent-filter>
<action android:name="Installations.ACTION_AWARE_APPLICATION_ADDED"/>
</intent-filter>
3) Once you have declared the BroadcastReceiver correctly, it will be triggered whenever Aware adds a plugin. The package name of the installed plugin is put into an "extra" in the Intent. To determine which plugin has been installed, you need to do something like this:
public void onReceive(Context context, Intent intent) {
String packageName = intent.getStringExtra("Installations.EXTRA_PACKAGE_NAME");
if (packageName != null && packageName.equals("your.plugin.package.name") {
// Do your stuff here...
}
}
I have a Problem with my Broadcastreceiver and I have no idea what I am doing wrong.
I already read many posts #stackoverflow, but nothing helped.
I am sending a broadcast from my helperclass, the broadcastreceiver is implemented in an activity. I am putting an extra on the Intent at the helperclass before sending it, but the intent # the activity has null extras. What am I doing wrong?
This is my sourcecode:
//Helperclass
...
public static String BROADCAST_ACTION_DM = "de.je.toctohk.DISPLAYMESSAGE";
...
public void method() {
String msg = _intent.getStringExtra("message");
Intent broadcast = new Intent();
broadcast.setAction(BROADCAST_ACTION_DM);
broadcast.putExtra("msg", _chatentryid);
sendStickyBroadcast(broadcast);
}
//Activity
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String test = getIntent().getStringExtra("msg");
Toast.makeText(getApplicationContext(), intent.getExtras().getString("msg"), Toast.LENGTH_SHORT).show();
}
};
protected void onResume() {
IntentFilter filter = new IntentFilter();
filter.addAction(GcmIntentService.BROADCAST_ACTION_DM);
_testintent = registerReceiver(receiver, filter);
super.onResume();
}
//Manifest
<activity
android:name="de.je.toctohk.activities.ChatActivity"
android:label="#string/title_activity_push" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="de.je.toctohk.DISPLAYMESSAGE" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
What I already tried:
normal broadcast
only registering the filter in the Activity
only registering the filter in the Manifest
Sticky broadcast
context.getIntent().getExtra…
intent.getExtra…
It would be great if somebody could give me some advises.
Thanks a lot!!
I'm doing a handle on android phone numbers, you can know if a call is made, ie confirm that the call was answered. Use the following code to make the call:
Intent callIntent = new Intent (Intent.ACTION_CALL, Uri.parse (number));
startActivity (callIntent);
When you end the call back to my application and that's when I want to know if the call was answered and if it could be the duration of the call.
Yes you can, for this you need create BroadCastReceiver with intent
for example
<receiver android:name=".broadcast.DontMissReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
and then on Receiver
#Override
public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase(PHONE_ACTION)) {
this.receivePhoneCall(context, intent);
}
}
private void receivePhoneCall(Context context, Intent intent) {
String curState = intent.getExtras().getString("state");
if (curState.equalsIgnoreCase("RINGING")) {
} else
if (curState.equalsIgnoreCase("IDLE") && state.length() > 0) {
if (!state.equalsIgnoreCase("OFFHOOK")) {
}
}
}
I am new to android, I have created intent's like this -
<receiver android:name=".IncommigCallListener" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<receiver android:name=".OutgoingCallReciever" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Now i created a service like this -
<service
android:name=".CallLogger"
android:exported="false"/>
Class CallLogger
public class CallLogger extends IntentService {
public CallLogger(String name) {
super(name);
// TODO Auto-generated constructor stub
}
#Override
protected void onHandleIntent(Intent arg0) {
// TODO Auto-generated method stub
System.out.println("service started");
}
}
I don't want to have any activity in my application, i just want to start the service so that it can work in background and receive PHONE_STATE and NEW_OUTGOING_CALL intent.
When i start this application, it doesn't log anything on PHONE_STATE or NEW_OUTGOING_CALL intent.
How can start service in background without using any activity ?
Edit :
public class OutgoingCallReciever extends BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
}
and
public class IncommigCallListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
String incommingCallNumber = incomingNumber;
System.out.println("incomming call : " + incomingNumber);
break;
}
}
}
Just start service in your BroadcastReceiver's onReceive method. As you are registering BroadcastReceiver in AndroidManifist, It will always listen for Broadcasts even if application is not running (OS will run it for you).
Example
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, MyService.class);
context.startService(service);
}
}
EDIT
To start a service on Boot completed you can do something like this.
1) Add permission to your Manifist :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
2) Register your Broadcast Receiver with BOOT COMPLETE action.
<receiver android:name="com.example.BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
3) In BootBroadcastReceiver.java:
public class BootBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, MyService.class);
context.startService(serviceIntent );
}
}
You should be able to do something like this in your receiver.
public class OutgoingCallReciever extends BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Intent service = new Intent(context, CallLogger.class);
context.startService(service);
}
}
You need to create an intent and call startService() on it to "launch" the service.
Also for what it's worth you should get out of the habbit of System.out.println use Log.d(tag,msg) to print debugging information to the logcat. You can switch the d to other letters if you want to print in different channels.
Why nothing gets printed is only due to the problem that System.out.println does not work in Android! Where do you think the background process will "print" this thing?
You need to change that to Log.d(tag, msg) and then check your logcat to see the output! Otherwise I guess your code might be running properly.