When trying to edit a custom arraylist from another Activity the application force closed.
Arraylist in MainActivity:
ArrayList<Contacts> contacts = new ArrayList<Contacts>();
Another Activity:
MainActivity main = new MainActivity();
main.contacts.get(position).contactname=x;
main.contacts.get(position).contactnumber=x;
How can I edit an arraylist from another activity?
Logcat:
09-08 22:53:40.415 1760-1760/com.example.amir_p.contacts E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.amir_p.contacts, PID: 1760
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2, result=-1, data=Intent { (has extras) }} to activity {com.example.amir_p.contacts/com.example.amir_p.contacts.ContactInfo}: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at android.app.ActivityThread.deliverResults(ActivityThread.java:3577)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3620)
at android.app.ActivityThread.access$1300(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.example.amir_p.contacts.ContactInfo.onActivityResult(ContactInfo.java:53)
at android.app.Activity.dispatchActivityResult(Activity.java:6192)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3573)
Two issues:
1
You can't instantiate an activity:
new MainActivity();
Activities must be launched from an Intent like so:
thisActivity.startActivity( new Intent( NextActivity.class ) );
2
If you want two activities to share a list, then you must instantiate that list in a greater scope, like the Application scope by creating a custom application class or creating a singleton.
Singleton:
public final class MySingleton {
private static final MySingleton SELF = new MySingleton();
private List<Contacts> contacts = new ArrayList<Contacts>();
private boolean didContacts
private MySingleton() {
// Don't want anyone else constructing the singleton.
}
public static MySingleton getInstance() {
return SELF;
}
public List<Contacts> getContacts() {
return contacts;
}
}
Now in any activity you like you may get the list
MySingleton.getInstance().getContacts()
Just be careful of concurrent modification.
Amendment due to a request in comments
It was stated in the comments that you want to change one activity from another. You must realize only one activity is active at a time and so you SHOULD NOT do that, regardless of whether or not you could hack it. I would normally recommend a listener but a listener wont work in this case since only one Activity Another way to do this would be to have some in-memory state that lives outside the activity (maybe the singleton) that the activities can respond to when they regain focus.
Pseudo code
ActivityB {
onClick() {
MySingleton.getInstance().getContacts().add( theContact );
}
}
ActivityA {
onResume() {
// consider contacts may have changed and redraw
listViewAdapter.clear();
listViewAdapter.addAll( MySingleton.getInstance().getContacts() );
}
}
Related
When using Hilt with Espresso I found that my activity is either not resumed or not destroyed. When I comment out the very first test that launches my activity the second one started to pass. The workaround is to separate each test however this will produce a lot of boiler plate code.
Also I have a custom activity inside the tests that inherits from my main activity.
#RunWith(AndroidJUnit4.class)
#HiltAndroidTest
public class MainActivityTest {
// ... initilisation & mocks
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
hiltAndroidRule.inject();
context = getInstrumentation().getTargetContext();
// ... other initialisation and setup
}
// Helper classes and functions
#AndroidEntryPoint
public class ModifiedMainActivity extends MainActivity {
// ... custom activity implementations
}
// Factory
private SingleActivityFactory<MainActivity> activityFactory = new SingleActivityFactory<MainActivity>(MainActivity.class) {
#Override
protected MainActivity create(Intent intent) {
ModifiedMainActivity mainActivity = new ModifiedMainActivity();
// other custom activity configuration & setup
return mainActivity;
}
}
#After
public void tearDown() {
// ... other code to tear down some stubs
}
}
Any ideas?
I can provide some code but other is under NDA.
My rules:
#Rule(order = 0)
public HiltAndroidRule hiltAndroidRule = new HiltAndroidRule(this);
#Rule(order = 1)
public ActivityTestRule<MainActivity> mainActivityRule = new ActivityTestRule<>(activityFactory, true, false);
Test example:
#Test
public void test_report_system_back_button_pressed_when_closing_main_activity() {
Intent intent = new Intent(Intent.ACTION_MAIN);
final MainActivity mainActivity = mainActivityRule.launchActivity(intent);
getInstrumentation().runOnMainSync(mainActivity::onBackPressed);
verify(mockedHelper, times(1)).reportEvent(eq(Codes.SYSTEM_BACK_PRESSED), eq("SystemBackPressed"), nullable(Map.class));
}
Exception:
java.lang.RuntimeException: No activities found. Did you forget to launch the activity by calling getActivity() or startActivitySync or similar?
at androidx.test.espresso.base.RootViewPicker.waitForAtLeastOneActivityToBeResumed(RootViewPicker.java:176)
at androidx.test.espresso.base.RootViewPicker.get(RootViewPicker.java:88)
at androidx.test.espresso.ViewInteractionModule.provideRootView(ViewInteractionModule.java:77)
at androidx.test.espresso.ViewInteractionModule_ProvideRootViewFactory.provideRootView(ViewInteractionModule_ProvideRootViewFactory.java:37)
at androidx.test.espresso.ViewInteractionModule_ProvideRootViewFactory.get(ViewInteractionModule_ProvideRootViewFactory.java:27)
at androidx.test.espresso.ViewInteractionModule_ProvideRootViewFactory.get(ViewInteractionModule_ProvideRootViewFactory.java:10)
at androidx.test.espresso.base.ViewFinderImpl.getView(ViewFinderImpl.java:63)
at androidx.test.espresso.ViewInteraction$2.call(ViewInteraction.java:280)
at androidx.test.espresso.ViewInteraction$2.call(ViewInteraction.java:272)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
I'm trying to use openFileOutput method in a non-activity class. When I try use a context, from the MainActivity (this), the program crash.
Some form to use that method in my class ?
private Context context;
public Events(Context context) {
this.context = context;
}
public void setEvent(int year, int month, int dayNumber, int hour, int minutes, String event, String eventParameters) {
try {
OutputStreamWriter events = new OutputStreamWriter(context.openFileOutput("events.txt", Context.MODE_PRIVATE));
} catch(IOException e) {
e.printStackTrace();
} // End of try
} // End of method - setEvent
I have a personalized dialog, it is used to call the setEvent method.
public CellOptions(final Dialog dialog) {
final Events event = new Events(dialog.getContext());
final TextView newEvent = (TextView) dialog.findViewById(R.id.newEvent), eventView = (TextView) dialog.findViewById(R.id.eventView);
newEvent.setOnClickListener(new View.OnClickListener() {
public void onClick(View option) {
event.setEvent(2018, 0, 1, 0, 0, "New year", "Nothing");
eventView.setBackgroundColor(Color.rgb(0, 0, 8));
}
});
}
public boolean showed() {
return true;
}
Too, I have tried to use setEvent in MainActivity class from the next form.
Events event = new Events(this, the next parameters);
But it doesn't work.
I have searched answers about this problem, but I can't find a solution that helps me.
I found this pages, but the same problem continue.
how to call method in activity form non activity class
Getting activity from context in android
using openFileOutput() in a class. (not an activity)
http://www.sgoliver.net/blog/ficheros-en-android-i-memoria-interna/
When I run my program, it crash when it use the context.
Logcat shows this:
01-03 15:55:25.932: W/Binder(632): Caught a RuntimeException from the binder stub implementation.
01-03 15:55:25.932: W/Binder(632): java.lang.NullPointerException
01-03 15:55:25.932: W/Binder(632): at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
01-03 15:55:25.932: W/Binder(632): at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
01-03 15:55:25.932: W/Binder(632): at android.os.Binder.execTransact(Binder.java:404)
01-03 15:55:25.932: W/Binder(632): at dalvik.system.NativeStart.run(Native Method)
01-03 15:55:25.932: W/InputMethodManagerService(487): Got RemoteException sending setActive(false) notification to pid 2744 uid 10036
01-03 15:55:26.572: I/ActivityManager(487): Displayed com.android.dropcalendary/.MainActivity: +4s402ms
Using activity method in non-activity class? Short story is, You cannot
But there certainly is a way for that, you can pass in your activity (which usually is not a good idea, if your activity is destroyed it can caused null pointer or memory leak).
One other way is if you need the context, you can use ApplicationContext for that.
Use ApplicationContext instead of context. Since the lifecycle of this Context is preserved until the app is destroyed or finished.
So Context is preserved only until the activity is destroyed.
getApplicationContext();
I've achieved solve the problem.
The method works in a activity, to use the method in a non-activity class, I did use:
getApplicationContext();
I did use it, sending the context since MainActivity, through of CellOptions class, and in CellOptions class I did send the same context.
MainActivity:
new CellOptions(cellOptions, getApplicationContext());
CellOptions class (context = application context):
Events event = new Events(context);
Events class:
context.openFileOutput(events.txt);
Other problem was that I used "/", and instead I used "\\"
I'm loading a picture from a url into a bitmap. This code below worked on previous classes that extended Fragment. This time, I'm just copying the code and trying to use it in a class that extends AppCompatActivity. The only difference is how I'm getting context.
public void loadBitmap(String url) {
if (loadtarget == null) loadtarget = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
handleLoadedBitmap(bitmap);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
mContext = MyActivity.this;
Picasso.with(mContext).load(url).into(loadtarget); //giving me null
}
In the original code, where I used it in a Fragment, I had it as
Picasso.with(getActivity()).load(url).into(loadtarget);
So now, since this class extends AppCompatActivity, I thought I could use "this" or MyActivity.this but that didn't work. I've tried initializing a Context variable "mContext" in onCreate and right before I load the image into the bitmap (like above) but neither worked. I've tried this.getApplicationContext() and I've also tried to pass mContext as a parameter in the loadBitmap() method but that didn't work either.
My URL string is correct. I'm just not sure how to tackle this problem after trying, what seems like, everything.
Last piece of information, the exception:
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:112)
at com.salty.seas.Driver.MyActivity.loadBitmap(MyActivity.java:144)
at com.salty.seas.Driver.MyActivity$1.onKeyEntered(MyActivity.java:61)
at com.firebase.geofire.GeoQuery$2.run(GeoQuery.java:126)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
In the comments to the question you said that the activity, the loadBitmap() belongs to, you actually instantiate yourself (in some other fragment) and use it as an utility class.
You should never create activites manually as they are managed by android and they have a lifecycle android maintains.
In your case the activity is not in a correct state (one of its internal fields is null), that's why you get NPE.
For utility methods create utility classes and call those from wherever you want.
I'm having some strange errors reports on Google Play Developer Console regarding NPEs on Activity context or Application context. I can't recreate this error on my device and I know it's working fine on most devices.
This is my Main Activity, the one that is first opened on app startup:
public class ActSplash extends Activity {
private Sync sync;
private Context ctx;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_splash);
do {
ctx = this.getApplicationContext(); //Using just "this" doesn't work either.
} while (ctx==null);
sync = Sync.getInstance(ctx); //Apparently ctx is null at this point in some devices
}
This is my Sync class (Singleton)
public class Sync {
private Context ctx;
private static Sync INSTANCE = null;
public static Sync getInstance(Context ctx) {
if (INSTANCE == null) createInstance(ctx);
return INSTANCE;
}
private synchronized static void createInstance(Context ctx) {
if (INSTANCE == null) {
INSTANCE = new Sync(ctx);
}
}
private Sync(Context _ctx)
{
ctx = _ctx;
//NPE on following line
WifiManager wifiMan = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE);
...
}
This is the stack trace:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.xxx.xxx/com.xxx.xxx.ActSplash}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2140)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2178)
at android.app.ActivityThread.access$700(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1271)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5118)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.xxx.xxx.Sync.<init>(SourceFile:82)
at com.xxx.xxx.Sync.void createInstance(android.content.Context)(SourceFile:67)
at com.xxx.xxx.Sync.com.xxx.xxx.Sync getInstance(android.content.Context)(SourceFile:72)
at com.xxx.xxx.ActSplash.void onCreate(android.os.Bundle)(SourceFile:40)
at android.app.Activity.performCreate(Activity.java:5058)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2104)
... 11 more
What can I do to make sure I have ctx!=null before calling:
sync = Util_Sync.getInstance(ctx);
so as you have code that does not change
do {
ctx = this.getApplicationContext(); //Using just "this" doesn't work either.
} while (ctx==null);
this is going to result in an endless loop, if it fails to get ctx.
Activity is a context! See http://developer.android.com/reference/android/content/Context.html
Known Indirect Subclasses
AbstractInputMethodService, AccessibilityService, AccountAuthenticatorActivity, ActionBarActivity, Activity, ActivityGroup, AliasActivity, Application, BackupAgent, BackupAgentHelper, ContextThemeWrapper, and 23 others.
Try
ctx = this;
Update
Further to your Sync code being posted
private Context ctx;
is never used, so remove it.
Note that this can never be null. Assume to the contrary that it can be, then this means you would have a call such as myObj.myMethod() where myObj is null. But then this method call would throw a NPE before execution enters myMethod().
This means that your error is coming from somewhere else.
Would you mind posting the full constructor ? null pointer exception occurs somewhere inside of Sync() constructor. _ctx is not null though
I managed to get my headset buttons get recognized by my app when pressed, but one of the buttons needs to call a method that's in MyCustomActivity. The problem is onReceive's 1st parameter is a Context that cannot be cast to Activity and using a MyCustomActivity's inner class won't work in Android 4.1 unless it is static (which has the same problem of inability to access MyCustomActivity's method.
So the only option left for me (in order to support both 2.x and 4.1) is to pass the activity as a parameter to RemoteControlReceiver.
But how do I do that, when the only way to instantiate it is via:
private ComponentName mRemoteControlReceiver = new ComponentName(this, RemoteControlReceiver.class);
Which doesn't accept any additional parameters?
Any idea how to work around this limitation?
Note: If I try to define RemoteControlReceiver as having a constructor with a parameter, I receive the following exception:
E/AndroidRuntime(2836): java.lang.RuntimeException: Unable to instantiate receiver com.example.RemoteControlReceiver: java.lang.InstantiationException: can't instantiate class com.example.RemoteControlReceiver; no empty constructor
Caused by:
E/AndroidRuntime(2836): Caused by: java.lang.InstantiationException: can't instantiate class com.example.RemoteControlReceiver; no empty constructor
E/AndroidRuntime(2836): at java.lang.Class.newInstanceImpl(Native Method)
E/AndroidRuntime(2836): at java.lang.Class.newInstance(Class.java:1319)
E/AndroidRuntime(2836): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2205)
So it is clear that this new registerMediaButtonEventReceiver requirement (introduced in Android 4.1) expects an empty constructor.
Is there no way to work around this?
For example, is there a way to get a reference to the actual RemoteControlReceiver object (instantiated indirectly via mAudioManager.registerMediaButtonEventReceiver())? So that I can use an accessor to set a data-member of RemoteControlReceiver after it has been instantiated?
registerMediaButtonEventReceiver requires the BroadcastReceiver to be declared in the application manifest. This means that the receiver must be a standalone class, meaning it knows nothing about your current activity or service.
In order to get this message to your activity or service, you have a number of options:
Use a static global for the activity or service so the receiver can forward the message to it. This is generally not a good idea as it leads to leaks and isn't very adaptable when you want to change the code later. Statics are generally to be avoided.
Re-broadcast the message to a specific class, which happens to be an inner class of the activity or service you want to invoke. E.g. in the BroadcastReceiver for registerMediaButtonEventReceiver:
// Standalone class, declared in the manifest
public class ButtonReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Intent intent = new Intent();
intent.setAction("com.foo.ACTION");
// Rebroadcasts to your own receiver.
// This receiver is not exported; it'll only be received if the receiver is currently registered.
context.sendBroadcast(intent);
}
}
And in your activity:
class MyActivity extends Activity {
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
MyActivity.this.onMessageReceived();
}
}
#Override
protected void onResume() {
registerReceiver(myReceiver, new IntentFilter("com.foo.ACTION"));
}
#Override
protected void onPause() {
unregisterReceiver(myReceiver);
}
private void onMessageReceived() {
}
}
Similar to the above method, it doesn't necessarily have to be a broadcast, it could be an Intent passed to the activity, depending on your use case. To do this instead of using sendBroadcast, you'd use startActivity (or startService if you're using a service).