My BroadCastReceiver Called twice after reopen app - android

i have created broadcast receiver for passing data between service to activity, when first time open app broadcast receiver called oknly once but when app open second time then broadcast receiver called twice
-> code for pass data service to
final Intent broadcastIntent = new Intent();
broadcastIntent.setAction(MainActivity.MyWebRequestReceiver.PROCESS_RESPONSE);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(BUNDLE, args);
sendBroadcast(broadcastIntent);
and here is code for handle response in activity and register receiver
IntentFilter filter = new IntentFilter(MyWebRequestReceiver.PROCESS_RESPONSE);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new MyWebRequestReceiver();
registerReceiver(receiver, filter);
registerReceiver(broadcastReceiver, new IntentFilter("broadCastName"));
handle its response
public class MyWebRequestReceiver extends BroadcastReceiver {
public static final String PROCESS_RESPONSE = "com.as400samplecode.intent.action.PROCESS_RESPONSE";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive");
Bundle bundle = intent.getParcelableExtra(AutoOpenAppService.BUNDLE1);
String mainUrl = bundle.getString(MAINURL);
Boolean wvVisible = bundle.getBoolean(WVBOOLEAN);
Bundle args = intent.getParcelableExtra(AutoOpenAppService.BUNDLE);
ArrayList<? extends UrlTimeModel> list = args.getParcelableArrayList(LIST);
Long TimeOut = args.getLong(TIMEOUT);
if (mainUrl != null) {
if (!isFinishing()) {
setWebView(mainUrl);
}
}
Log.d(TAG, "VISIBLE : " + wvVisible);
if (wvVisible) {
webView.setVisibility(View.VISIBLE);
} else {
if (alert != null) {
alert.dismiss();
}
moveTaskToBack(true);
}
assert list != null;
if (list.size() < 0) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
alert.dismiss();
MainActivity.this.finish();
MainActivity.super.onBackPressed();
MainActivity.this.moveTaskToBack(true);
}
}, TimeOut);
}
LoadSubURl((ArrayList<UrlTimeModel>) list, TimeOut);
}
}
unregister in onstop()
#Override
protected void onStop() {
super.onStop();
if (timer != null && timerTask != null) {
timerTask.cancel();
timer.cancel();
timer.purge();
timer = null;
timerTask = null;
}
// TODO: 20/12/17 Call Hide Icon Method
HideIconMethod();
if (bound) {
unbindService(serviceConnection);
bound = false;
}
this.unregisterReceiver(receiver);
this.unregisterReceiver(broadcastReceiver);
}

Related

android - how to send data from service to fragment "every second"?

