I was reading some post but none have a good answer for me.
So, which is the best way to pass data from broadcast to activity without restart the activity?
Actually I'm using this.
SMSListener:
public class SmsListener extends BroadcastReceiver {
private OnSmsReceivedListener listener = null;
#Override
public void onReceive(Context context, Intent intent) {
try {
if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
String messageBody = smsMessage.getMessageBody();
String phoneNumber = smsMessage.getDisplayOriginatingAddress();
if (listener != null) {
listener.onSmsReceived(phoneNumber, messageBody);
}
}
}
}
} catch (Exception e)
{
Log.e("Error", "Some some");
}
}
public void setOnSmsReceivedListener(Context context) {
this.listener = (OnSmsReceivedListener) context;
}
}
OnSmsReceivedListener:
public interface OnSmsReceivedListener {
void onSmsReceived(String sender, String message);
}
Activity:
public class MainActivity extends AppCompatActivity implements OnSmsReceivedListener {
private SmsListener receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
/***********/
receiver = new SmsListener();
receiver.setOnSmsReceivedListener(this);
}
#Override
public void onSmsReceived(String sender, String message) {
Log.e("Test", "Sender: "+sender+" - Message: "+message);
}
}
Another of my questions is why I never get log "Test" in my activity. Is like listener is always null, why?
You should add at the end of onCreate()
final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
IntentFilter intentFilter = new IntentFilter(SMS_RECEIVED_ACTION);
registerReceiver(receiver, intentFilter);
and in the onPause()
unregisterReceiver(receiver);
add also the following permission on AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
Related
Have a Firebase Cloud messagin Service running , and i want each time i receive a new message a methode in a specif fragment is called.
public class FirebaseMsgService extends FirebaseMessagingService {
public FirebaseMsgService() {
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
ServiceConnector serviceconnector =null;
JSONObject data;
String json = remoteMessage.getData().toString();
try{
data= new JSONObject(json);
**Fragment.method(data);**
}
catch(Exception e){
}
}
}
You can use LocalBroadcastManager
Service:
private void notifyFragment(String json){
Intent intent = new Intent("nameOfTheAction");
Bundle bundle = new Bundle();
bundle.putString("json", json));
intent.putExtras(bundle);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
Fragment:
LocalBroadcastManager bm;
#Override
public void onAttach(Context context) {
super.onAttach(context);
bm = LocalBroadcastManager.getInstance(this);
IntentFilter actionReceiver = new IntentFilter();
actionReceiver.addAction("nameOfTheAction");
bm.registerReceiver(onJsonReceived , actionReceiver);
}
private BroadcastReceiver onJsonReceived = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
String json = intent.getString("json")
data = new JSONObject(json);
}
}
};
#Override
protected void onDetach() {
super.onDetach();
bm.unregisterReceiver(onJsonReceived);
}
I've got a BroadcastReceiver which checks if Internet connection is available then it starts a service which retrieves an ArrayList from the DB:
public class NetworkWatcher extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
Intent retrieveVehicleList = new Intent(context, RetrieveVehicleListService.class);
if (info != null)
{
if (info.isConnected())
{
context.startService(retrieveVehicleList);
}
else
{
context.stopService(retrieveVehicleList);
}
}
}
}
public class RetrieveVehicleListService extends IntentService
{
private static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
private NotificationCompat.Builder builder;
private ArrayList<Vehicle> vehicles;
private void parseVehiclesFromMap(ArrayList vehicles)
{
for (int i = 0; i < vehicles.size(); i++)
{
final Vehicle v = new Vehicle();
HashMap vehicleMap = (HashMap) vehicles.get(i);
v.setPlate(vehicleMap.get("plate").toString());
v.setKm(vehicleMap.get("km") == null ? null : Integer.parseInt(vehicleMap.get("km").toString()));
v.setFuelQuantity(Double.parseDouble(vehicleMap.get("fuel_quantity").toString()));
v.setEffectiveFuelEconomy(Double.parseDouble(vehicleMap.get("fuel_economy").toString()));
v.setInsuranceDate(vehicleMap.get("insurance_date") == null ? null : new LocalDate(vehicleMap.get("insurance_date").toString()));
v.setMatriculationDate(new LocalDate(vehicleMap.get("matriculation_date").toString()));
v.setLatitude(vehicleMap.get("latitude") == null ? null : Double.parseDouble(vehicleMap.get("latitude").toString()));
v.setLongitude(vehicleMap.get("longitude") == null ? null : Double.parseDouble(vehicleMap.get("longitude").toString()));
v.setFuelType(FuelType.fromInt(Integer.parseInt(vehicleMap.get("id_fuel").toString())));
this.vehicles.add(v);
}
}
private void sendRequest(int userID)
{
Response.Listener<String> listener = new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
try
{
HashMap json = new ObjectMapper().readValue(response, HashMap.class);
String errorCode = json.get("error_code").toString();
switch (errorCode)
{
case "0":
parseVehiclesFromMap((ArrayList) json.get("vehicles"));
break;
default:
// TODO gestire
break;
}
}
catch (IOException e)
{
// TODO gestire
e.printStackTrace();
}
}
};
VehicleListRequest request = new VehicleListRequest(String.valueOf(userID), listener, null);
RequestQueue queue = Volley.newRequestQueue(this);
queue.add(request);
}
#Override
protected void onHandleIntent(Intent intent)
{
SharedPreferences sp = getSharedPreferences(getString(clyky.cartracker.R.string.sharedPreferencesName), Context.MODE_PRIVATE);
int userID = sp.getInt("id_user", SplashActivity.DEFAULT_USER_ID);
if (userID != SplashActivity.DEFAULT_USER_ID)
{
sendRequest(userID);
}
}
public RetrieveVehicleListService()
{
super("RetrieveVehicleList");
vehicles = new ArrayList<>();
}
}
I want my MainActivity gets that ArrayList from RetrieveVehicleListService when the activity is started. How could I do that?
Thanks in advance.
Use LocalBroadcast reciever to send data from service to activity. Add following code to your activty
private BroadcastReceiver BReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
//put here whaterver you want your activity to do with the intent received
ArrayList<String> arrayList=intent.getStringArrayListExtra("arrayList");
}
};
protected void onResume(){
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(bReceiver, new IntentFilter("message"));
}
protected void onPause (){
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(bReceiver);
}
and use following method to send broadcast from service
private void sendBroadcast (boolean success){
Intent intent = new Intent ("message"); //put the same message as in the filter you used in the activity when registering the receiver
intent.putExtra("success", success);
intent.putStringArrayListExtra("arrayList", arrayList);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
Use Local Broadcast Receiver :
send broadcast using below code
Intent intent = new Intent("YourAction");
Bundle bundle = new Bundle();
bundle .putSerializable("ARRAYLIST",(Serializable)vehicles);
intent.putExtra("BUNDLE",bundle);
intent.putExtras(intent)
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
And receive broadcast in your activity:
private MyBroadcastReceiver myReceiver;
#Override
public void onResume(){
myReceiver = new MyReceiver();
final IntentFilter intentFilter = new IntentFilter("YourAction");
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, intentFilter);
}
#Override
public void onPause(){
if(myReceiver != null)
LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
myReceiver = null;
}
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Here you have the received broadcast
// And if you added extras to the intent get them here too
// this needs some null checks
Intent intent = getIntent();
Bundle args = intent.getBundleExtra("BUNDLE");
ArrayList<Object> object = (ArrayList<Object>)args.getSerializable("ARRAYLIST");
}
}
As we know that, when we use any menu in sim toolkit it send command to mobile network in ussd or sms format.
I need that sms or ussd to record and show it to me in android application.
I am calling the library service which i got in main activity like this
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent srvIntent = new Intent(this, CDUSSDService.class);
startService(srvIntent);
}
}
USSD Service Class is like that:
public class CDUSSDService extends Service{
private String TAG = CDUSSDService.class.getSimpleName();
private boolean mActive = true;//false //we will only activate this "USSD listener" when we want it
BroadcastReceiver receiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equals(Intent.ACTION_INSERT))
{
//activity wishes to listen to USSD returns, so activate this
mActive = true;
Log.d(TAG, "activate ussd listener");
showtoast(""+"activate ussd listener");
}
else if(intent.getAction().equals(Intent.ACTION_DELETE))
{
mActive = false;
Log.d(TAG, "deactivate ussd listener");
showtoast(""+"DeActivate ussd listener");
}
}
};
private final IExtendedNetworkService.Stub mBinder = new IExtendedNetworkService.Stub ()
{
public void clearMmiString() throws RemoteException
{
Log.d(TAG, "called clear");
showtoast("called clear.");
}
public void setMmiString(String number) throws RemoteException
{
Log.d (TAG, "setMmiString:" + number);
showtoast("setMmiString:"+number);
}
public CharSequence getMmiRunningText() throws RemoteException
{
if(mActive == true)
{
return null;
}
return "USSD Running";
}
public CharSequence getUserMessage(CharSequence text)
throws RemoteException {
Log.d(TAG, "get user message " + text);
showtoast("GET Usr Message:"+text);
if(mActive == false){
//listener is still inactive, so return whatever we got
Log.d(TAG, "inactive " + text);
showtoast("inactive:"+text);
return text;
}
//listener is active, so broadcast data and suppress it from default behavior
//build data to send with intent for activity, format URI as per RFC 2396
Uri ussdDataUri = new Uri.Builder()
.scheme(getBaseContext().getString(R.string.uri_scheme))
.authority(getBaseContext().getString(R.string.uri_authority))
.path(getBaseContext().getString(R.string.uri_path))
.appendQueryParameter(getBaseContext().getString(R.string.uri_param_name), text.toString())
.build();
sendBroadcast(new Intent(Intent.ACTION_GET_CONTENT, ussdDataUri));
mActive = false;
return null;
}
};
#Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "called onbind");
//the insert/delete intents will be fired by activity to activate/deactivate listener since service cannot be stopped
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_INSERT);
filter.addAction(Intent.ACTION_DELETE);
filter.addDataScheme(getBaseContext().getString(R.string.uri_scheme));
filter.addDataAuthority(getBaseContext().getString(R.string.uri_authority), null);
filter.addDataPath(getBaseContext().getString(R.string.uri_path), PatternMatcher.PATTERN_LITERAL);
registerReceiver(receiver, filter);
return mBinder;
}
public void showtoast(String str)
{
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG).show();
}
}
I have created MainActivity inside the UssdLibray structure is like that in the below picture:
you can do this with the help of this library https://github.com/alaasalman/ussdinterceptor
I'm writing an app that checks external storage state. For monitoring the state I use BroadcastReceiver and I've noticed, that onReceive is called multiple times (eg.: 3x for unmount and 1x for mount) for one event (eg.: unplug usb).
Here is my code:
public class MainActivity extends ActionBarActivity {
final static String TAG = "BroadcastReceiverDemo";
private IntentFilter filter;
private BroadcastReceiver receiver;
private void registerReceiver() {
filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
filter.addAction(Intent.ACTION_MEDIA_SHARED);
filter.addDataScheme("file");
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String broadcast;
String state = Environment.getExternalStorageState();
Log.d(TAG, "State: " + state);
if (Environment.MEDIA_MOUNTED.equals(state) && !Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
broadcast = "External storage aviable";
} else {
broadcast = "External storage NOT aviable";
}
String msg = intent.getAction() + " received broadcast: " + broadcast;
Log.d(TAG, msg);
}
};
this.registerReceiver(receiver, filter);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver();
}
#Override
protected void finalize() throws Throwable {
if (receiver != null) {
this.unregisterReceiver(receiver);
}
super.finalize();
}
}
Q: Why is onReceive called so many times and how to make it call only once?
Thanks for any help.
I am trying to display an alert in a specific Activity when the charging status changes.
this is my receiver class:
public class BatteryChargeReceiver extends BroadcastReceiver {
private String TAG = "receiver";
private ChargeReceiverCallback callback;
public BatteryChargeReceiver(ChargeReceiverCallback callback) {
this.callback =callback;
Log.v(TAG,"Inside Constructor (Callback)");
}
public interface ChargeReceiverCallback {
public void onReceive(Intent intent);
}
#Override
public void onReceive(Context context, Intent intent) {
callback.onReceive(intent);
}
}
And below is how I instantiate it from my MainActivity's onResume. MainActivity implements my interface and overrides onReceive(intent). I found out that at no stage does intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1) return anything else then -1.
BatteryChargeReceiver batteryReceiver = new BatteryChargeReceiver(this);
IntentFilter filterPower = new IntentFilter("android.intent.action.ACTION_POWER_CONNECTED");
registerReceiver(batteryReceiver, filterPower);
Intent.ACTION_POWER_CONNECTED not delivering current plugged-in state - this is probably a change in how API works, but I could not locate any mention of such change in docs.
The broadcast Intent.ACTION_POWER_CONNECTED was never meant to receive current plugged-in type, but it merely lets the receiving end of power connection (ref.). In fact, BatteryService.java broadcasts plain intent without any extra values (lines 410~412 as of this writing):
Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
However, following code with
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="19" />
worked on Nexus 5:
public class MainActivity extends Activity {
private static final String TAG = "PowerReceiver";
private final BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_POWER_CONNECTED.equals(action)) {
Log.d(TAG, "Power connected");
checkPluggedState(context, intent);
} else if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
Toast.makeText(context, "Power disconnected", Toast.LENGTH_SHORT).show();
} else {
Log.wtf(TAG, "Unknown action: " + action);
}
}
};
private void checkPluggedState(Context context, Intent intent) {
Intent chargingIntent = registerReceiver(null, new IntentFilter(
Intent.ACTION_BATTERY_CHANGED));
final int pluggedState = chargingIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
final String msg;
switch (pluggedState) {
case 0:
msg = "The device is running on battery";
break;
case BatteryManager.BATTERY_PLUGGED_AC:
msg = "Plugged into AC charger";
break;
case BatteryManager.BATTERY_PLUGGED_USB:
msg = "Plugged into USB charger";
break;
case BatteryManager.BATTERY_PLUGGED_WIRELESS:
msg = "Plugged into wireless charger";
break;
default:
msg = "Unknown state: " + pluggedState;
}
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_POWER_CONNECTED);
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
registerReceiver(mPowerReceiver, filter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mPowerReceiver);
}
}
Hope this helps.
According to The docs, EXTRA_STATUS is for ACTION_BATTERY_CHANGED