Broadcast Receiver from Service to Fragment not working properly - android

I've implemented a Broadcast Receiver to pass data each second from Service that is running a CountDownTimer with the time remaining to the Fragment.
The problem is that Fragment is not receiving data properly or better to say that is receiving it only when I press some search button, hide the keyboard or something else in the activity.
Here is my Service Class:
CountDownTimer timer = new CountDownTimer(number, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeLeft = millisUntilFinished;
normalTime = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(timeLeft),
TimeUnit.MILLISECONDS.toMinutes(timeLeft) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeLeft)),
TimeUnit.MILLISECONDS.toSeconds(timeLeft) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeLeft)));
Intent timerInfoIntent = new Intent(TIME_INFO);
timerInfoIntent.putExtra("VALUE", normalTime);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerInfoIntent);
}
Here is my Fragment that is supposed to receive the data and update the item of a list view.
In onCreateView I register a receiver:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mTimerStatusReceiver = new TimerStatusReceiver();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIME_INFO));
...
}
Do the same on onResume:
#Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIME_INFO));
...
}
Unregister it onPause:
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mTimerStatusReceiver);
}
TimerStatesReceiver class:
private class TimerStatusReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction().equals(NotificationService.TIME_INFO)) {
if (!IS_ALREADY_EXECUTED) {
modelTimer = new ModelTimer();
if (intent.hasExtra("VALUE")) {
modelTimer.setexpirationTime(intent.getStringExtra("VALUE"));
}
listOfTimers.add(modelTimer);
mAdapter = new ListViewAdapter(getActivity(), listOfTimers);
mListView.setAdapter(mAdapter);
IS_ALREADY_EXECUTED = true;
}else{
for (ModelTimer timer: listOfTimers){
View v = mListView.getChildAt(timerPosition.get(timer.getId()));
timer.setexpirationTime(intent.getStringExtra("VALUE"));
timer.setName(intent.getStringExtra("NAME_FOOD"));
if (v == null) return;
TextView time = (TextView) v.findViewById(R.id.active_timer_timeLeft);
time.setText(timer.expirationTime);
}
mAdapter.notifyDataSetChanged();
}

Related

How to set limit when user enter wrong pattern many time?

Currentlly I am implementing pattern lock application and I want to set limit when user enter wrong pattern many time.Example,If user enter wrong pattern at that time set limit(3 or 4 time limit) and set delay 30 second and after 30 second give permission to enter pattern.
So,If anyone know how i can do this please give idea of that.
Here this my Reciever
public class LockScreenReceiver extends DeviceAdminReceiver {
Context context;
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("Action...","..."+action);
//If the screen was just turned on or it just booted up, start your Lock Activity
if(action.equals(Intent.ACTION_SCREEN_OFF) || action.equals(Intent.ACTION_BOOT_COMPLETED))
{
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
#Override
public void onPasswordFailed(Context ctxt, Intent intent) {
DevicePolicyManager mgr = (DevicePolicyManager) ctxt.getSystemService(Context.DEVICE_POLICY_SERVICE);
int no = mgr.getCurrentFailedPasswordAttempts();
if (no >= 3) {
context.startActivity(new Intent(context,ChangeActivity.class));
}
}
}
Service
public class LockScreenService extends Service {
DeviceAdminReceiver receiver;
#Override
public IBinder onBind(Intent intent) {
return null;
}
// Register for Lockscreen event intents
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
receiver = new LockScreenReceiver();
registerReceiver(receiver, filter);
startForeground();
return START_STICKY;
}
// Run service in foreground so it is less likely to be killed by system
private void startForeground() {
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(getResources().getString(R.string.app_name))
.setTicker(getResources().getString(R.string.app_name))
.setContentText("Running")
.setContentIntent(null)
.setOngoing(true)
.build();
startForeground(9999,notification);
}
#Override
#SuppressWarnings("deprecation")
public void onCreate() {
KeyguardManager.KeyguardLock key;
KeyguardManager km = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
//This is deprecated, but it is a simple way to disable the lockscreen in code
key = km.newKeyguardLock("IN");
key.disableKeyguard();
//Start listening for the Screen On, Screen Off, and Boot completed actions
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
//Set up a receiver to listen for the Intents in this Service
receiver = new LockScreenReceiver();
registerReceiver(receiver, filter);
super.onCreate();
}
#Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
}
Activity
public class MainActivity extends ActionBarActivity {
private Lock9View lock9View;
private static String MY_PREFS_NAME = "PatternLock";
private static String PATTERN_KEY;
SharedPreferences prefs;
Button btnChange;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(MainActivity.this, LockScreenService.class));
makeFullScreen();
setContentView(R.layout.activity_main);
btnChange = (Button)findViewById(R.id.btnChange);
btnChange.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent in = new Intent(MainActivity.this,ChangeActivity.class);
startActivity(in);
}
});
prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
lock9View = (Lock9View) findViewById(R.id.lock_9_view);
lock9View.setCallBack(new Lock9View.CallBack() {
#Override
public void onFinish(String password) {
PATTERN_KEY = prefs.getString("Pattern", "invalid");
if (PATTERN_KEY.equals("invalid")) {
Toast.makeText(MainActivity.this, "Options --> Create new Pattern", Toast.LENGTH_LONG).show();
} else {
if (password.equals(PATTERN_KEY)) {
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
}else{
Context context = getApplicationContext();
// Create layout inflator object to inflate toast.xml file
LayoutInflater inflater = getLayoutInflater();
// Call toast.xml file for toast layout
View toastRoot = inflater.inflate(R.layout.layout_toast3, null);
Toast toast = new Toast(context);
// Set layout to toast
toast.setView(toastRoot);
toast.setGravity(Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.BOTTOM,
0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.show();
}
}
}
});
}
private void makeFullScreen() {
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
if(Build.VERSION.SDK_INT < 19) { //View.SYSTEM_UI_FLAG_IMMERSIVE is only on API 19+
this.getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
} else {
this.getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE);
}
}
#Override
public void onBackPressed() {
return; //Do nothing!
}
public void unlockScreen(View view) {
//Instead of using finish(), this totally destroys the process
android.os.Process.killProcess(android.os.Process.myPid());
}
}
So,How i can achieve this...
Have a int field like failedCounter and increment it each time user inputs invalid patterns check if reached the limit then disable the input interface and have a handler to reset the value after the time delay.
int failedCount = 0;
final static int LIMIT = 5; //set your limit here
private void invalidPattern() {
if (++failedCount == LIMIT) {
//disable the input
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//reset the failed count
faildCount = 0;
//Enable the input interface here
}
}, 30000); // 30Sec delay
}
}
Use this two methods -
ScheduledThreadPoolExecutor c1;
private void IncorrectCallCounter() {
if (failedCounter>=0)
{
c1.shutdownNow();
LockScreenFor30Second();
}else
{
if (c1!=null)
c1.shutdownNow();
}
c1 = new ScheduledThreadPoolExecutor(1);
c1.schedule(new Runnable() {
#Override
public void run() {
failedCounter=0;
c1.shutdownNow();
}
}, 15, TimeUnit.SECONDS);
}
ScheduledThreadPoolExecutor c2;
private void LockScreenFor30Second() {
//Lock Screen Here
c2 = new ScheduledThreadPoolExecutor(1);
c2.schedule(new Runnable() {
#Override
public void run() {
//Unlock Screen Here
c2.shutdownNow();
}
}, 30, TimeUnit.SECONDS);
}
Declare failedCounter globally
private int failedCounter=0;
And call this method when you detect wrong pattern -
failedCounter=failedCounter+1;
IncorrectCallCounter();
If user enter wrong pattern 4 times in 15 seconds then this will call LockScreenFor30Second method. and inside LockScreenFor30Second add your code.

