I am very new with android development. My app has a lot of views/Activity and user can jump from one view to another depending his/hers inputs. so i thought of creating an interface IView which will have a function
void openNewView(Class viewClass);
and the function in the view class would look something like this
public void openNewView(Class viewClass)
{
Intent intent = new Intent(this, viewClass.class);
startActivity(intent);
}
The whole idea is that my controller can listen for user inputs and then call openNewView as per the requirement.
The issue that i am facing is with java not accepting a parameter of type Class
What is it that i am doing wrong here. is there a work around what i am trying to achieve.
One good approach would be extend all your activities from an abstract Activity like this:
public abstract class BaseActivity {
//....
public void openNewView(Class viewClass) {
Intent intent = new Intent(this, viewClass.class);
startActivity(intent);
}
}
Doing this way you don't have to copy your code in every activities and keep code clean.
try by adding current Context param in openNewView method as:
void openNewView(Class viewClass,context);
and in your function :
public void openNewView(Class viewClass,Context context)
{
Intent intent = new Intent(context, viewClass.class);
context.startActivity(intent);
}
Related
This question already has answers here:
How do I pass data between Activities in Android application?
(53 answers)
How to pass an object from one activity to another on Android
(35 answers)
Closed 4 years ago.
I am currently working on a project for my programming class, it is a d&d character creator I've decided to do for my final project. I am nearly finished with it but have run into one problem. I want to take the user's data from a screen where they create a character and store it into a screen where they can view their created characters, but I am not sure how to do this. This is the code from the create a character screen:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_char_screen);
Button btnSave = (Button)findViewById(R.id.btnSaveChar);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (checkData())
startActivity(new Intent(NewCharScreen.this, HomeScreen.class));
}
});
Button btnEx = (Button)findViewById(R.id.btnExplanation);
btnEx.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(NewCharScreen.this, ExplanationScreen.class));
}
});
}
private boolean checkData(){
final EditText charName = (EditText) findViewById(R.id.txtNameInput);
if (charName.getText().toString().isEmpty()){
charName.setError("Enter character name");
charName.requestFocus();
return false;
}
return true;
}
}
If there is a need for the rest of my code or the project itself here is a link to a repository on GitHub:
https://github.com/cbetlinski98/MAD105-final_project
If you want to pass data from one activity to another one, you should pass it inside the Intent object, so intead of creating it inside StartActivity you can create it outside as a normal object, and use putExtra() to put data inside it.
Intent intent = new Intent(getBaseContext(), DestinationActivity.class);
intent.putExtra("OBJECT_PARAM_NAME", your_object);
startActivity(intent);
To recover data on the other activity you can use
String sessionId= getIntent().getStringExtra("OBJECT_PARAM_NAME");
Pass basic types
If you need to pass basic objects like int, float, strings, you can always pass them with putExtra() but to take them in the destination activity there are relative methods like getStringExtra() or getIntExtra() and many others.
Pass your class
If your user is a class defined by you, you can implement Serializable in that class, put it inside the intent with putExtra() and recover it from the other activity with getIntent().getSerializableExtra("OBJECT_PARAM_NAME") and then just cast it to your class before putting it inside an object
In order to pass information across intents:
Intent i = new Intent(this, Character.class);
myIntent.putExtra("paramKey","paramValue1");
startActivity(i);
Then in your activity to obtain the parameters:
Intent i2 = getIntent();
i2.getStringExtra("paramKey");
startActivity(new Intent(CurrentActivity.this, AnotherActivity.class).putExtra(KEY, DATA));
Please i will like to have a method/function in a separate class
that will enable me to go to next activity or fragment class when i call it
here is my little try of code
inside my go_to.class i have this below
for activity
void goToActivity(Activity t){
startActivity(new Intent(this, t.class));
}
void goToFragment(Fragment f,package.com.R l){
getSupportFragmentManager().beginTransaction().add(l,new f).commit();
}
and to use example
goToActivity(mynextactivity.class);
goToFragment(mynextfragment.class,R.id.fragment_layout);
Any help is welcome
From non activity class you can create a function it like this:
public static void goToHomeActivity(Context context)
{
Intent i = new Intent(context, ActivityDashboard.class);
context.startActivity(i);
}
Then call it like this MyUtils.goToHomeActivity(context);
Alternatively, from activity class like this:
private void goToHomeActivity()
{
Intent i = new Intent(getBaseContext(), ActivityDashboard.class);
context.startActivity(i);
}`
Then call it like this goToHomeActivity();
I later solve it this way after many trial:
What i am trying to achive is to have a function to call new activity class and fragment when a button is clicked on at runtime
void goToActivity(Class t){
startActivity(new Intent(this, t));
}
my where i have been getting the fragment concept wrong is fragment is not indepent activity class, so to overcome fragment need anactivity parent or root layout to hold the fragment layout that is you can never start fragment instance alone like activity which is very big issure for begginers to understand
void goToFragment(Fragment f){
fragmentTransaction.replace(R.id.your_layout, f);
fragmentTransaction.addToBackStack(null);
}
or if you cannot determine your xml layout you can write it like this:
void goToFragment(int l,Fragment f){
fragmentTransaction.replace(l, f);
fragmentTransaction.addToBackStack(null);
}
Thank you all for your help
I am implementing a login system. The user needs to be redirected to the login activity from any previous activity if the token is no longer valid. I can go to the login activity with this
new Intent(CurrentActivity.this, NextActivity.class);
But this needs the current activity. I just want to go to the login activity no matter where I am. I cannot know where I am because this is inside an entirely different package.
you should probably register in the Application class to ActivityLifecycleCallbacks and if the user is not registered send them to the correct Activity.
just be sure to not endlessly send them from the login page to itself
EDIT:
adding some code and explanation.
In order to figure out if an Activity that shouldn't be alive is going through lifecycle events you'll need to implement some sort of a gate keeper. Previously it used to be some sort of static state that is kept in the Application class and holds the current activity and sometime even the stack of current activities.
This was far from a complete solution and had issues due to different tasks and even isolated procesies.
In API 14 Android introduced the Activity lifecycle callbacks which can be passed into the method registerActivityLifecycleCallbacks int the Application class.
What you want to do basically is the following:
class ThepooshApplication extends Application {
private static sIsRegistered = false;
public static setIsRegistered(boolean isRegistered) { sIsRegistered = isRegistered; }
public void onCreate() {
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks(){
#Override
void onActivityCreated(Activity activity, Bundle savedInstanceState){
if (!sIsRegistered && !(activity instanceof LoginActivity)) {
Intent loginIntent = new Intent(this, LoginActivity.class);
loginIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(loginIntent);
}
}
#Override
void onActivityStarted(Activity activity) { /*empty method*/ }
#Override
void onActivityResumed(Activity activity) { /*empty method*/ }
#Override
void onActivityPaused(Activity activity) { /*empty method*/ }
#Override
void onActivityStopped(Activity activity) { /*empty method*/ }
#Override
void onActivitySaveInstanceState(Activity activity, Bundle outState) { /*empty method*/ }
#Override
void onActivityDestroyed(Activity activity) { /*empty method*/ }
});
}
}
You must add FLAG_ACTIVITY_NEW_TASK flag to your intent
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Try some like this
Intent i = new Intent();
i.setClass(this,TestActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
Replace TestActivity.class for your target activity
Usually you would start an activity with something like the following:
private void llMenuSettings_Click() {
this.runOnUiThread(new Runnable() {
public void run() {
Intent intent = new Intent(XXXXXXXX.this, View_Settings.class);
startActivity(intent);
XXXXXXXX.this.finish();
}
});
}
However I am extending a LinearLayout:
public class MenuContainer extends LinearLayout {
}
Therefore I have run into a couple of issues:
How would you know what XXXXXXXX is in the example as the LinearLayout can be included in multiple Layouts?
startActivity() does not exist in a LinearLayout class?
There are a few similar questions but none that fully answer the above scenario therefore hoping this can be answered and help others in the future?
Inside your LinearLayout extending class, you could create the following method:
public void launch() {
Intent i = new Intent(getContext(), YourActivity.class);
getContext().startActivity(i);
}
Use the getContext() method inside your customview to retrieve the Context and start a new Activity.
I'm trying to define a custom Java class (extending a LinearLayout), which needs to start an activity on click. My code looks like this :
public ArizaSatiri(Context context/*, AttributeSet attrs , final Activity aktivite*/ , JSONObject mysql_satiri)
{
super(context/*, attrs*/);
// code to initialize my view :
final Context finalContext = context;
this.setOnClickListener(new OnClickListener() {#Override
public void onClick(View v) {
Intent newIntent = new Intent(finalContext, ArizaDetaylari.class);
finalContext.startActivity(newIntent);
}//onClick
});
}
But when I clicked on the instantiated view, I get the error :
Calling startActivity() from outside of an Activity context requires the
FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
As you can see from the code, I tried passing the Activity to the constructor, and that worked. But is that the correct way? Which way would you reccomend ?
Edit:
And I also need to call setTypeFace() at some point. Should I use context, or Activity for that ?
Try this:
this.setOnClickListener(new OnClickListener() {#Override
public void onClick(View v) {
Intent newIntent = new Intent(finalContext, ArizaDetaylari.class);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
finalContext.startActivity(newIntent);
}//onClick
});
You can put your code into onAttachedToWindow() of your custom view class.
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
final Context context = ArizaSatiri.this.getContext();
Intent intent = new Intent(context , ArizaDetaylari.class);
context.startActivity(intent);
}
});
}
This helps because this function is called after your view is added to the activity, the view has the reference of it. Constructor of views probably run before being added to the activity, thus the error.
This should also work if you declare your view in xml instead of creating it programmatically. (Not tested yet)
If take a look to the Context class reference you could see that Activity is an indirect subclass. So if you use an Activity as Context your code should work.
For example:
public ArizaSatiri(Context context, JSONObject mysql_satiri){ ...}
you can change the call to the ArizaSatiri constructor:
new ArizaSatiri(myActivity, mysql_satiri);
Hope it helps.
If context (finalContext) that you are using is referring to ApplicationContext then you need to use the flag. Just add the sentence newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); before finalContext.startActivity(newIntent);
Problem with this approach especially when you are starting something outside of your app for ex: mail client etc, is it will continue to be there in the recent apps stack even after the activity is completed, in case of mail client it continues to be there even after mail has been sent