The appropriate way to leave an Android app? (Xamarin) - android

I'm developing an Android using Xamarin. The app has a login modal and I would like the behavior of the back button on the login modal to essentially exit the app, as if you were at the end of the navigation stack.
Is this possible?

If you are displaying the modal on android via a new Activity, override OnBackPressed in the modal activity like so:
public override void OnBackPressed()
{
Intent intent = new Intent(Intent.ActionMain);
intent.AddCategory(Intent.CategoryHome);
intent.SetFlags(ActivityFlags.NewTask);
StartActivity(intent);
}

As the solution that #wishmaster provided does give the appearance of the behavior I was looking for, I marked his as as acceptable.
For completeness though, I did run across a more appropriate solution. There's a MoveTaskToBack() method on the Activity class. So this is what my solution was:
public void CloseApp()
{
var mainActivity = Forms.Context as MainActivity;
if (mainActivity != null)
mainActivity.MoveTaskToBack(true);
}
To explain the context a little more. I'm developing a Xamarin Forms app and this is a method on an interface that's injected into the login Forms page.

Related

How to Remove the MvvmCross Messenger Subscriptions

I am using MvvmCross for my Xamarin.Android Application. I am using Messenger for Communication between my Service and ViewModel. Eg: HomeViewModel has a Subscription for ItemRefresh Method. I used to Publish from Service for any change in Items. Below is the example code snippet.
public class HomeViewModel
{
private MvxSubscriptionToken _updatedItemToken;
public HomeViewModel()
{
_updatedItemToken = messenger.Subscribe<UpdatedItemMessage>(ItemUpdated);
}
public void ItemUpdated(UpdatedItemMessage message)
{
//my code to refresh the page.
}
}
What is the Problem now?
Everything is working fine until I Introduce logout feature.
During Logout, Irrespective of where you are in the app, I need to clear all the activities from navigation stack and navigate to login page
After Logout, If I goes to HomeViewModel, The Subscription added again and the messages doubled up (hitting twice on each publish message).
What I have tried?
Purge the Subscription On Logging out. using _messenger.RequestPurgeAll();
Tried purging individual message like below
if(_messenger.HasSubscriptionsFor())
{
messenger.RequestPurge(typeof(UpdatedItemMessage));
}
Unsubscribe the Message OnDestroy(). It works well on navigations of the page but not during logout. Logout will clear all activities immediately which will not call OnDestroy of every Visible Activities. Logout code is below.
var intent = new Intent(this, typeof(LoginView));
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
StartActivity(intent); Finish();
Any help would be appreciated? I don't understand the use of RequestPurge which should ideally help for me but not.
Have you tried disposing the MvxSubscriptionToken you get from the messenger?
In your case:
_updatedItemToken.Dispose();
This should make the subscription go away.

Show a splash screen with MvvmCross after Android purged an application from memory

