How to correctly call a method between activities? - android

In the ActivityA.java, I have tryAgain() method that calls the goToGame() method from ActivityB.java.
ActivityA.java
public void tryAgain(View view) {
ActivityB activityB = new ActivityB();
activityB.goToGame(view);
}
I get the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
because in ActivityB.goToGame() there is the following string:
Intent intent = new Intent(getApplicationContext(), GameActivity.class);
I think that the error is due to a wrong argument of activityB.goToGame() or to getApplicationContext() of the intent.
In similar questions, the solution suggested is to use static but I face a lot of other issues with this solution.
EDIT
Consider that:
I cannot make goToGame() as static
I cannot change the argument goToGame() that as to remain View
I cannot make goToGame() return anything

to call a method from your ActivityB with the right way, you can do something like this
add this your ActivityB
public static Intent goToGame(Context context) {
//here do the things you want to
return new Intent(context, GameActivity.class);
}
Wherever you want to open GameActivity over ActivityB, use this
startActivity(ActivityB.goToGame(this));
so this style is not right
ActivityB activityB = new ActivityB();
activityB.goToGame(view);
do it like this
public void tryAgain(View view) {
startActivity(ActivityB.goToGame(this));
}
hope it helps!

Related

why am i getting error when trying to open new activity in android studio

I'm getting this error when I write the intent inside the onCreate method.
But when I write the intent inside an outer method and call it, it works.
Button click listener is an interface and you implemented it here as an anonymous class, so inside of that class this refers to that anonymous class, not your activity class, but Intent constructor needs activity class implementation, therefore as #ADITYA RANADE answered you need to change it to MainActivity.this.
However if you replace anonymous class with lambda you can avoid this:
Button button = new Button(context);
button.setOnClickListener(v -> {
Intent intent = new Intent(this, MainActivity.class);
});
Change it to MainActivity.this inside the intent
Well that is because of the place or more precisely "context" (not the androidish Context) of where you are calling it.
When you call it from the anonymously created inner class which implements the listener for a view click, so in this case the this represents something else - anonymous class.
But on the other side when you make the method e.g. openScheduleActivity() inside the activity itself, the this keyword represents the activity itself and in fact represents the androidish Context or in this particular case even the activity. So you can either stay with case that you have already had there and slightly edit it, or you can use lambda expression, or you can use the method inside the activity itself as you have already discovered.
edited case:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, schedule.class);
startActivity(intent);
}
});
lambda expression:
button.setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, schedule.class);
startActivity(intent);
});

Why does getPackageManager return null

So I am trying to start another app my inside my AccessibilityService but I keep getting the following java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.PackageManager android.content.Context.getPackageManager()' on a null object reference even though I use the same method in my MainActivity.class and it works fine. And I know the package name is correct, cause like I said I call it in MainActivity.class
This is the class where I call the function.
public class myAdapter extends Application
{
private void turnOn(String text)
{
Intent b = getPackageManager().getLaunchIntentForPackage(text);
startActivity(b);
}
}
I have tried the various ways to call this same function.
Intent b = getApplicationContext().getgetPackageManager().getLaunchIntentForPackage(appName);
getApplicationContext().startActivity(b);
Intent b = getApplicationContext().getgetPackageManager().getLaunchIntentForPackage(appName);
getApplicationContext().startActivity(b);
My Logcat:
Process: com.tech.myApp, PID: 17195
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:106)
at com.tech.myApp.turnOn(myAdapter.java:198)
You say that you're trying to start an Activity from an AccessibilityService, yet your code very clearly shows that your class is extending Application. This is confusing and also likely one of the core issues you're having regarding these NullPointerExceptions. I am going to state my answer assuming that you are indeed attempting this from an AccessibilityService class, as mentioned in the description of your issue, even though this very much conflicts with the code you have posted. If this is indeed the case, you should update this question to clarify. If this answer does not help you, your question needs considerable TLC.
Once we realize that we're within an AccessibilityService, we see that there is a MUCH simpler way to accomplish starting an activity. Starting another Activity within an AccessibilityService is as simple as the following code snippet:
public class A11yService extends AccessibilityService {
void startMainActivityFromService() {
final Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
Easy as that!
Okay so what I had to do was on my MainActivity.class was create a static context. Which then I could pull from any other class even the ones that run in the background.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivity.context = getApplicationContext();
// CALL MY FUCTION - THIS COULD BE ANYWHERE NOW
startApp(app name you want to start);
}
}
Then in my other classes or activities or services I use this:
public static void startApp(String appName)
{
// MAKE SURE TO GET THE CONTEXT
Context context = MainActivity.getAppContext();
Intent b = context.getPackageManager().getLaunchIntentForPackage(appName);
context.startActivity(b);
}

Passing a reference of an object to activity

I have a reference to an anonymous class object that I want to pass to an activity. It is a kind of reference to a callback fn which gets called based on an action on activity i.e. click of button. But, I dont know a way to do so as activities can not be instantiated directly (done only through startActivity) and using intents will pass my object by value not by reference. So, I need tips on a good solution. I want to avoid statics.
Short Answer: No You cannot pass objects as references to activities.
Try this
CustomListing currentListing = new CustomListing();
Intent i = new Intent();
Bundle b = new Bundle();
b.putParcelable(Constants.CUSTOM_LISTING, currentListing);
i.putExtras(b);
i.setClass(this, SearchDetailsActivity.class);
startActivity(i);
Afterwards to call
Bundle b = this.getIntent().getExtras();
if (b != null)
mCurrentListing = b.getParcelable(Constants.CUSTOM_LISTING);
Here is the answer :
Create a public static method in the Activity to which you want to pass the reference of an object.
public static void openActivity(Activity activity, Class object){
YourNextActivity.object = object;
Intent intent = new Intent(activity, YourNextActivity.class);
activity.startActivity(intent);
}
Call this method from current Activity :
YourNextActivity.openActivity(this, classObject);

