So, I'm kind of a noob in Android but I searched a lot for this and I was not able to find a solution:
In my navigation drawer, each row opens a new intent. How can I check if a certain intent is open/active so that I'll use that instead of creating a new one?
I tried using this solution:
Link
But my issue is that the drawer opens the same class everytime, but each class has different "extras." For example:
public void itemClicked(View view, int position) {
Intent intent=null;
switch (position) {
case 1:
intent = new Intent(getActivity(), DisplayActivity.class);
intent.putExtra("ARGUMENT","SECTION 1");
break;
case 2:
intent = new Intent(getActivity(), DisplayActivity.class);
intent.putExtra("ARGUMENT","SECTION 2");
break;
case 3:
intent = new Intent(getActivity(), DisplayActivity.class);
intent.putExtra("ARGUMENT","SECTION 3");
break;
}
startActivity(intent);
}
How can I check if an intent with that class and with those extras is already open?
Thanks!
You can use shared preferences or extent from Application class where you store last/current activity visible
If you extend class for Application or you are targetting devices API Level 14 or above you can implement ActivityLifecycleCallbacks.
Sample Code
public class MyApplication extends Application implements ActivityLifecycleCallbacks {
private static boolean isMySomeActivityVisible;
#Override
public void onCreate() {
super.onCreate();
// Register to be notified of activity state changes
registerActivityLifecycleCallbacks(this);
....
}
#Override
public void onActivityResumed(Activity activity) {
if (activity instanceof YOURACTIVITY) {
isMySomeActivityVisible = true;
}
}
#Override
public void onActivityStopped(Activity activity) {
if (activity instanceof YOURACTIVITY) {
isMySomeActivityVisible = false;
}
}
// Other state change callback stubs
....
}
You can also check about the launch modes in android which you make use of.
I think it will serve your requirement well.
For your reference have a look at this
http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode
Related
I'm a beginner and I have (I think) a simple question for you. I have a method used in every Activity except LoginActivity. It's opened when I click on the shutdown icon. This is code ->
public void logOut(MenuItem item) {
Intent intent = new Intent("THIS_CLASS".this, LoginActivity.class);
startActivity(intent);
}
but I do not want to duplicate it in every Activity, may exist any solution ? I am writing here because I can't find a solution on the Web. The problem is that I can not express my intentions in the question on the Internet. Every "duplicate method" gives answers not on the subject. I am not looking for complete code. I prefer only prompt.
Firstly, create a help class and add a static method like this:
import android.content.Context;
import android.content.Intent;
public class MyHelper {
public static void startActivityB(Context context) {
Intent intent = new Intent(context, LoginActivity.class);
context.startActivity(intent);
}
}
Then call the method and pass correct context like below:
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MyHelper.startActivityB(YourActivity.this);
}
});
Note: if MyHelper, LoginActivity,YourActivity are not in a same package, you should import corresponding package, that is an easy job.
It's not the best solution, but if you want a bunch of activities to share the same methods, then create a BaseActivity that they all extend from.
public abstract class BaseActivity extends Activity {
//... Shared stuff
protected void logOut() {
//Do some data cleaning and whatever else you need
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
startActivity(intent);
}
}
public class MyActivity extends BaseActivity {
//... Main code
private void onLogOutClicked() {
logout();
}
}
Just make sure you clean out your authentication/session data when this occurs. Try to utilise inheritance for shared functionality.
I am creating an abstract base class to keep my navigation drawer code in one place and want to implement an onClickListener on my app title (defined in the toolbar) to start my launch activity
I am using the following code :
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.toolbar_title:
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
return;
}
}
The app works properly, but I read somewhere that one must not use the Application context to start new activities. However, android studio doesn't let me use any other context apart from getApplicationContext and getBaseContext, maybe because this class is abstract.
Which context should I use then?
Have a look at Context.getApplicationContext() and ContextWrapper.getBaseContext(). Both have in common to be defined on a context instance. In your case it's even an Activity.
So you could even use this as a context to start your MainActivity. This is even better, because with any other context type you' have to include the flag FLAG_ACTIVITY_NEW_TASK to start a new activity.
If you get errors by using this for a context, it's because you define your OnClickListener as anonymous inner class which of course isn't a context. For that you'd have to write MyBaseActivity.this instead. This references the outer class instance.
Well, one of the ways can be: You can define an abstract method in your BaseActivity class:
abstract void launchMainActivity();
And call this method in your click listener:
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.toolbar_title:
launchMainActivity();
return;
}
}
The sub-classes can then implement this method as:
#Override
void launchMainActivity() {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
I'm new to android and trying to find out how to show a new screen when the user clicks something in the menu item.
I'm using ActionbarSherlock and looking at the sample github-android app.
When the user clicks on an item in the menu, I want to show them a new screen. Github code is doing that like so:
startActivityForResult(new Intent(getActivity(), CreateGistActivity.class), GIST_CREATE);
But I've seen some code samples do:
Intent i = new Intent(getApplicationContext(), SomeActivity.class);
My code looks like this:
public class MainActivity extends SherlockActivity {
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create) {
//show createactivity class
return true;
}
return true;
}
What is the right way to do ?
You can do it just like that:
public class MainActivity extends SherlockActivity {
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create) {
//show createactivity class
Intent i = new Intent(MainActivity.this, SomeActivity.class);
startActivity(i);
return true;
}
return true;
}
startActivityForResult is used when you have to return some value/data to the first screen like a user selection. More here
As far as the context to use getActivity() or getApplicationContext(), I prefer to use the context of current activity MainActivity.this its more straitforward similar to documentation example
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
Inside a fragment use getSherlockActivity() instead of getActivity() as getActivity() can cause crashes to older devices.
Of course getApplicationContext() would always work and not crash but I feel that it may mess the garbage collector and do not let activities to be cleared (but not sure about it)
Just use startActivityForResult
There is no 'right' way. The Github code doesn't first declare the variable. The onther does. I believe for a menu, you normally need to declare the Intent as a local variable, if not a field.
Create an intent: Intent i = new Intent(MainActivity.this, CreateGistActivity.class);
where MainActivity is the activity you're in, and CreateGistActivity is the class you want to launch.
Then use startActivity(Intent) to launch the new activity: startActivity(i);
Or just combine them:
startActivity(new Intent(MainActivity.this, CreateGistActivity.class));
Full code:
public class MainActivity extends SherlockActivity {
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create)
{
Intent i = new Intent(MainActivity.this, CreateGistActivity.class);
startActivity(i);
return true;
}
return true;
}
startActivityForResult probably isn't needed in your case, unless you're expecting to send values between the classes.
I am developing a multi level game, where each level is a new activity.
I want to know, if i change the activity like
Intent myIntent = new Intent(getBaseContext(), Level3.class);
startActivity(myIntent);
The memory used for Level 1 and 2 is cleared?
If not, how can I clear everything from previous level activities so the phone uses just the memory just for the current activity ?
You need to call finish() for the activity (or activities) that you no longer want to be active. You can simply call it right after starting the new activity:
Intent myIntent = new Intent(getBaseContext(), Level3.class);
startActivity(myIntent);
finish();
Otherwise, the previous activity will remain on the activity stack.
since you are using an activity/level design, just add a check if your activity is finishing in your onPause method, and null all your references to the current level, that way the GC will know that your level object should be released, and it will release it as soon as possible.
#Override
public void onPause(){
super.onPause();
if (isFinishing()){
levelObject = null;
}
}
I would not recommend you to create Activity for each of your game level. Would be better to create some Controller that will initializate you game levels in one Activity. And of cource it must have some methods to clear memmory from last stage, something like this :
class StageManager
{
public Stage curStage;
public initStage(Stage stage)
{
//init stage here
curStage = stage;
stage.init();
}
public clearStage()
{
//do some clearing staff
curStage .clear();
}
}
abstract class Stage
{
public abstract init();
public abstract clear();
}
abstract class FirstStage extends Stage
{
//....
}
abstract class SecondStage extends Stage
{
//....
}
In Activity :
StageManager stageManager = new StageManager();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.your_view);
stageManager.init(new FirstStage());
}
#Override
public void onClick(View theView)
{
int id = theView.getId();
if (id == R.id.btnNextLevel) {
stageManager.clear();
stageManager.init(new SecondStage());
}
}
Instead of your custom manager, you can use fragmets :
http://developer.android.com/training/basics/fragments/creating.html
http://developer.android.com/training/basics/fragments/fragment-ui.html
In both ways - fragments or yout own manager you will seperate different stages logic to different classes.
Youd don't need to create another Activity to seperate yours 1000+ lines code. Just use one of Stage or Stratagy desing patters.
And if you still want to use Activities just do something like this :
Intent myIntent = new Intent(getBaseContext(), Level3.class);
startActivity(myIntent);
finish();
and in onDestroy() :
#Override
protected void onDestroy()
{
//here you must clear all data that were used in this Stage (Activity) like this :
clearMemmory();
super.onDestroy();
}
private void clearMemmory()
{
if(stageData!=null)
{
stageData.clear();
stageData =null;
}
}
or clear memmory directly before opening another Stage, something like :
clearMemmory();
Intent myIntent = new Intent(getBaseContext(), Level3.class);
startActivity(myIntent);
finish();
Best wishes.
Good evening Stack !
I have started to learn Android development as a hobby and I am now trying to develop my first "real" application (I have made already only five simple applications from books).
In this application, I have two buttons that will "create" the same Activity but by using two different objects from the same base class, hence allowing me to customize the behavior of the application depending on the button that was clicked.
However, when I am trying to create the Intent instance, my application crashes.
Here is the code of the base Activity class
public class BaseDictionnaryActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.basedictionnary);
}
public void onDestroy()
{
super.onDestroy();
}
}
and here is the code that crashes. The line is the one creating the Intent object.
public class DictionnaryActivity extends Activity
{
private BaseDictionnaryActivity jlpt1;
private BaseDictionnaryActivity jlpt2;
private Button btjlpt1 = null;
private Button btjlpt2 = null;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.dictionnary);
jlpt2 = new BaseDictionnaryActivity();
jlpt1 = new BaseDictionnaryActivity();
btJLPT1 = (Button)findViewById(R.id.jlpt1);
btJLPT1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent myIntent = new Intent(DictionnaryActivity.this,
jlpt1.getClass());
jlpt1.this.startActivity(myIntent);
}
});
btJLPT2 = (Button)findViewById(R.id.jlpt2);
btJLPT2.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
Intent myIntent = new Intent(DictionnaryActivity.this,
jlpt2.getClass());
jlpt2.this.startActivity(myIntent);
}
});
}
public void onDestroy()
{
super.onDestroy();
}
}
Thank you for your help !
Just to make correction,
Intent myIntent = new Intent(DictionnaryActivity.this,
jlpt1.getClass());
In this the second argument must be, your target activity BaseDictionnaryActivity.class
So, it looks something like,
Intent myIntent = new Intent(DictionnaryActivity.this,
BaseDictionnaryActivity.class);
startActivity(myIntent);
Also please make sure there will be entry of BaseDictionnaryActivity in your Application's manifest file,
Which is look like,
<activity android:name=".BaseDictionnaryActivity"
....>
</activity>
Maybe:
Intent myIntent = new Intent(DictionnaryActivity.this,
BaseDictionnaryActivity.class);
startActivity(myIntent);
change this
Intent myIntent = new Intent(DictionnaryActivity.this,
NextActivity.class);
Intent myIntent = new Intent(DictionnaryActivity.this,
jlpt2.class);
^^^^^^^^^^^^
You need to provide next activity .class in second argument of Intent.
Replace jlpt1.getClass() with NameOfClassToBeLaunched.class
Also this is bad practice to create Activity instances in other activities.