I have a service that turn on my app sometimes, the main activity prompt Dialog message to user sometimes,
after the user answer YES\NO I call to finish() to close the app.
my problem is when the message is shown, user answers it and app was call to finish() and when you look in the recent history you played before (in samsung for example you press long on home button) you will see my app along with other apps user started.
when you push it to open it again the Dialog show again..
How to show the activity when launched from recent app without showing the Dialog
public void dialog_1(){
myDialogViewN = new MyDialogViewNegativeTime(MainActivity.this);
// Setting vibrator
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
long[] pattern= {100, 1000};
vibrator.vibrate( pattern,0 );
// Setting 2 Dialog Listeners
myDialogViewN.setOnDialogListener(new DialogListener() {
#Override
public void onNegativeClick()
{
// Stopping Vibraror
if (vibrator.hasVibrator()){
vibrator.cancel();
vibrator = null;
}
initialize_DialogToUser(); /// ??
SendDataToService(3); //doesn't want reminder
myDialogViewN.dismissDialog();
waitForDialogAnswer=false;
finish();
}
#Override
public void onPositiveClick()
{
// Stopping Vibrator
if (vibrator.hasVibrator()){
vibrator.cancel();
vibrator = null;
}
initialize_DialogToUser();
SendDataToService(1); //remind!
myDialogViewN.dismissDialog();
squre.setImageResource(R.drawable.triangle_red2);
waitForDialogAnswer=false;
finish();
} });
myDialogViewN.show();
}
#Override
public void onDestroy()
{
super.onDestroy();
// close/stop running application on background
int id= android.os.Process.myPid();
android.os.Process.killProcess(id);
}
finally i find solution,
the problem was when you open the app from history - the last intent that comes from service to your activity stay there and not goes, in contrary for openning the app by click it's own icon. (different openning ways).
my solution:
send 2 intent's from service to activity,
the first - with what you really need.
the second - after you receive your answer in the service. in the second you will not put any data! it is a mere intent that comes to change the "stuck" intent in history-app open way.
maby it is stupid, but it's the only solution i found :)
Related
Here is the use case:
1. User logs into the app and presses the hardware home button and app is sent to background
2. I run a handler in the background to check if the inactivity time out is 5 mins. Then I need to call the logout API and start the loginactivity, Without launching or bringing the app to foreground
Here is what I have tried
if (!mIsAppInForeground) {
Log.d("App in background", "App in background and timing out");
activity.startService(new Intent(activity,LogOutBackGroundService.class).addFlags( Intent.FLAG_ACTIVITY_MULTIPLE_TASK ));
}
public class LogOutBackGroundService extends Service {
public static final String HAS_SIGNED_OUT = "hasSignedOut";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
intent.putExtra(HAS_SIGNED_OUT, true);
startActivity(new Intent(this, LoginActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
The app is timing out properly and login activity is being launched, but the app is being brought to foreground (i.e app is being launched). I want this to happen in the background only. Only when the user relaunches the app, he should see the login screen again
startactivity(intent) pops up the backstack activity or creates a new one if it doesn't exist.. so your solution is there is onResume() and onPause().. onPause() is called when you the activity is gone, onResume() is called when you see the activity, so my advice to you is create a boolean, it can be in a singleton class
public class MySingletonClass {
public static boolean startloginpage; // by default its false
}
then you in mainactivity or the activity that the user will launch or come back to, put the code in its onresume
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
if(MySingletonClass.startloginpage){ //check if your boolean is true
// if it checks out then call do what you want to do when the user times run out
}else{
// if it doesn't check out continue without telling user to login,
}
}
in your service remove the intent code and put this
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
intent.putExtra(HAS_SIGNED_OUT, true);
MySingletonClass.startloginpage = true;
return START_NOT_STICKY;
}
In a typical logout scenario , clicking on logout button should just start the login activity clearing the login details. In your case after 5 mins you should try to clear the stored token for login ( assuming you store the login details for the user to login automatically when required). When the user launches the app next time your LAUNCHER activity would check for the stored token to launch the required activity.
I am currently working on a test application that will show a dialog that asks the user to stop using the app if he/she is driving. Supposing that the user has their GPS on, I have created a custom intent to be broadcast and then on the onReceive() method of the subclassed BroadcastReceiver class, the speed of the vehicle is calculated and if it's found to be in the range of usual car speeds, a dialog is shown to the user.
The second part (the onReceive() code) works great: the speed is calculated and the dialog is shown. However, I am at a loss about how the dialog can be shown at any point of the lifeycle of that specific activity. If the app is launched while the user is driving or if the user navigates to another activity and then back to the activity that does the speed check (essentially, if onCreate() or onResume() are called), the dialog is shown. If the dialog is dismissed and the user stays on the same activity, the dialog is not reshown, even if the user keeps driving (to be clear, the desired behavior is for the dialog to keep getting shown for as long as the user keeps driving and is in the activity). Here is the code of the activity that sends the Broadcast(the relevant code, everything else is omitted):
public class MainActivity extends Activity {
IntentFilter intentFilter;
SpeedReceiver speedceiver = new SpeedReceiver();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
broadcastSender();
intentFilter = new IntentFilter();
intentFilter.addAction("com.example.animationshitz.ACTION_GET_SPEED");
}
public void onResume() {
super.onResume();
registerReceiver(speedceiver, intentFilter);
Log.d("Loggger", "BROADCAST RECEIVER REGISTERED");
}
public void onPause() {
super.onPause();
unregisterReceiver(speedceiver);
}
public void broadcastSender() {
Intent intent = new Intent();
intent.setAction("com.example.animationshitz.ACTION_GET_SPEED");
sendStickyBroadcast(intent);
Log.d("Loggger", "BROADCAST SENT");
}
}
Am I completely wrong about this? I thought that the sticky broadcast would keep calling the onReceive() method of the receiver so that it would keep checking the speed in the background. Is there some other way to achieve what I want? Maybe the onReceive() method should start a service that keeps checking the speed in the background? Any help would be really appreciated.
I am creating simple widget for contact management, which allows user to dial and send sms to desired contact.
It works fine as "normal widget", but when I add it as lockscreen widget on Android 4.2, sms app or dial app does not start.
Well in fact they star, but "behind" lockscreen, so user still must manually unlock screen to be able to dial/send sms.
I searched web for some solution, but nothing come in handy.
I' am aware of FLAG_DISABLE_KEYGUARD or FLAG_SHOW_WHEN_LOCKED, but since sms/dial apps are not "mine" so i dont know if they set up proper flag.
As a workaround i tried to create my activity which set those flag and then simply starts desired one (dial or sms), but this does not help.
There is a way to unlock screen, but this involves using KeyguardManager and KeyguardLock (which work fine), but in a result of using KeyguardLock.newKeyguardLock() I end up with phone not being able to turn lock automatically, surely because I do not release this lock (it causes lock to appear again, which is not what i want).
In fact, this widget should work simmilarly to default sms widget or mail widget on lock screen?
So, my question is, how to achieve that and start new activity from lockscreen?
Well, i found solution myself. it turned out i was close :)
To launch 3rd party app/activity, simplest solution is to create some kind of proxy activity, which will set proper flags on window and then launches desired activity and FINISHES.
sample code is shown below:
calling intent in widget (calling proxy):
#Override
public void onReceive(Context context, Intent intent) {
Utilities.printLog(TAG, "onReceive");
Utilities.printLog(TAG, "intent: " + intent);
if (intent.getAction().equals(ACTION)) {
final String number = intent.getStringExtra(EXTRAS);
Toast.makeText(context, "Selected number: " + number,
Toast.LENGTH_SHORT)
.show();
/** REMOVING KEYGUARD RECEIVER **/
// not really an option - lock is still holded by widget and screen
// cannot be locked again ;(
// KeyguardManager keyguardManager = (KeyguardManager) context
// .getSystemService(Context.KEYGUARD_SERVICE);
// KeyguardLock lock = keyguardManager
// .newKeyguardLock(Context.KEYGUARD_SERVICE);
// lock.disableKeyguard();
final Intent activity = new Intent(context, MainActivity.class);
activity.putExtras(intent.getExtras());
activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
activity.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
context.startActivity(activity);
}
super.onReceive(context, intent);
}
in proxy activity just call:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
final Intent callingIntent = getIntent();
final String actionToLaunch = callingIntent.getStringExtra(ContactsStackWidgetProvider.ACTION);
final String number = callingIntent.getStringExtra(ContactsStackWidgetProvider.EXTRAS);
final Intent activity = new Intent();
if (actionToLaunch.equals(Intent.ACTION_DIAL)) {
activity.setAction(Intent.ACTION_DIAL);
activity.setData(Uri.parse("tel:"+number));
} else if (actionToLaunch.equals(Intent.ACTION_SENDTO)) {
activity.setAction(Intent.ACTION_SENDTO);
activity.setData(Uri.parse("sms:"+number));
} else {
throw new IllegalArgumentException("Unrecognized action: "
+ actionToLaunch);
}
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startActivity(activity);
finish();//it is important to finish, but after a small delay
}
}, 50L);
}
I tried one millions way, but in every way the music keeps playing when i play the HOME button of my mobile.
My last attempt was with application, but i still have the same problem.
This is my code.
public class ProvaMusica extends Application {
Intent musica_backGround;
public Background_music musicaDiBackground = new Background_music();
public void avvia(){
//this is the class where i manage mediaplayer//////////
musica_backGround=new Intent(this, Background_music.class);
startService(musica_backGround);
}
public void onDestroy(){
stopService(musica_backGround);
}
}
In my first activity i use this code to start the music
ProvaMusica appState = ((ProvaMusica)this.getApplication());
appState.avvia();
Now, what should i do to let the music play when showing other activities and make the music stops when my app is not displayed?
I WANT THE MUSIC TO KEEP PLAYING WHILE MOVING FROM AN ACTIVITY TO ANOTHER, I DON'T WANT TO STOP THE MUSIC AND THEN START IT AGAIN, WHEN A NEW ACTIVITY STARTS.
The way I do this is:
I have a singleton class that is the SoundManager.
On onPause each activity calls soundManager.stopPlayingDelayed. This method starts a timer that will call soundManager.checkIfShouldStop in 1 or 2 seconds. It also saves the lastCloseTime to the current time.
Each activity on it's onResume calls soundManager.startPlaying. If already playing the sound manager will ignore the request. This also clears the lastCloseTime
In checkIfShouldStop , if the lastCloseTime is not zero and is more than 1 second ago, it means that after the last activity finished, no new activity of my app was started, so the music should be stopped.
You can have an Application class and set it in AndroidManifest. in its onDestroy() callback, you can use stopService() function to stop the service or you can start the service with an Intent to stop the music.
Your app works as a process in the Android operating system. There are various ways for Android OS to terminate processes and sometimes callback functions like onDestroy() may not be called before the process is killed. Therefore if you start and play your music in a service, the music will play as long as your process lives. However, if you want it to stop, when a specific activity of your app is killed, you can override onDestroy() of that activity and broadcast a message for your service to stop the music. Use a service to implement this.
Maybe i found a way mixing the suggestions all of you gave me.
WITH THIS CODE THE BACKGROUND MUSIC (IN THIS CASE MANAGED WITH A SERVICE) STOPS ONLY WHEN USERS CLOSE THE APP WITH THE BACK BUTTON, WHEN USERS CLOSE THE APP WITH THE HOME BUTTON AND WHEN SCREENS TURN OFF BECAUSE USERS LOCK THE SCREEN WITH THE LOCK BUTTON OF THE DEVICES.
I'd like someone more expert and good at programming than me to confirm this is correct
in this class i check if my current activity is in foreground or not
public class GestioneApplicazioneInBackground{
public static boolean applicazioneInBackground(final Context context) {
ActivityManager am = (ActivityManager) MainActivity.context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
}
in onStop() and onPause() methods of all my activities i have this code
/// if my app and his activities are in background i stop the service i started in my main/first activity////
if(GestioneApplicazioneInBackground.applicazioneInBackground(this) ){
context_of_the_Intent.stopService(intent);
}
else{
// if my app and his activities are NOT in background i check if user turned off the screen with the lock button of the device//////
PowerManager kgMgr = (PowerManager) getSystemService(Context.POWER_SERVICE);
boolean showing = kgMgr.isScreenOn();
if(!showing){
context_of_the_Intent.stopService(intent);
}
}
Use this one : Tf you usr media player then Call this method in your activity...
MediaPlayer mp=null;
#Override
protected void onDestroy() {
super.onDestroy();
if (!(mp == null)) {
if (mp.isPlaying()) {
mp.stop();
mp.release();
mp = null;
}
}
};
v #Override
protected void onResume() {
super.onResume();
if (!(mp == null)) {
if (mp.isPlaying()) {
mp.stop();
mp.release();
mp = null;
}
}
};
There are a class of Android applications that enable password protection on certain user-specified apps; for example, Android Protector. I need to approach this problem from a different direction.
Is it possible to create an application that blocks all activity launches unless they are on a predefined whitelist? Will there be unintended consequences with this approach? I am familiar with Android basics and have written a few reasonably simple apps, but I'm still trying to figure out how these "Protector" apps intercept the launch intents correctly. Would someone mind giving me a brief overview on the correct way to do this?
The basic problem is that we have a generic Android phone that needs to be locked down so that our clients (internal only) can access our custom applications without being able to play "Need for Speed", etc. I would like to remove the carrier bloatware, but rooting the device seems like it would be a maintenance headache. We want the setup for each phone to be as simple as installing a few custom applications.
Edited to elaborate on the solution
Overview
My simple solution was to add a new service and activity to my application. The service uses Handler and postDelayed to continuously schedule the monitoring task. The monitoring task checks that the current activity is on the whitelist. Getting the currently running activity involves ActivityManager and a call to getRunningTasks. After finishing the check, the monitoring task schedules itself to run again after X seconds (1, in my case).
If the activity on top is not on the whitelist, we launch the blocking activity which pops up over whatever is currently running. The key part of the blocking activity is that it overrides onBackPressed, preventing the user from simply going back to the "bad" activity. Pressing the Home key is the only way (to my knowledge) to leave this screen.
Tips
Build a backdoor into the lock screen. For example, my solution prompts for a password on a long-press of the back key. After entering the correct password, the monitor service goes to sleep for 5 minutes so I can do my administrative work
Display the name of the blocked activity
Gather a good whitelist before turning this on! Activities you should definitely whitelist: the launcher, package installer, your own app (obviously), the browser, if your app has a web-based component
I don't like that my service is constantly looping in the background; it seems wasteful. I'd like to find some way to be notified when a new task is being launched, but I couldn't find a way to do that. The battery usage for my particular value of the monitor period and my particular phone is acceptable; though you should definitely test before adopting this yourself.
an efective solution,and here is the code from author's opinion
public class MonitorService extends Service {
private Handler handler;
Runnable runnable;
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
new Thread(new Runnable() {
#Override
public void run() {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am
.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
String currentActivityName=componentInfo.getClassName();
String packageName=componentInfo.getPackageName();
if(whitelist.contains(currentActivityName)){
Intent launchIntent = new Intent();
launchIntent.setComponent(new ComponentName(blockActivityPackageName,
blockActivityName));
launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(launchIntent);
}
}
}).start();
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runnable, 1000);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Intent intent = new Intent(this, MonitorService.class);
startService(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
As you suggest, writing a custom launcher is probably would be cleaner; check out this open source launcher for reference http://code.google.com/p/adw-launcher-android/