Get Activity after startActivity(Intent i)

In one method i start a new activity
public void start(){
Intent i = new Intent(mContext, Screen.class);
mContext.startActivity(i);
//Here i want to get the new activity
Activity a = ...
//Do something with new activity
}
After calling starActivity() i need to get that new Activity and doing something with it.
Is it possible??
EDIT:
Well i have these methods on my Screen class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadedScreen = false;
}
public void loadScreen(String folderResources, String nameXml, String nameScren){
//Do something
}
loadScreen read an XML file and create by code all user interface, instead of doing in onCreate
In another class I call foo():
public void goToScreen(String nameScreen){
Class screen = Screen.class;
Intent i = new Intent(mContext, screen);
mContext.startActivity(i);
//Here in screen.getMethod... i need use a instance of Screen, which i think it have to be created in `startActivity()`
Method loadUrl = screen.getMethod("loadScreen", String.class, String.class, String.class);
loadUrl.invoke(screen, "folder-s","screen1","screen1.xml");
}
I need call to loadScreen after startActivitybecause this method load all views. I use reflection for doing this. So i need get that new Activity
After calling starActivity() i need to get that new Activity and doing something with it.
Once you call startActivity(), the other activity does not yet exist -- it will not exist for some time.
I need call to loadScreen after startActivitybecause this method load all views.
Call loadScreen() from onCreate() of the Screen activity.
If you wish to pass the values of folderResources, nameXml, and nameScren to Screen, do so by calling putExtra() on the Intent you use with startActivity(). Then, Screen can call getIntent().getStringExtra() in onCreate() to retrieve those values, in order to pass them to loadScreen().

how to know the calling activity in android

I have an activity which is called by few other activities. For example: I have Activity1,Activity2,Activity3.
Activity1 calls Activity2 and pass parameter.
Activity3 also calls Activity2 and pass parameter.
Now based on the calling activity, Activity2 performs some task.
But how do I know which activity is calling Activity2??
can anybody plz help me??
If you start the activity with startActivityForResult(Intent, int), then you can get calling activity by getCallingActivity().getClassName().
A. If you can use startActivityForResult
As per Zain Ali's answer below: If you can start Activity with startActivityForResult() then you can get name of calling Activity class by this.getCallingActivity().getClassName();
B. If you can not use startActivityForResult
If you can not use startActivityForResult(), then you can use following method:
You can pass additional parameter in intent, check the value in activity and act accordingly.
1) Define an interface or constants class to define integer constants to indicate calling activity
public interface ActivityConstants {
public static final int ACTIVITY_1 = 1001;
public static final int ACTIVITY_2 = 1002;
public static final int ACTIVITY_3 = 1003;
}
2) Add extra parameter in intent while calling Activity2.
Intent act2 = new Intent(context, Activity2.class);
act2.putExtra("calling-activity", ActivityConstants.ACTIVITY_1);
// or ActivityConstants.ACTIVITY_3 if called form Activity3
startActivity(act2);
3) Check the value of this extra parameter in Activity2 and act accordingly..
int callingActivity = getIntent().getIntExtra("calling-activity", 0);
switch (callingActivity) {
case ActivityConstants.ACTIVITY_1:
// Activity2 is started from Activity1
break;
case ActivityConstants.ACTIVITY_3:
// Activity2 is started from Activity3
break;
}
In your calling activity (FirstActivity):
Intent i = new Intent(FirstActivity.this, SecondActivity.class);
i.putExtra("classFrom", FirstActivity.class.toString());
startActivity(i);
And add the following code in the onCreate of the called activity (SecondActivity):
Bundle bundle = getIntent().getExtras();
if (bundle.getString("classFrom").equals(FirstActivity.class.toString())) {
//Do some task
}
Notice that you should be carefully because the bundle object can't be null when you perform "b.getString("classFrom")".
You could pass an additional parameter that specifies the calling Activity.
I successfully use: (Activity).getLocalClassName()
Pass anything(String/ int etc.) to putExtra and base on that do the your work like
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("PARENT_ACTIVITY_REF", "ParentActivityIsA");
startActivity(intent);
And then receive in child like
String parentActivityRef = intent.getStringExtra("PARENT_ACTIVITY_REF");
then
if (parentActivityRef.equals("ParentActivityIsA"){
// do your work here
}else if ...{
// ...
}else{
//...
}
I'm Using This line
if (((((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1).get(0).baseActivity)).compareTo(new ComponentName(getPackageName()
, AnyActivityWantToCheck.class.getName())) == 0){
// do somthing .....
}
i hope it work with you
Another solution, using companion object as in the following example:
class MainActivity: BaseActivity {
...
LoginActivity.callerActivity = this
it.context.startActivity(Intent(getActivity(), LoginActivity::class.java))
...
}
class LoginActivity : BaseActivity() {
companion object {
var callerActivity: AppCompatActivity? = null
}
...
callerActivity?.let {
it.callSomething()
}
}

Categories

Resources