Here is my scenario: when my app gets purged from memory by the OS and its reopened from the recent apps list, it goes straight to the Activity that was last open. When this happens I would like to initialize a couple of business objects.
My first approach to achieve this was to do the initialization in the InitializeLastChance method in the Setup class.
Inside the InitializeLastChance method I check if the current top activity is the MvxSplashScreenActivity. If it's not, I make the necessary initialization. The code is something like this:
protected override void InitializeLastChance()
{
try
{
var topActivity = Mvx.Resolve<IMvxAndroidCurrentTopActivity>().Activity;
if (topActivity.LocalClassName != _splashScreenName)
{
//Do special initialization
}
}
catch (Exception ex)
{
//Log error
}
base.InitializeLastChance();
}
This works as expected but the visual effect isn't the best: a blank screen with the name of the app appears for a couple of seconds while the initialization occurs. When the initialization is finished, the last open activity is loaded.
To avoid this blank screen, I wanted to try a different approach: show an Activity while the initialization is being done, similar to a splash screen, so that the user can have some feedback that something is happening. In this approach the ViewModel attached to the new Activity would do the initialization that I want.
To show this new activity, I tried creating a custom IMvxAppStart and register it in the App class, but that hasn't worked. My custom IMvxAppStart has the following code:
public class CustomAppStart
: MvxNavigatingObject
, IMvxAppStart
{
public void Start(object hint = null)
{
if (hint == null)
{
ShowViewModel<LoginViewModel>();
}
else
{
ShowViewModel<InitializationViewModel>();
}
}
}
I wanted to show the LoginViewModel when the app starts from scratch and in the cases where the app goes straight to the last loaded Activity, the InitializationViewModel would be shown. In the latter scenario the Start method isn't called. I've checked the MvvmCross source code and as far as I can understand, the Start method is called by the MvxSplashScreenActivity (correct me if I'm wrong). When an app is reopened and goes straight to the last opened Activity, the MvxSplashScreenActivity isn't used so the Start method in CustomAppStart is not called.
That being said, I have some questions regarding the CustomAppStart approach:
Is this approach the best way to show a splash screen or "initialization activity" in the cases where the app goes straight to the last opened activity?
How do I use the CustomAppStart in these situations, since it seems that the Start method is called only from the MvxSplashScreenActivity?
How do I pass a value to the hint parameter in the Start method?
Thanks

Android: Two actvities as launchers

I'm developing locker application. I created service and receiver to hide default android locker. But for few days I have problem with settings activity. I'm looking for a solution, how to make two activites as launchers. I want to make something like that:
Locker activity is only launched when phone is locked. And Settings activity only when I press app icon in menu. Is it possible to programme?
Thanks for help.
You can try to launch the same activity but changing the content view (into onCreate) for each situation. Something like:
if (isLocked()) {
setContentView(R.layout.locker_activity);
} else {
setContentView(R.layout.settings_activity);
}
You can use just one activity as launcher and use Fragments to load what you want. Something like this:
public class LauncherActivity extends FragmentActivity {
super.onCreate(savedInstanceState);
Fragment fragment;
if (isLocked()) {
fragment = new LockerFragment();
}
else {
fragment = new SettingsFragmentFragment();
}
getFragmentManager().beginTransaction().add(R.id.container_id,fragment).commit();
}

Double Activity window when using intent for achartengine graph

Development Environment: Eclipse 3.7.0
Developing: Android 3.2 application for Market Place
Using: aChartEngine 0.7.0
I'm new to the development scene but have done a bit of coding in the past various languages, I've created the ZopaStats(on Marketplace) app, but I'm now trying to convert a text based stats page to be displayed in a bar graph using achartengine.
I can get the graph to display from an activity via another activity i.e.:
Intent achartIntent = new TemperatureChart().execute(this);
startActivity(achartIntent);
but this gives me an additional activity screen i.e.:
Main Screen -> 1st Activity (Original Text Stats View) -> 2nd Activity (Graph)
Therefore, with I hit back on the graph screen, I get the blank 1st activity screen.
I hope I'm making sense here.
So what I tried to do was launch the activity from the Main Screen (i.e. my Main class) e.g.
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent achartIntent = new TemperatureChart().execute(this);
startActivity(achartIntent);
}
});
But eclipse gives me the following error in the code:
The method execute(Context) in the type TemperatureChart is not applicable for the arguments new (View.OnClickListener(){}}
I've tried letting Eclipse change the method but this then causes other problems, so I think what I'm really looking for (in a round about way) is to find out what the difference is when I can try to start the activity from another Activity class rather than starting it from the main class.
I apologise for the misuse of terms etc, as I say I'm new. I've been looking at this for a few days now but the Intent and Activity documentation doesn't help me much so I just need a few pointers.
Thanks,
In your example, the this reference that you're passing to execute() is your annonymous inner subclass of OnClickListener. This is not a context object, which is what eclipse is complaining about.
Rather, you want to pass in the activity instance. Assuming the code snippet you posted lives in a class named MyExampleActivity, then you can use MyExampleActivity.this from inside the inner class to access the instance of the containing class. You should be able to pass that to TemperatureChart.execute()
There is no difference in starting an activity from the main activity or from any other activity. You just create an intent, and call startActivity on it.
For completeness, the new code is this:
N.B. My original class is called ZopaStats.class
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent achartIntent = new MarketZopaGraph().execute(ZopaStats.this);
startActivity(achartIntent);
}
});
This works great, only a single Activity windows, once again many thanks for the quick response, in record time ;)
when we use achartengine to draw graph in includes it own activity...i.e.org.achartengine.GraphicalActivity..
when we press back it shows own activity which is used to show graph..to hide these activity call finish() method on onPause() method.

Kill and destroy activity

The first screen of my application is a login screen, so I used the method finish () after user have logged. However when i return the application I would like to be already logged. I tried to use onDestroy (), but without success.
It'll be better if you implement your logic otherwise. The first screen in your application can be HomeScreenActivity in which you'll check if the user is logged and start LoginActivity if needed.
public class HomeScreenActivity extends Activity {
/* some declaration */
public void onCreate(Bundle savedInstanceState) {
/* some other stuff */
if (!userIsLogged()) {
Intent intent = new Intent(this,LoginActivity.class);
startActivity(intent);
}
}
}
You have to use SharedPreferences.
See Data Storage on Android Developer
You might want to have a look at the Activity Life Cycle... Furthermore SharedPreferences can be used to save username/login details but im of the understanding that they can be accessed by any application, so be careful what you put there.

Categories

Resources