Android custom Intent class - java

I want to send a complex object from one Activity to another, so this complex object cannot be serialize, because some fields in this object are system classes and natively non-serializable. That's why I want to create my custom class named "MyIntent" inherits from android.content.Intent, with this way, I can put any type of objects in my custom Intent. But, in the second activity, getIntent() method returns android.content.Intent instance, not MyIntent instance. I don't understand why, maybe i did not implement android.content.Intent class correctly.
public class MyIntent extends Intent
{
}
//starting activity
MyIntent intent = new MyIntent();
intent.setClass(context, SecondActivity.class);
context.startActivity(intent);
//inside of onCreate() of SecondActivity
Intent i = getIntent();
i instanceof MyIntent = false

startActivity() involves inter-process communication, even when the activity you are starting is in the same app and the same process. Android will ignore your subclass, because the OS process that handles startActivity() requests cannot use your subclass, as that is in your app, and the OS process is not your app. And, the IPC that delivers the request to start the activity back to your process will not know anything about your subclass.
Either:
Combine these into one activity (e.g., using two fragments), or
Use some sort of singleton data manager that both activities can work with

Related

Android communication between Activities without onActivityResult

In an App I am currently working on I am facing a problem regarding the communication between Activities.
Basicly I have a UI-Component, which is similar to a Combobox. However, the list of the possible values for this component has to be openend in a new Activity.
So when you clicked the component, a new Activity is opened, using startActivityForResult.
When you select the new value, it is put inside a Bundle and returned to the previous Activity. I then need to use the onActivityResult-method to get the selected value and set it to the component.
That means, that every Activity that uses this component needs to override onActivityResult and refresh the component with the new value.
What I want instead is, that the component takes care about all this stuff and you only have to register a Listener, just like you do it for a TextView and similar components.
But at the moment I just can't find a good way to do that, as the communication is tightly bound to the Activity and I just can't get the result of the Activity outside the onActivityResult.
Does anyone know a good solution for this problem?
Solution to this- use EventBus and post sticky event on it. By doing so you don't have to override onActivityResult.
The workflow will be as following:
- Create event object with your data
- Remove all sticky events of the same type from the Bus
- post new values by .sendSticky() method.
That event will be around until something remove it from the bus
- start another activity
- in this activity override method, subscribing to that event type, in it:
a) take and process event with your argument
b) remove it from the bus
- subscribe to the bus (second Activity) in onResume() method
- unsubscribe from the bus in .onPause() method
The point is, that this allow you to seamlessly handle lifecycle of second Activity, and you can subscribe/unsubscribe to the bus in base class
What about using BroadCastReceiver?
Basically you send a broadcast and every activity that is registered to receive that broadcast will receive that broadcast will receive the message in onReceive
First of all declare in the manifesto what you are going to listen for, something like:
<receiver android:name=".TestBroadCast”>
<intent-filter>
<action android:name="io.test.TEST"/>
</intent-filter>
</receiver>
Than simply extend BroadCastReceiver
public class TestBroadCastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//TODO: Handle the Intent received.
}
Example of how to send a broadcast:
public static final String INTENT_ACTION = "io.test.TEST";
public static final String INTENT_EXTRA = "someData";
Intent intent = new Intent();
intent.setAction(INTENT_ACTION);
intent.putExtra(INTENT_EXTRA,"test");
sendBroadcast(intent);
And you will get the Intent and than you can handle it as you wish :)!
UPDATE ~ Registering from code instead of manifesto
To avoid registering the service from the Manifesto you can do it from the code, with a code similar to the following listing:
IntentFilter intentFilter = new IntentFilter("io.test.TEST");
TestBroadCastReceiver mReceiver = new TestBroadCastReceiver();
context.registerReceiver(mReceiver, intentFilter);
P.S.
I suggest you using LocalBroadcastReceiver if you don't need other applications to be able to send results insted of the common BroadcastReceiver for security reasons
You can implement Observer Design Pattern, the better implementation of that are BroadcastReceiver and a Library which implement event bus design Otto
Hello #Alex Shutov was right Try this
https://github.com/greenrobot/EventBus
http://greenrobot.org/eventbus/
Use EventBus here is the link https://github.com/greenrobot/EventBus
only 3 steps and yes it is 3rd PartyLibrary. its very light should not affect your app size as well
Generally for such scenario I will keep the data in Main Activity as static data and use and update them in other activities.
For example you can declare and populate these 2 variables in Main Activity (i.e. MainActivity)
public static ArrayList arrayList ;
public static SparseBooleanArray sparseBooleanArray ;
now all other activities while populating list values, they can populate from array list using name MainActivity.arrayList. When user select or unselect a value only sparseBooleanArray will be updated with a boolean value.
while populating values first time in arrayList and sparseBooleanArray , ensure to use same index so they will be in sync
arrayList.add(1,"List Item 1") ;
sparseBooleanArray.put(1,false ) ; // represent selected value for List Item 1
In case you have plan to use this functionality for multiple activities, arraylist will remain same, however there will be one SparseBooleanArray for each activity to store activity wise selected values.

How to close all open Activities and open a new one from a Java Class