How to stop service started by another fragment of the same activity?

I have two fragments AlertTabFragment and WalkAloneTabFragment.
I have started a Service called LocationService from AlertTabFragment but I am unable to stop the LocationService from WalkAloneTabFragment.
The LocationService is a bit resource occupying since it has LocationListener and GpsListener. Since the LocationService is used for speedometer functionality with an alert system and it also updates the current location through a webservice and on top of that it has the functionality of GpsListener.
So whenever I am trying to call a webservice from WalkAloneTabFragment it is taking time so I want to stop the service whenever I call it and after that, I will again start the service, so that it does not allocate so much resources.
AlertTabFragment.java
public class AlertTabFragment extends Fragment
{
private final String TAG = AlertTabFragment.class.getName();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View root = inflater.inflate(R.layout.fragment_alert, container, false);
Log.d(TAG, "Inside onCreateView");
Intent serviceIntent = new Intent(getActivity(), LocationService.class);
getActivity().startService(serviceIntent);
return root;
}
#Override
public void onResume()
{
Log.d(TAG, "Inside onResume");
super.onResume();
BroadcastReceiver mReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(HomeScreenActivity.mBroadcastAlertAction))
{
// Code Related to Locaton Listener of LocationService.java
}
else if (intent.getAction().equals(HomeScreenActivity.mBroadcastAlertGpsAction))
{
// Code Related Gps Listener of LocationService.java
}
}
};
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(HomeScreenActivity.mBroadcastAlertAction);
mIntentFilter.addAction(HomeScreenActivity.mBroadcastAlertGpsAction);
mIntentFilter.addAction(HomeScreenActivity.mBroadcastWalkAloneAction);
getActivity().registerReceiver(mReceiver, mIntentFilter);
}
#Override
public void onPause()
{
Log.d(TAG, "Inside onPause");
super.onPause();
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.d(TAG, "Inside onDestroy");
}
}