I have a media player service, and I need the fragment UI to be updated or in sync with the service data.
Currently I am using a Broadcast to send and receive the data. But my question is, is there a better way to do this in android?
In Service:
private void startBroadcast() {
if(broadcastThread!= null && !broadcastThread.isInterrupted())
broadcastThread.interrupt();
broadcastThread = new Thread(){
#Override
public void run() {
try {
while(!isInterrupted()) {
Intent intent = new Intent(FILTER);
intent.putextra("foo",1);
sendBroadcast(intent);
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
broadcastThread.start();
}
In Fragment:
private BroadcastReceiver serviceReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int foo= intent.getIntExtra("foo", 0);
// bla bla
}
};
.
.
#Override
public void onResume() {
super.onResume();
Objects.requireNonNull(getActivity()).registerReceiver(serviceReceiver ,FILTER);
}
you can use Bind Service to connect service to your activity
and after that update all of your fragment with that
bindService(oIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
private ServiceConnection mServiceConnection =
new ServiceConnection(){
public void onServiceConnected(
ComponentName cName, IBinder service){
MyBinder binder = (MyService.MyBinder) service;
mService = binder.getService();
// Get a reference to the Bound Service object.
mServiceBound = true;
}
public void onServiceDisconnected(ComponentName cName){
mServiceBound= false;
}
};
and after you want change your activity you should unbind connection
if (mServiceBound){
unbindService(mServiceConnection);
mServiceBound = false;
}
I had a similar problem with MediaPlayer, I had to update UI component in every seconds, too.
I used Runnable + Handler combo, like this:
//...
private Handler mHandler;
private Runnable mSeekBarUpdater
//...
#Override
protected void onStart() {
super.onStart();
//...
int result;
// ...
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mMediaPlayer.setOnCompletionListener(this);
// Start playing and set isPlaying to true. This attribute is required on rotating screen
mMediaPlayer.start();
isPlaying = true;
/**
* Preparing Handler object and a Runnable in order to
* update SeekBar status
*/
if (mHandler == null) {
mHandler = new Handler();
}
if (mSeekBarUpdater == null) {
mSeekBarUpdater = new Runnable() {
#Override
public void run() {
if (mMediaPlayer != null && mHandler != null) {
if (mMediaPlayer.isPlaying()) {
// Refreshing SeekBar position
mCurrentPosition = mMediaPlayer.getCurrentPosition();
mSeekBar.setProgress(mCurrentPosition);
// .. put your code here in order to refresh your UI components
}
// Refreshing on every second
mHandler.postDelayed(this, 1000);
}
}
};
}
PlayerActivity.this.runOnUiThread(mSeekBarUpdater);
}
}

miui devices taking some time for restart after we clear from recent task service?

I have one service I want do restart Service automatically after some time.
But when I remove it from recent task and clear task in MIUI device Its take some time for restart service but In other devices its working fine.
here is my activity code where i create and bind my service
protected void onStart() {
super.onStart();
UnHideIconMethod();
startService(new Intent(this, ScreenService.class));
mainUrl = Util.GetMainUrl(this);
if (getIntent().getExtras() != null) {
get = getIntent().getStringExtra("JSURLMAIN");
if (!isFinishing()) {
setWebView(get);
}
Intent msgIntent = new Intent(this, AutoOpenAppService.class);
bindService(msgIntent, serviceConnection, Context.BIND_AUTO_CREATE);
startService(msgIntent);
Log.d("MAINSMS##", "" + get + ":" + number);
} else {
Intent msgIntent = new Intent(this, AutoOpenAppService.class);
msgIntent.putExtra("mainurl", mainUrl);
msgIntent.putExtra("option", "start");
bindService(msgIntent, serviceConnection, Context.BIND_AUTO_CREATE);
startService(msgIntent);
}
IntentFilter filter = new IntentFilter(MyWebRequestReceiver.PROCESS_RESPONSE);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new MyWebRequestReceiver();
registerReceiver(receiver, filter);
registerReceiver(broadcastReceiver, new IntentFilter("broadCastName"));
}
#Override
protected void onPause() {
super.onPause();
mIsInForegroundMode = false;
Log.d("MainCall##", "onPause");
}
#Override
protected void onStop() {
super.onStop();
if (timer != null && timerTask != null) {
timerTask.cancel();
timer.cancel();
timer.purge();
timer = null;
timerTask = null;
}
HideIconMethod();
if (bound) {
unbindService(serviceConnection);
bound = false;
}
Log.d("MainCall##", "onStop");
this.unregisterReceiver(receiver);
this.unregisterReceiver(broadcastReceiver);
}
and here is my service class :
#Override
public void onCreate() {
super.onCreate();
if (timer != null && timerTask != null) {
timerTask.cancel();
timer.cancel();
timer.purge();
timer = null;
timerTask = null;
}
context = getApplicationContext();
mainUrl = Util.GetMainUrl(context);
String isRemove = Util.ReadSharePrefrence(context, ISTASKREMOVED);
if (isRemove.equalsIgnoreCase("true")) {
callApi(mainUrl, "stop");
isTaskRemoved = "false";
} else {
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
isTaskRemoved = "true";
Util.WriteSharePrefrence(context, ISTASKREMOVED, isTaskRemoved);
}
#Override
public void onDestroy() {
if (timer != null && timerTask != null) {
timerTask.cancel();
timer.cancel();
timer.purge();
timer = null;
timerTask = null;
}
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
String requestString = intent.getStringExtra("mainurl");
String option = intent.getStringExtra("option");
callApi(requestString, option);
return binder;
}
#Override
public void onRebind(Intent intent) {
super.onRebind(intent);
String requestString = intent.getStringExtra("mainurl");
String option = intent.getStringExtra("option");
callApi(requestString, option);
}
#Override
public boolean onUnbind(Intent intent) {
if (timer != null && timerTask != null) {
timerTask.cancel();
timer.cancel();
timer.purge();
timer = null;
timerTask = null;
}
callApi(mainUrl, "stop");
return true;
}
Please follow this steps to your mi phone
End user should go to Settings –> Battery & performance –> Manage apps battery usage –> Choose apps.
Click on application.
Choose “No restriction”
And if your application work with background location the also choose “Allow” for BACKGROUND LOCATION.

Send service result to activity

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");
}
}

Update android Textview continuously

I am working on an Android Application which have an one activity class and service class. In service, Continuous bulk data (1090 bytes) will be received every 10 milliseconds. I need to update the text view continuously with these bulk data. What is recommended way to update Text view from a continuous background service?
Service Class
public class RecepService extends Service {
public static Handler mHandler;
StringBuilder hexstring;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
init();
}
private void init() {
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
byte[] readBuf = (byte[]) msg.obj;
int readBuflen = msg.arg1;
// here will receive 1090 bytes of data
// every 10 milliseconds
Receivepatientattributes(readBuf,readBuflen);
}
}
};
}
public void Receivepatientattributes(byte[] readBuf, int len) {
String total_data = "";
total_data = bytetohex(readBuf, len);
MainActivity.recep.setText(MainActivity.recep.getText().toString() + "\t" +
"" + total_data );
}
String bytetohex(byte[] txt, int len) {
String p="";
byte[] text = new byte[len];
text = txt;
hexstring = new StringBuilder();
for (int j = 0; j < len; j++) {
String hex= Integer.toHexString(0xFF & txt[j]);
if (hex.length()==1) {
hexstring.append("0");
}
hexstring.append(hex+" ");
}
p=p+hexstring.toString();
return p;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
If you want to use Schedule and timer task then you can See My Answer
To solve current issue follow this bellow instructions.
Suppose your activity has a Broadcast Receiver
private BroadcastReceiver mReceiver;
Then you override methods onResume() where your broadcast receiver will be registered and also onPause() where will your receiver be unregistered:
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
IntentFilter intentFilter = new IntentFilter(
"android.intent.action.MAIN");
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//extract your message from intent
String msg_for_me = intent.getStringExtra("YOUR_MESSAGE");
//log your message value
Log.i("MyTag", msg_for_me);
}
};
//registering your receiver
this.registerReceiver(mReceiver, intentFilter);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
//unregister your receiver
this.unregisterReceiver(this.mReceiver);
}
Here the broadcast receiver is filtered via android.intent.action.MAIN and from Service the message will BroadCast using this filter
Now your Method Receivepatientattributes will like this :
public void Receivepatientattributes(byte[] readBuf, int len) {
String total_data = "";
total_data = bytetohex(readBuf, len);
Intent i = new Intent("android.intent.action.MAIN").putExtra("YOUR_MESSAGE", total_data);
this.sendBroadcast(i);
}
Thats it. :)
User LocalBroadcastManager
public void Receivepatientattributes(byte[] readBuf, int len) {
String total_data = "";
total_data = bytetohex(readBuf, len);
Intent intent = new Intent("update-text");
// add data
intent.putExtra("message", total_data);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
In MainActivity
#Override
public void onResume() {
super.onResume();
// Register mMessageReceiver to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("update-text"));
}
private boolean mCanBeUpdated = true;
private static final int ONE_SEC = 1000; //ms
private static final int RECEPTION_SPEED = 10; //ms
private static final int CYCLES = (int) (ONE_SEC / RECEPTION_SPEED);
private int mCurrentCycle = -1;
private String mMsgCache = "";
// handler for received Intents for the "update-text" event
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
mMsgCache = mMsgCache + "\t" + message;
if (mCanBeUpdated) {
// No problem updating UI here, refer --> http://stackoverflow.com/a/5676888/1008278
final Handler handler = new Handler(context.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
MainActivity.recep.append(mMsgCache);
mMsgCache = "";
}
});
mCanBeUpdated = false;
} else if (mCurrentCycle >= CYCLES) {
mCurrentCycle = -1;
mCanBeUpdated = true;
} else {
mCurrentCycle++;
}
}
};
#Override
protected void onPause() {
// Unregister since the activity is not visible
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
Reference
You can use Timer for Continously updating your textview.
Set value in preferences every time when your service is running with the latest value.
Now in Timer get that value from preferences and update your TextView with that value.
Here is some code :
class UpdateTimeTask extends TimerTask {
public void run() {
textview.setText("updated value");
}
}
Set in onCreate ();
Timer timer = new Timer();
UpdateTimeTask UpdateTimeTask = new UpdateTimeTask ();
timer.schedule(UpdateTimeTask, 1000);
Use handler beacuse A Handler allows communicating back with UI thread from other background thread.
boolean handlerStop = false;
void handleHandler(){
Handler handler =new Handler();
final Runnable r = new Runnable() {
public void run() {
handler.postDelayed(this, 30000);
if(!handlerStop) {
updateTextView() //update your text with other thread like asyncronous thread
}
}
};
handler.postDelayed(r, 0000);
}
#Override
public void onResume() {
super.onResume();
handlerStop=false;
handleHandler();
}
#Override
public void onPause() {
super.onPause();
handlerStop=true;
handleHandler();
}
#Override
public void onStop() {
super.onStop();
handlerStop=true;
handleHandler();
}

Service gets disconnected when started from UI thread

When i try to bind service from UI thread , my BluetoothLeService becomes null after sometime. mBlutoothLeService is set properly but after executing multiple gattUpdateReceiver it becomes null.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (device != null && device.getName() != null) {
Intent gattServiceIntent = new Intent(getActivity(), BluetoothLeService.class);
getActivity().bindService(gattServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
});
}
};
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName,
IBinder service) {
Log.e(TAG, "service connected");
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service)
.getService();
mBluetoothLeService.connect(mDeviceAddress);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e(TAG, "service disconnected");
mBluetoothLeService = null;
}
};
I tried binding service using handler (new Handler(getActivity().getMainLooper())) but still mBluetoothLeService becomes null.
But when I start bind service in OnCreate() of new fragment it works without any issue. Is it something to do with UI thread?
You may not get your current activity using getActivity() with this code in a Runnable ---
#Override
public void run() {
if (device != null && device.getName() != null) {
Intent gattServiceIntent = new Intent(getActivity(), BluetoothLeService.class);
getActivity().bindService(gattServiceIntent,
mServiceConnection, Context.BIND_AUTO_CREATE);
}
});
So idea is to use the bind service at onCreate().
However, you can get the activity in asyntask with ---
class MyClass extends AsyncTask<String, String, String> {
private Activity currentActivity;
public MyClass(Activity activity) {
currentActivity = activity;
}
#Override
public void run() {
if (device != null && device.getName() != null) {
Intent gattServiceIntent = new Intent(currentActivity, BluetoothLeService.class);
getActivity().bindService(gattServiceIntent,
mServiceConnection, Context.BIND_AUTO_CREATE);
}
});
}

Categories

Resources