I have a broadcastreceiver created in my Service class.
It is set to react to this action: WifiManager.SCAN_RESULTS_AVAILABLE_ACTION
So basically everytime I do a method call of wifi.startScan(); , and the results become available, the broadcastreceiver's onReceive method does its thing.
My issue is that I need to process those scan results and its likely not good practice to do so much in the broadcastreceiver. I want to do all the calculations back in my service class but I need to somehow access the ScanResults.
Any sort of help with this? As it is much needed.
Here is a simplified version of my code conveying the purpose of my broadcastreceiver:
Snippet from my Service class:
IntentFilter i = new IntentFilter();
i.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); //reacts to the scan results being available
registerReceiver(mybroadcast,i);
wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if(!wifi.isWifiEnabled()){ // if wifi is not enabled
toast = Toast.makeText(getApplicationContext(), "Wifi is off. Please turn it on.", Toast.LENGTH_LONG);
toast.show();
//wifi.setWifiEnabled(true);
//startActivity(backIntent);
}
else
{
wifi.startScan(); //what the receiver is going to react to
}
Code for my receiver:
private final BroadcastReceiver mybroadcast = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//gets the scan results
wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
List<ScanResult> scans = wifi.getScanResults();
// do some work here...
}
}
You can try adding an handler to service for ex:
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
String aResponse = msg.getData().getString("message");
if ((null != aResponse)) {
// ALERT MESSAGE
Toast.makeText(getBaseContext(),
"Server Response: " + aResponse, Toast.LENGTH_SHORT)
.show();
} else {
// ALERT MESSAGE
Toast.makeText(getBaseContext(),
"Not Got Response From Server.", Toast.LENGTH_SHORT)
.show();
}
}
};
And send a message to it in OnReceive of your BroadcastReceiver:
Message msgObj = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("message", msg);
msgObj.setData(b);
handler.sendMessage(msgObj);
Related
i'm trying to use in my project a broadcast receiver which listens to battery status of charging/not charging and throw a toast in each of the options .
every time i change the charger status in the app ,the app crash.
(if i start the app with the charger connected it's show me the right toast
but when i uncharge the phone the app crashes)
here is the code
thanks in advance
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = this.registerReceiver(null, ifilter);
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
if(isCharging==true){
Toast.makeText(this, "Charging", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this, "Charger not connected", Toast.LENGTH_SHORT).show();
UPDATE
i'm having an hard time to understand what i suppose to do.
i'm pretty new so be patient with me :)
here is the code i made
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkBatteryState(null);
public void checkBatteryState(View sender) {
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = registerReceiver(null, filter);
int chargeState = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
String strState;
switch (chargeState) {
case BatteryManager.BATTERY_STATUS_CHARGING:
case BatteryManager.BATTERY_STATUS_FULL:
strState = "charging";
Toast.makeText(this, strState, Toast.LENGTH_LONG).show();
break;
default:
strState = "not charging";
Toast.makeText(this, strState, Toast.LENGTH_LONG).show();
}
}
}
http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html
is this what you're using?
Maybe you haven't ensured your Intent is sticky.
My advice would be not to use a registerreceiver with a null argument.
Try this method for creating a broadcastreceiver:
How to send data to another app which is not started
put your Toasts in the onReceive() function.
The code is not actually registering a receiver, just getting a sticky broadcast. If the broadcast has never been sent the this will return null which will cause a NPE in the remaining code.
I have a mUsbReceiver (BroadcastReceiver) and CameraActivity. The receiver setContentView(R.layout.main) from CameraActivity via an Intent. Then CamearActivity updates its View with this value. Notice that the setContentView is in the Broadcast receiver class and not in the CameraActivity Class.
public class CameraActivity extends Activity {
private static final String TAG = "openXC::Activity";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
usbConnection();
}
public void usbConnection() {
UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_CANCEL_CURRENT);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
String txt = "default";
HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
Log.i(TAG, "Device List: " + deviceList);
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
UsbDevice device = deviceIterator.next();
Log.i(TAG, "Device List: " + deviceList);
mUsbManager.requestPermission(device, mPermissionIntent);
}
private static final String ACTION_USB_PERMISSION ="com.ford.openxc.webcam.USB_PERMISSION";
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
Log.d(TAG, "Displayed Comten View " + device);
setContentView(R.layout.main);
}
}
else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
}
This works fine sometimes but sometimes throws the following error
I/openXC::Activity( 5609): Device List: {/dev/bus/usb/001/002=UsbDevice[mName=/dev/bus/usb/001/002,mVendorId=1133,mProductId=2085,mClass=239,mSubclass=2,mProtocol=1,mInterfaces=[Landroid.os.Parcelable;#421a1f50]}
I/openXC::Activity( 5609): Device List: {/dev/bus/usb/001/002=UsbDevice[mName=/dev/bus/usb/001/002,mVendorId=1133,mProductId=2085,mClass=239,mSubclass=2,mProtocol=1,mInterfaces=[Landroid.os.Parcelable;#421a1f50]}
I/Adreno200-EGLSUB( 5609): <ConfigWindowMatch:2087>: Format RGBA_8888.
E/ ( 5609): <s3dReadConfigFile:75>: Can't open file for reading
E/ ( 5609): <s3dReadConfigFile:75>: Can't open file for reading
D/openXC::Activity( 5609): Displayed Comten View UsbDevice[mName=/dev/bus/usb/001/002,mVendorId=1133,mProductId=2085,mClass=239,mSubclass=2,mProtocol=1,mInterfaces=[Landroid.os.Parcelable;#421d3ed0]
D/WebcamPreview( 5609): WebcamPreview constructed
Technically, you can call setContentView any time you are executing on the event thread.
Otherwise you need to use a Handler to call it.
Also, here are some usefull links that might help you:
link1
link 2
link 3
I dont have much exp on USB sort of thing but since u said its saying cannot readfile.. i believe dat the error may be in the usb so for the debugging purpose i would suggest to move the setContentView(int) from if conditions to the onRecieve directly so dat whenever the onReceive is called ur contenview will change , this will help to ensure that the error is not with setcontentview... After dat u can see without setcontentview in the usb and now if the error is coming then surely the error is in the usb and not in the setContentView ....
Hope it works :)
The main activity has an AlarmManager which calls a Service every X minutes. I need a way that the methods inside the service's class can update a TextView in the main activity, but I dont know how to get the TextView's object in the service. Is there any way?
Here is part of the code:
Intent myIntent = new Intent(MainActivity.this, MyAlarmService.class);
pintent = PendingIntent.getService(MainActivity.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 60000, pintent);
In your alarm service you have a onReceive method
public void onReceive(Context context, Intent arg1) {
String data = "haha";
if (data.isEmpty() == false && data.contentEquals("") == false) {
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = "sing";
CharSequence message = data;
//get the activity
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(), 0);
Notification notif = new Notification(R.drawable.icon,
data, System.currentTimeMillis());
notif.defaults |= Notification.DEFAULT_SOUND;
notif.setLatestEventInfo(context, from, message, contentIntent);
nm.notify(1, notif);
}
Method call:
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, ReminderReceiverActivity.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
100000, pendingIntent);
}
I had the same need, in an accelerometer-reading service and an app that would start/stop the service and display the current average accelerometer magnitude.
I used Service Binding to allow the Service to send a Message to the Activity, containing the accelerometer value.
See http://developer.android.com/guide/components/bound-services.html#Messenger for background on Binding. For a good example, see the API Samples' MessengerServiceActivities and MessengerService classes.
I did the following. I've left out the mundane details (such as Synchronization to avoid races) for clarity. Notice that I use bind() as well as StartService(). The bind() is for sending messages between the Activity and Service; the StartService() is so the Service keeps running after the Activity exits.
Basically, the Activity and Service exchange Messengers that will allow each to send Messages to the other. The Activity sends custom Messages to the Service in order to Subscribe to Service Messages or Unsubscribe from Service Messsages. When the Service wants to send data to the Activity, it sends a custom Message to the Activity's Messenger. The Activity, on receiving such a message, displays the new value to the user.
The answer that suggested using Notifications uses a simple way to get data onto the screen. This more complex Message-passing answer is needed if you want to display data in your Activity (vs. the Notification bar).
I apologize for the length of the example code below, but there are a lot of necessary details to convey.
In my Activity, named AccelServiceControl:
private FromServiceHandler handler; // My custom class for Handling Messages from my Service.
private Messenger fromService; // For receiving messages from our Service
...
public void onCreate(Bundle savedInstanceState) {
...
handler = new FromServiceHandler(this);
fromService = new Messenger(handler);
...
}
protected void onResume() {
...
// While we're in the foreground, we want to be bound to our service.
// onServiceConnected() will return the IBinder we'll use to communicate back and forth.
bindService(new Intent(this, AccelService.class), this, Context.BIND_AUTO_CREATE);
}
protected void onPause() {
...
// Note: By itself, this doesn't stop the Service from sending messages to us.
// We need to send a custom Unsubscribe Message to stop getting messages from the Service.
unbindService(this);
}
public void onClick(View v) {
// Send a custom intent to start or stop our Service.
if (buttonStart == v) {
startService(new Intent(AccelService.ACTION_START));
} else if (buttonStop == v) {
startService(new Intent(AccelService.ACTION_STOP));
}
...
}
public void onServiceConnected(ComponentName name, IBinder service) {
...
// Ask our Service to send us updates.
toService = new Messenger(service);
Message msg = Message.obtain(null, FromClientHandler.MSG_SUBSCRIBE); // our custom Subscribe message
msg.replyTo = fromService;
try {
toService.send(msg);
} catch (RemoteException e) {
// Failed because the Service has died.
// We handle this in onServiceDisconnected().
}
}
In the Activity's custom Message Handler:
....
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ACCEL_UPDATE:
...
Bundle bundle = msg.getData();
double accelValue = bundle.getDouble(ACCEL_UPDATE_VALUE);
...then display the new accelValue in, for example, a TextView.
...
}
}
In the Service, named AccelService:
...
private Messenger fromClient; // For receiving messages from our Client(s).
private FromClientHandler handler; // needed just for unlinking at in onDestroy().
// Since we have only one Client, we store only one Activity's Messenger
private Messenger subscribedMessenger;
public void onCreate() {
...
handler = new FromClientHandler(this);
fromClient = new Messenger(handler);
}
public void onDestroy() {
// Unlink ourselves from our Handler, so the Garbage Collector can get rid of us. That's a topic in itself.
handler.unlink();
....
}
public int onStartCommand(Intent intent, int flags, int startId) {
...
int returnValue = START_NOT_STICKY;
String action = intent.getAction();
if (ACTION_START.equals(action)) {
doActionStart();
returnValue = START_STICKY;
} else if (ACTION_STOP.equals(action)) {
...
// Our Service is done
stopSelf();
}
...
return returnValue;
}
public IBinder onBind(Intent intent) {
// Hand back a way to send messages to us.
return fromClient.getBinder();
}
...when we want to send data to the Activity:
Message msg = Message.obtain(null, FromServiceHandler.MSG_ACCEL_UPDATE);
Bundle bundle = new Bundle();
bundle.putDouble(FromServiceHandler.ACCEL_UPDATE_VALUE, avgAccel);
msg.setData(bundle);
try {
subscribedMessenger.send(msg);
} catch (RemoteException e) {
// Failed because the Client has unbound.
subscribedMessenger = null;
}
I am loading an HTTP request in the background using loopj HTTP CLIENT and when it is done, I want to display a "success" notification (dialog, toast, etc.)
I have the code in a seperate (non-activity) class with a static method that executes the background request. In the end, the response is in a AsyncHttpResponseHandler under a onSuccess method. In this method, I can print out the response, confirm that the request went through, save data to the sd card/ Shared Preferences, but how do I access the UI thread to display a notification?
Thanks in advance.
you can do it using a Handler, or by calling Activity.runOnUiThread(). so you either pass a Handler, or an Activity object to your static method, then in your onSuccess() method, do,
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
// i'm on the UI thread!
}
}
);
or,
handler.post(new Runnable() {
#Override
public void run() {
// i'm on the UI thread!
}
}
);
I guess you mean a service as a background process. Service has many built in methods like onCreate, onStartCommand, onDestroy, etc. I suggest using a Notification, because notifications do not require a UI thread to do the job.
Create a method to generate a notification and call it after your HTML read is over.
private static void generateNotification(Context context, String message) {
int icon = R.drawable.ic_stat_gcm;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context, MainActivity.class);
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
}
You could fire a local broadcast with the message, and show a toast with a receiver.
Do this in the class doing the updates:
Intent intent = new Intent("ACTION_TOAST");
intent.putExtra("message", "Success!");
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
Then in any activity that might want to know about the update, do this:
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if ("ACTION_TOAST".equals(intent.getAction()) {
Toast.makeText(MyActivity.this, intent.getStringExtra("message"),
Toast.LENGTH_SHORT).show();
}
}
}
#Override
protected void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(this).registerReceiver(
receiver, new IntentFilter("ACTION_TOAST"));
}
#Override
protected void onStop() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
You still need to pass a context into your static method, but this works even if that context is a Service or some other context that can't show Toasts / create UI.
I am planning on sending SMS messages in my app. I have this code so far:
private void sendMessage(String number, String message ){
dlg.setCancelable(false);
dlg.setMessage("Sending...");
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(etText.getWindowToken(), 0);
etText.setText("");
dlg.show();
SmsManager sms = SmsManager.getDefault();
Intent sendingIntent = new Intent(Intent.ACTION_SEND);
sendingIntent.putExtra("number", number);
sendingIntent.putExtra("message", message);
PendingIntent sendPI = PendingIntent.getBroadcast(this, 0, sendingIntent, PendingIntent.FLAG_ONE_SHOT);
sms.sendTextMessage(number, null, message, sendPI, null);
}
My Receiver:
public class SMSSenderReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
int resultCode = this.getResultCode();
String number = intent.getExtras().getString("number");
String message = intent.getExtras().getString("message");
ContentValues val = new ContentValues();
val.put("address", number);
val.put("body", message);
switch(resultCode){
case Activity.RESULT_OK:
context.getContentResolver().insert(Uri.parse("content://sms/sent"), val);
if (MessageListActivity.dlg != null){
if (MessageListActivity.dlg.isShowing()){
MessageListActivity.dlg.dismiss();
}
}
}
}
}
In my methods for my activity:
SMSSenderReceiver receiver = new SMSSenderReceiver();
#Override
public void onCreate(Bundle b){
this.registerReceiver(receiver, new IntentFilter(Intent.ACTION_SEND));
}
#Override
public void onResume(){
super.onResume();
this.registerReceiver(receiver);
}
#Override
public void onStop(){
super.onStop();
this.unRegisterReceiver(receiver);
}
#Override
public void onPause(){
super.onPause();
this.unRegisterReceiver(receiver);
}
Now the problem is that when I send a message with my phone screen on, it does fine by dismissing the dialog and putting the message into the sent box when it is sent, but when I try to send a message and immediately turn off my screen it sends the message, but doesn't dismiss the dialog nor put the message into the sent folder. I know this has something to do with life cycles of the activity, but I'm not sure what to do with the onPause and onResume functions. If I don't unregister the receiver when the phone turns off then I get an error that the receiver has already been leaked error. Is there anyone that knows of a way of receiving the broadcast when my phone is off? Or of a way for getting the ACTION_SEND broadcast through the manifest?
Turning off screen will always call onStop(), but not with onDestroy(). onDestroy() could be called in case the system is losing memory… I think you can unregister the receiver in onDestroy()…