Android notification keeps reappearing

I am trying to get a better handle on notifications with the simple app shown below (at least the relevant parts). I would like to show a notification icon when the app is not destroyed, and remove the notification icon when it is destroyed; pretty simple right?
My problem is that when the fragment's onDestroyView event is fired the notification icon does disappear, but then reappears and I can't figure out why.
To try to figure things out a bit better I create a stop notification button that calls the mServiceBinder's stop() method, which does remove the notification icon for good even though it is calling the same method called in the onDestroyView event.
Any ideas to what the problem is?
MainActivityFragment
package org.chrisolsen.notificationtest;
import ...
/**
* A placeholder fragment containing a simple view.
*/
public class MainActivityFragment extends Fragment {
private ServiceConnection mServiceConn;
private TestService.TestBinder mServiceBinder;
public MainActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
#Override
public void onDestroyView() {
Log.d("Fragment", "onDestroyView");
// *try* to prevent services from restarting
if (mServiceConn != null) {
getActivity().unbindService(mServiceConn);
}
if (mServiceBinder != null) {
mServiceBinder.stop();
}
mServiceConn = null;
mServiceBinder = null;
super.onDestroyView();
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
Log.d("Fragment", "onViewCreated");
Button showButton = (Button) view.findViewById(R.id.button);
Button hideButton = (Button) view.findViewById(R.id.btnHide);
showButton.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Fragment", "onCLick");
mServiceConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("serviceConn", "onConnected");
mServiceBinder = (TestService.TestBinder) service;
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d("serviceConn", "onDisconnected");
}
};
Intent service = new Intent(getActivity(), TestService.class);
getActivity().startService(service);
getActivity().bindService(service, mServiceConn, Context.BIND_ABOVE_CLIENT);
}
});
hideButton.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
mServiceBinder.stop();
}
});
}
}
TestService
package org.chrisolsen.notificationtest;
import ...
public class TestService extends Service {
public class TestBinder extends Binder {
public void stop() {
TestService.this.stopForeground(true);
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("TestSErvice", "onDestroy");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return new TestBinder();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TestSErvice", "onHandleIntent");
Context c = getApplicationContext();
Intent activityIntent = new Intent(c, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
c, 0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("The Content Text")
.setOngoing(false)
.setAutoCancel(true)
.setPriority(Notification.PRIORITY_LOW)
.setContentTitle("The content title");
startForeground(1, builder.build());
return super.onStartCommand(intent, flags, startId);
}
}
The notification reappears because your service onStartCommand called after your activity closed.
It is a bad place to create and show notification. onStartCommand method maybe called multiple times. Place the notification creation to the onCreate for example.
What do you mean when you wrote "app is not destroyed"? If you thought while your service is running, put the creation to the onCreate and remove it in onDestroy.
Returning START_STICKY instead of super.onStartCommand(intent, flags, startId), is what I should've been doing.

Android broadcast receiver get registered multiple times when activity minimise and maximise

Hi I am working with android.I am looking to update ui from service data. So that I get data from service via broadcast receiver succesfully and I updated listview when value changes.My problem is that during activity running, if i minimise the activity and then maximise, the another receiver is get registered and which will repeats my listview data.How can I set only one receiver when after maximise ? here is my code
public class MainActivity extends Activity {
ListView l1;
ArrayList<String> t1=new ArrayList<String>();
ArrayList<String> d1=new ArrayList<String>();
ArrayList<Integer> i1=new ArrayList<Integer>();
MyReceiver myReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
l1=(ListView)findViewById(R.id.listView1);
//l1.setAdapter(new dataListAdapter(t1,d1,i1));
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
//Register BroadcastReceiver
//to receive event from our service
myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MyService.MY_ACTION);
registerReceiver(myReceiver, intentFilter);
//Start our own service
Intent intent = new Intent(MainActivity.this,
com.example.androidservice.MyService.class);
startService(intent);
super.onStart();
}
#Override
protected void onStop() {
unregisterReceiver(myReceiver);
stopService(new Intent(MainActivity.this,MyService.class));
super.onStop();
}
#Override
protected void onPause() {
//unregisterReceiver(myReceiver);
stopService(new Intent(MainActivity.this,MyService.class));
super.onPause();
}
private class MyReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context arg0, Intent arg1) {
String datapassed1 = arg1.getStringExtra("DATAPASSED1");
String datapassed2 = arg1.getStringExtra("DATAPASSED2");
Toast.makeText(MainActivity.this,
"Triggered by Service!\n"
+ "Data passed: " + String.valueOf(datapassed1),
Toast.LENGTH_SHORT).show();
t1.add(datapassed1);
d1.add(datapassed2);
for(int i=0;i<t1.size();i++)
{
i1.add(R.drawable.ic_launcher);
}
l1.setAdapter(new dataListAdapter(t1,d1,i1));
}
}
class dataListAdapter extends BaseAdapter {
ArrayList<String> Title, Detail;
ArrayList<Integer> imge;
dataListAdapter() {
Title = null;
Detail = null;
imge=null;
}
public dataListAdapter(ArrayList text, ArrayList text1,ArrayList text3) {
notifyDataSetChanged();
Title = text;
Detail = text1;
imge = text3;
}
public int getCount() {
// TODO Auto-generated method stub
return Title.size();
}
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row;
row = inflater.inflate(R.layout.custom, parent, false);
TextView title, detail;
ImageView i1;
title = (TextView) row.findViewById(R.id.title);
detail = (TextView) row.findViewById(R.id.detail);
i1=(ImageView)row.findViewById(R.id.img);
title.setText(Title.get(position));
detail.setText(Detail.get(position));
i1.setImageResource(imge.get(position));
return (row);
}
}
}
Register the broadcast receiver and start the service in onCreate(), and
unRegister the receiver and stop the service in onDestroy().
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
l1=(ListView)findViewById(R.id.listView1);
//l1.setAdapter(new dataListAdapter(t1,d1,i1));
//Register BroadcastReceiver
//to receive event from our service
myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MyService.MY_ACTION);
registerReceiver(myReceiver, intentFilter);
//Start our own service
Intent intent = new Intent(MainActivity.this,
com.example.androidservice.MyService.class);
startService(intent);
}
#Override
protected void onDestroy() {
unregisterReceiver(myReceiver);
stopService(new Intent(MainActivity.this,MyService.class));
super.onDestroy();
}
You should register your BroadcastReceiver in onResume and unregister it in onPause. After that, you don't need to register/unregister it in any of the other activity's lifecycle methods.
#Override
protected void onResume() {
super.onResume();
registerReceiver(myReceiver, new IntentFilter(MyService.MY_ACTION));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(myReceiver);
}
I hope this helps.
There should be something missing here (Perhaps your manifest). It seemed correct to me how to handle your receivers (you don't necesarily to use onPause-onResume to register/unregister).
Please make sure you don't also register the receiver # the manifest file as well.

android: how to get broadcasted messages from service when activity is in background

I have a service and an activity. in service I broadcast messages received from network and in the activity show these messages. this works fine. but all messages will lost when the activity is in the background.
How can I get last messages(if exists) from server, in activity onResume(or onCreate)?
EDIT :
in service:
public class server extends Service implements Runnable
{
#Override
public void onCreate()
{
}
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onStart(Intent intent, int startID)
{
//initializing socket and begining listen
new Thread(this).start();
}
public void run()
{
String readed;
while (true)
{
if(reader == null) continue;
try
{
if ((readed = reader.readLine()) != null)
{
Intent intent = new Intent(SEND_DATA_INTENT);
intent.putExtra("type", "message");
intent.putExtra("content", readed.substring(1));
sendBroadcast(intent);
Thread.sleep(100);
}
}
catch (Exception ee) { }
}
}
}
and in activity:
public class menhaj extends Activity
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
#Override
protected void onResume()
{
if (dataUpdateReceiver == null) dataUpdateReceiver = new DataReciver();
IntentFilter intentFilter = new IntentFilter(server.SEND_DATA_INTENT);
registerReceiver(dataUpdateReceiver, intentFilter);
super.onResume();
};
#Override
protected void onPause()
{
if (dataUpdateReceiver != null) unregisterReceiver(dataUpdateReceiver);
super.onPause();
};
private class DataReciver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(server.SEND_DATA_INTENT))
{
Bundle bdl = intent.getExtras();
String type = bdl.getString("type");
if (type.equals("message"))
{
String message = bdl.getString("content");
db.addMessage(message);
showMessage(message);
}
}
}
}
}
If that activity is in the background, the user probably doesn't want to see messages from it. Show notifications from your services instead. Generally, an activity should de-register itself onPause() and register again onResume() when it comes back to the foreground.
I would declare BroadcastReceivers , those can receive messages and bring back to from your avtivity / app

Categories

Resources