I have created a class that is extending from CountDownTimer, It has a a method onFinish() which calls when timer expires.
There are 6 Activities, user can be in any activity when timer expires, So in CounterTimerwhen Finish() method calls , i need to show an Alert Message to the user,along with i need to redirect user to Login page.
Things getting confusing, as i cannot call Intent class in the Normal Class, I can also not pass the context, as user can be in any activity.
I have written following code, but its not helping out.
I am using context here, but its giving error message on passing context to Intent
public class CounterClass extends CountDownTimer implements ITMServiceEvent {
#Override
public void onFinish() {
if(sql_code.equalsIgnoreCase("0")) {
String resultCode = command1.getString("result");
context.startActivity(context.getApplicationContext(), MainActivity.class);
}
Calling Timer at the Start of Wizard, in a Fragment
CounterClass counterClass= new CounterClass(180000,1000);
counterClass.setTextView(tvTimer);
counterClass.start();
There are two parts of your question, first is how you can clean up the Activity stack and start a new Activity on Top of them, I suppose this would be the LoginActivity in your case.
To do this, you need to set the Flag of your LoginActivity Intent when you want to start it,
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
And the second part is, you want to be able to finish the current activity after showing a dialog to the user. I assume your Timer is a Service Class, which runs in the background. The way to tell your current activity that the Time is Up ! is to send a Broadcast Message. Preferably, LocalBroadcastManager can help you out. You can have a BaseActivity class where all of your 6 Activities can be extended from it and you can register/unregister LocalBroadcastManager to/from those activities in the BaseActivity class (register in onResume and unregister in onPause). After you register them you just need to implement and handle the onReceive method where you can show a dialog and start the LoginActivity after finishing the current one.

Call Android Activity from inside?

Is it possible to call an Activity form inside the Activity class, so I can deliver information over constructor?
something like
public MyClass(){
startActivity(new Intent(this, this.getClass()));
}
I'm assuming this is because you want to pass some initialisation data to the activity?
The way to do this is by adding a Bundle to the activity.
Intent intent = new Intent(YourStartingActivity.this,YourNewActivity.class);
intent.putExtra("key", "value");
startActivity(intent);
The in the OnCreate method of your new Activity
Bundle bundle = getIntent().getExtras();
String myString = bundle.getString("key");
Which will get whatever you passed in as your "value" which can be a String, int, float etc....
I think you can't do that. If I understood correctly you want to pass data between two activities, you should always do this via Intent. Take a look on this https://stackoverflow.com/a/2091482/3707606
If you want to pass more complex data you should make the data class implement Parcelable. It may look hard but you can generate your parcelable at http://www.parcelabler.com/ or install this plugin to Android Studio.

use function from main activity in another java file

I’m trying to call a method in my main Activity from another file, but it crashes. I can easily do this the other way. Can you not invoke methods of the main Activity from another Activity?
public class MainActivity extends Activity {
….
……..
……
public void my_function(String a){
//do some stuff
}
}
package main;
public class stuff extends Activity {
….
….
…
MainActivity run = new MainActivity();
run.my_function(String a);
}
}
If you want a method to get called from different classes, create a seperate class
and encapsulate the logic. See an activity more as a view controller, the logic
should be somewhere else.
Sorry for my english, hope this helps.
Steve
The problem is this line
MainActivity run = new MainActivity();
you never instantiate Activities directly, you need to instantiate them through Intent objects.
Intent intent = new Intent(this, MainActivity.class);
If you want to instantiate a new activity use an Intent. If you want to call my_function in an activity that is already instantiated, you need first to get a pointer to that Activity, which in Android is a little bit tricky.
Additionally, the fact that you want to call a method from another activity is a sign of bad design, or that you don't fully understand the Android way of doing things.
Think if there's any other approach you can use for your purpose.

How to I can call a method from another activity with passing data?

I have 2 activities.
I start one, and at a point I start another one:
Intent enabler = new Intent(this, cprompt.class);
startActivity(enabler);
I want to call a method from the old one, but I want to pass some data too.
This is how I tried:
Activity1.sendcommand(DATA);
And I got this:
Cannot make a static reference to the non-static method sendcommand(String) from the type Activity1
And I don't want change the method to static.
The only way if I make a Listener? If I have to, you can describe for me to how?
The java is new for me... :/ But if this problem is solved I think I am done with my program :)
Only one Activity is active at a time. Are you trying to trigger the method just because you want to pass some data?.You can do it via an Intent
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("YOUR_DATA_KEY", "Data Value");
startActivity(intent);
and in the SecondActivity , you can retrieve the data and process it
String data = getIntent().getStringExtra("YOUR_DATA_KEY");
It's not just Strings that you can send this way.You can even transmit Serializable and Parcelable Extras. For more information refer - Intents on Android Developer Website
You can declare an interface and make Activity1 implements that interface..
Then when you need to call Activity1's method call the inetrface's method...
Your interface:
public interface OnSendCommand{
public void onSendCommand(values);
}
Activity1:
public Activity1 implements OnSendCommand {
public void onSendCommand(values){}
}
Are you returning to the first activity from the second when executing this method? If so you could use startActivityForResult() following this tutorial. If not, then something is wrong with the structure of your application if this method can not be static, and this method should be in a separate class not inheriting from Activity.

Categories

Resources