I'm trying to create an android app that communicate with Bluetooth low energy module. I am able to connect to module, read data and so on. But the problem is i do not know how to update textview from class that extends Service (the one in which whole connection to BLE is going on). I know there is like BILLION or even more posts like these, but believe me i tried.
Here is MainActivity: http://pastebin.com/6yaP0dYM
and here is a class that extends Service: http://pastebin.com/cYuAUina
If someone could provide me some tips to solve my issue that would be more than great!
Create Broadcast Receiver and broadcast that in Service.
If your Activity is ope, register receiver and in onReceive() update the UI.
The receiver should be in the Activity...
Below is the working code
https://stackoverflow.com/a/14695943/1403112
You can get values through broadcast receiver......as follows, First create your own IntentFilter as,
Intent intentFilter=new IntentFilter();
intentFilter.addAction("YOUR_INTENT_FILTER");
Then create inner class BroadcastReceiver as,
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
/** Receives the broadcast that has been fired */
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction()=="YOUR_INTENT_FILTER"){
//HERE YOU WILL GET VALUES FROM BROADCAST THROUGH INTENT EDIT YOUR TEXTVIEW///////////
String receivedValue=intent.getStringExtra("KEY");
}
}
};
Now Register your Broadcast receiver in onResume() as,
registerReceiver(broadcastReceiver, intentFilter);
And finally Unregister BroadcastReceiver in onDestroy() as,
unregisterReceiver(broadcastReceiver);
Now the most important part...You need to fire the broadcast from wherever you need to send values..... so do as,
Intent i=new Intent();
i.setAction("YOUR_INTENT_FILTER");
i.putExtra("KEY", "YOUR_VALUE");
sendBroadcast(i);
....cheers :)
Related
My app runs a background service indicated by the persistent notification. Users need to use the toggle button in MainActivity to turn on/off this service and thus to remove the persistent notification.
Now I want to implement a notification action that can turn this service off & as well as the toggle within MainActivity. All in all, it should be an exit button to close my app and background service directly from the notification.
How do I achieve this?
note that I have two different java files, one for NotificationService
and the other is MainActivity. The toggle belongs to MainActivity.
edit: Is this okay to call System.exit(0) if I use pending intent with
BroadCastReceiver to exit from the app completely?
You have to use PendingIntent with BroadcastReceiver or Service to perform this. Here is an example of PendingIntent with BroadcastReciever.
Build a Notification
public static void createNotif(Context context){
Intent intentAction = new Intent(context,StopServerBroadcast.class);
//This is optional if you have more than one buttons and want to differentiate between two
intentAction.putExtra("action","actionName");
pIntent = PendingIntent.getBroadcast(context,1,intentAction,PendingIntent.FLAG_UPDATE_CURRENT);
drivingNotifBldr = (NotificationCompat.Builder) new NotificationCompat.Builder(context, CHANNEL_NAME)
.setSmallIcon(R.drawable.steeringwheel)
.setContentTitle("Stop Service")
.setContentText("Example Text")
.addAction(R.drawable.smallmanwalking, "On/off", pIntent)
.setOngoing(true);
...
}
Now the receiver which will receive this Intent
public class StopServerBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Toast.makeText(context,"recieved",Toast.LENGTH_SHORT).show();
String action=intent.getStringExtra("action");
if(action.equals("action1")){
performAction1();
/*
Code that will stop your service
*/
}
}
}
Register Receiver in Manifest
<receiver
android:name=".StopServerBroadcast"
android:enabled="true" />
In AndroidManifest.xml I have a BroadcastReceiver:
<receiver android:name=".SmsMonitor">
<intent-filter android:priority="-100">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
In my MainActivity, I have RecyclerView with a list of received SMS.
My question is - How I can update the RecyclerView from my BroadcastReceiver "SmsMonitor" in case new SMS received when the application is running?
UPD: I mean I need solution for both states - for running application AND for state when application is not running, in one receiver. Because I have to take SMS all time while phone is working. And in case the application is running I want to update RecyclerView.
I tried to do it through the Service, but I did not succeed.
But I found simple solution:
I still have BroadcastReceiver SmsMonitor, registered in AndroidManifest.xml
And in the point where I create instance of my RecyclerAdapter:
mainAdapter = new MainAdapter(this);
After this I register another BroadcastReceviver:
BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
setInitialData();
mainAdapter.notifyDataSetChanged();
}
};
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
this.registerReceiver(br, filter);
And in setInitialData() I recreate all list of data for RecyclerView.
And now I have two independently working BroadcastReceiver. The first working the BroadcastReceiver from the AndroidManifest.xml, and then working the BroadcastReceiver registered in MainActivity.
You need to have the BrodcastReceiver in your MainActivity or Fragment as well which hosts the RecyclerView. So that when the new SMS is received, you can call the notifyDataSetChanged on the adapter of your RecyclerView to update it.
Declare a BroadcastReceiver in your Activity like the following. This can be an inner class of your MainActivity class.
class SMSBroadcastReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String TAG = "SMSBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == SMS_RECEIVED) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
// Update your RecyclerView here
// by calling notifyDataSetChanged on the adapter
}
}
}
}
Now create an instance of this BroadcastReceiver in the onCreate function of your MainActivity and register the receiver.
You need to ask for SMS permission first in your Activity like the following.
if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.RECEIVE_SMS}, 0);
} else {
// register sms receiver
IntentFilter filter = new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
registerReceiver(smsReceiver, filter);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
} else {
// register sms receiver
IntentFilter filter = new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION);
registerReceiver(smsReceiver, filter);
}
}
Do not forget to un-register the receiver in the onDestroy function of your MainActivity.
Hope that helps!
Update
Based on the comment below this answer, you have two cases.
Case 1. The app is running.
Case 2. The app is not running.
For case 1: The local BroadcastReceiver like I shown above, is good enough to update the RecyclerView instantly when a new SMS arrives. As you are handling the BroadcastReceiver from the MainActivity this should not be a problem, as you have the reference to your RecyclerView.
Now for Case 2: If you are able to detect any new SMS arrival, you can save the new SMS received in your local database. You need to have an SQLite database for your application which will store all the SMS and the RecyclerView in your application should populate the data from the database table where the SMS are stored. I hope you get the idea - just store the SMS in your local database associated with your application and when you run the application and launch the MainActivity, read the SMS from your local database and show them in your RecyclerView.
This question is indeed a duplicate to Listen for new calendar events
I have been trying to register the BroadcastReceiver with the way specified in the link, however, my app couldn't receive any broadcast when I modified the phone's calendar.
I also tried to add it through IntentFilter instead of through the AndroidManifest
filter = new IntentFilter();
filter.addAction(Intent.ACTION_PROVIDER_CHANGED);
registerReceiver(calendarReceiver,filter);
still no luck getting it to receive the broadcast. Did I miss anything or listening to calendar's changes cannot be done anymore?
You must add the scheme and and authority for calendar events:
filter.addDataScheme("content");
filter.addDataAuthority("com.android.calendar", null);
A complete example of listening for calendar changes would be:
CalendarReceiver.java
public class CalendarReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("example", "Calendar changed (or the phone just booted)");
}
}
Activity.java
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PROVIDER_CHANGED);
filter.addDataScheme("content");
filter.addDataAuthority("com.android.calendar", null);
registerReceiver(new CalendarReceiver(), filter);
I need to check when the value of a variable is changed in my activity by a service so that I can then update the UI with the new values. I am currently using an infinite loop to check for this within a new thread, will this be using a lot of resources/is there a more efficient way to do this?
You should use a broadcast from the Service to send the changes in the variable. First of all create a broadcast in your main Activity.
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Broadcast","broadcast received");
String value = intent.getStringExtra("Variable"); // this will get the value
// send from Service
}
};
Next set a intent filter to which the broadcast listens. This you can do in onCreate() of your activity.
IntentFilter intentFilter = new IntentFilter("FROM_SERVICE");
registerReceiver(broadcastReceiver,intentFilter);
then in your service you must send a broadcast. If you want to send some data from Service to Activity then you must replace the above code with below
Intent intent = new Intent("FROM_SERVICE");
intent.putExtra("Variable", "change");
sendBroadcast(intent);
Is there any way after this action has been broadcast via a receiver to determine that the action has finished? i.e the user has exit camera mode and is doing something else?
You can register a broadcast receiver to receive this intent.
Note however that this intent will be broadcasted every time the user pushes the camera button, and is thus not directly related to any specific "action" (e.g. taking a photo).
BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do whatever you want to do
}
};
registerReceiver(myReceiver, new IntentFilter(Intent.ACTION_CAMERA_BUTTON));
unregisterReceiver(myReceiver);
Is there any way after this action has been broadcast via a receiver to determine that the action has finished?
No. For starters, there may be no "action" to "finish", and there is no definition of "action".