Starting an Android Activity from an Listener defined in an external class file - android

I have an Activity MyActivity with a Button MyButton.
I want to attach a MySpecialOnClickListener to MyButton.
I write MySpecialOnClickListener in an external class file.
public class MySpecialOnClickListener extends ButtonHandler implements OnClickListener {
public OnClickListenerWithSpeech (Context context)
{ super.context = context; }
#Override
public void onClick(View view) { handleClick(view); }
}
and ButtonHandler looks like this
public abstract class ButtonHandler {
protected Context context;
protected void handleClick (View view){
if (view.getid()==R.id.button_B) {
context.startActivity (new Intent(context, ActivityC.class));
}
}
}
I basically want to store all logic for Buttons in the ButtonHandler.
SO...as I said, I have the MySpecialOnClickListener defined in an external class file.
When I click MyButton I get the following fatal error.
Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
So I can't start an activity normally from within a non-Activity. Fair enough.
However, if I change MySpecialOnClickListener to be an inner class in 'MyActivity' it works fine. Remember 'ButtonHandler' is still an external class file. So it (where ActivityC is ultimately started from) doesn't change.
My question (finally) is: can someone explain the logic of why one is allowed and the other isn't. I presume its a scoping thing or something but I'm a bit confused. It seems the code to start the process of starting an activity has to literally be inside another Activity.
EDIT - PROBLEM SOLVED
See below. The location of the class is irrelevant. I just didn't pass in the context properly.

because the ButtonHandler 'context' field isn´t associated with any activity context. So, when you attach the MySpecialOnClickListener instance to a button you create it passing the context parametener, isn´t???
something like this:
MySpecialOnClickListener listener = new MySpecialOnClickListener(MyActivity.this);
aButton.setOnClickListener( listener );
in this way you´re constructing the Button with the correct context...

It's likely that you are not passing the Activity context to MySpecialOnClickListener. Could you show me the difference in the way you invoke the inner-class approach?

Apologies to those of you who tried to answer. It was my fault (and I didn't include the following info initially for people)
When I was passing in the context to the 'MySpecialOnClickListener' I would do:
view.setOnClickListener(new MySpecialOnClickListener(getApplicationContext()));
when I should have done:
view.setOnClickListener(new MySpecialOnClickListener(this));
So getApplicationContext() doesn't seem to get the "correct" context for the app.
Which leads me to my next question as to what getApplicationContext() actually returns :)

Related

findViewById in non activity class

I know there are some topics in StackOverFlow asking this But all of them are answering in special cases No one answers this question generally.
Can anyone say how to use findViewById in non activity classes?
For Example in my case I want to define a webview:
WebView view=(WebView)findViewById(R.id.webview);
But I can't and I really don't understand why android makes everything complicated.Why you can use everything in main activity but you can't use many of them in non activity class :(
UPDATE
I can't extend my class as activity cause it extends sth else.
UPDATE
This is the class:
class DownloadTask extends AsyncTask<String, Void, Void> {
protected Void doInBackground(String... sUrl) {
...
WebView view=(WebView)findViewById(R.id.webview);
final Snackbar snackbar = Snackbar.make(view,"message",Snackbar.LENGTH_LONG);
...
}
}
I'm gonna use the webview in a Snackbar.
Can anyone say how to use findViewById in non activity classes?
Pass the activity into the method you are calling on the non-activity class.
Or, pass the activity into the constructor of the non-activity class.
Or, call findViewById() in the activity and pass the WebView to the non-activity class.
Plenty of other patterns exist. You need to be careful that you do not try using the activity or WebView longer than you should (e.g., after the user rotates the screen, presses BACK, or otherwise causes the activity to be destroyed).
I'm gonna use the webview in a Snackbar.
Using a Snackbar is fine. Using one from an AsyncTask is not, unless you do so very carefully. In particular:
Only try doing this from the main application thread (i.e., not doInBackground())
Make sure that you are handling configuration changes, BACK presses, and the like properly. In particular, you cannot show a Snackbar on a destroyed activity
1-in non activity class:
public Context con;
public NonAct(Activity c){//NonAct = your non activity class name
this.con = c;
}
//in your class or function do this:
WebView view=(WebView)con.findViewById(R.id.webview);
2-call non activity class with sending context argumant:
NonAct n = new NonAct(YourActivity.this);
try this
ClassName instance = new ClassName(this);
and starting of your class will look like this
public class ClassName extents to something {
public Activity activity;
//.... other attributes
public ClassName( Activity _activity){
this.activity = _activity;
//other initializations...
you can use findviewby id like this
WebView mywebview = (WebView)this.activity.findViewById(R.id.mywebview);
///// now do whatever u want
i hope this will help u.
just look at this link u have to pass your view inflated to AsyncTask
findviewbyid in asyncTask

Access button reference from other class

I have somthing like that:
public class A()
{
private Button myButton;
public void setMyButton(Button myButton)
{
this.myButton = myButton;
}
public Button getMyButton()
{
return myButton;
}
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
setMyButton(button);
}
public class B()
{
public void exampleMethod()
{
A aObject = new A();
Button button = aObject.getMyButton();
}
}
Button in class B is always null. I tryied that:
In class A
public Button myButton;
In class B
A aObject = new A();
Button button = aObject.myButton;
but it is not working too.
I am sure that first is button initiate, then geting button reference. I checked that using logs.
I don't know what is going on, becasue "getMyButton" in class A work fine. How can I get reference of button from class A in class B?
What is the best way to do that?
Looks like you are creating new java object of your activity on your own. Please try to get existing object of an created activity; so that you will get activity context and activity properties as well.
The button is always null because its set in onCreate, which is not automatically called. Let me guess, A is supposed to be an Activity subclass, based on the signature, right? In that case you're doing things really wrong.
*You cannot create an Activity via new, it won't be properly initialized.
*Accessing views of an Activity like that is really weird. It makes more sense to pass the view into B, as B is likely owned by A. If the Activity A doesn't own B, you're probably doing something really wrong. Pretty much if you need to do this you've probably misarchitected something.
The way that you are doing will only works in JAVA and not in ANDROID.
Its because of ACTIVITY class. Activity class reference will be created only when its life cycle is created and you cannot pass the UI elements of one activity to Another.
As the button is associated with the 'A' Class in your case and if you want this in Class 'B' you have to start Activity and its life cycle and also setContentView(R.layout.activity_main);
Other way is get the data that you want from any class and publish the value in 'A' class itself. this can be done by startActivityForResult();

Pass reference of one Activity to another Activity

I know that I can pass some values between Activities using intent.
However, if I want to pass whole Activity to another Activity I think it is not good approach.
Is there another way to do that?
I have Settings Activity in which I am changing some Colors. So after I come back to my Main Activity I would like to apply those colors. To do this, I need access to MainActivity fields after I change Color value, so inside PreferenceActivity. In other words, I want to have access to Main activity fields from PreferenceActivity class. Any ideas?
You should be using a SharedPreference and then accessing that in your main activity. I recommend you reading up at http://developer.android.com/guide/topics/ui/settings.html because it seems like you are implementing your settings activity incorrectly. The part you might be specifically interested in is the "Read Preferences" section. However, I strongly suggest you read through the whole thing and then implement your settings the proper way.
Updated answer with the 3 different ways (that I can think of):
1) Start your preference activity using startActivityForResult(), then in your onActivityResult() access the SharedPreference and make your necessary changes. See here
2) Register a SharedPreferenceChangeListener with your MainActivity, which will be called when any changes happen to your SharedPreference. See here for a detailed discussion. Also see my initial response.
3) In your MainActivity's onResume(), access the SharedPreference and then make your changes there. I do not like this method because you will be cluttering onResume() with more logic and you will also probably have to have a variable that keeps track of the state of the variable you are interested in.
I would personally go with option 2 because the callback was created for this exact purpose.
I think you could pass the value by using method putExtra(name, value).
And after you start new activity you can get the value you pass before by using method getStringExtra(name).
Shared preferences can be used. If you want your changes to be reflected right away add listener. Refer to SharedPreferences.onSharedPreferenceChangeListener. Its an easy way to do.
If you want to lots of changes required in many activity from you change in any one.
And access last modify data from all Activity and modify also.
for example.
Constants.java
public class Constants
{
public static String name;
}
In your MainActivity you have an editText.
MainActivity.java
public class MainActivity extends Activity {
private EditText yourName;
private Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
yourName = (EditText) findViewById(R.id.yourName);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Constants.name = yourname.getText().toString();
Intent intent = new Intent(getApplicationContext(),Activity2.class);
startActivity(intent);
}
});
}
In your Activity2 you have an TextView and that getting value which you enter in MainActivity.java without pass in Intent.
Activity2.java
public class Activity2 extends Activity {
private TextView yourName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
yourName = (TextView) findViewById(R.id.tv_yourName);
// directly use ferom serializable class
yourname.setText(Constants.name);
}
like that you use many values from all activity and modify from all activity.

Calling an activity from a custom dialog

I guess this is just a simple question (I’m such a noob…)
I have this custom dialog box that has 3 buttons in it.
Now I want to call an activity from one of the buttons so
I tried this:
public class picturedialog extends Dialog implements OnClickListener {
Button Camera;
public picturedialog (Context context){
super (context);
setContentView(R.layout.picturedialog);
Camera = (Button) this.findViewById(R.id.pdButton1);
Camera.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
dismiss();
Intent myIntent = new Intent(view.getContext(), CameraActivity.class);
startActivity(myIntent);
}
});
...
}
Then the red squiggly line appears on startActivity(myIntent).
Upon hovering on it, eclipse tells me this: “The method startActivity(Intent) is undefined for the type new View.OnClickListener(){}”
Ehhh? Please orient me on how to do this properly.
Any help would be appreciated.
Suppose the name of your Activity is A, then you just do:
A.this.startActivity(myIntent);
The problem arises because "this" inside your inner class refers to the object of that inner class, when what you want is the object of the enclosing Activity. A.this will refer to that.
If you aren't enclosing this class in an Activity, then try calling the startActivity from method using the context that you passed into the method, e.g. context.startActivty(myIntent).
The startActivity method belongs to the Context class.
I am sure you are overcomplicating with subclassing from Dialog. Try to follow to the dialog tutorial - https://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog
Note that dialogs are created on the fly (in Activity.onCreateDialog()) without the need to have your own custom dialog classes. Since you set a listener being inside of the wrapping activity (if you follow the tutorial), then you are able to call startActivity(myIntent), because all the fields/methods of a wrapping class instance are available for an instance of an inner class.

New Activity nullpointerexception

I have a beginners problem. Here is my situation:
I want to start a new activity from the main activity. The code to launch the new activity is found in a separate class file. I seem to be passing the wrong arguments and I am ending up in a nullpointerexception when trying to launch the new activity. The new activity launches fine when I place the code in the main activity class file, therefore the second activity and the manifest are fine. Here is a sample of my code:
In my main activity class where I instanciate the second class (THIS IS MY MAIN ACTIVITY. I OMITTED THE REST BECAUSE I DO NOT THINK IT IS RELATED TO THE PROBLEM):
Tester mytest = new Tester();
mytest.test(this);
In my second class file (THIS IS NOT AN ACTIVITY; IT IS A CLASS THAT IS INSTANTIATED IN THE ACTIVITY):
public class Tester extends Activity {
Intent myIntent;
public void test (Context context) {
myIntent = new Intent (Intent.ACTION_VIEW);
myIntent.setClass(context, newActivity.class);
thebutton.setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
startActivity(myIntent);
}
}
):}
When I perform the click I receive a nullpointerexception at startactivity. Can anyone enlighten me on this please?I am sure that I am wrongly using the context.
Activities are started with Intents. Please read the Android Application Fundamentals first and try the Hello World app :)
I understood that you will use your separate Tester class at all cost ;) so I'm trying to adapt and help you out there.
First of all, don't let your class inherit from Activity. This won't help you, cause this calls will probably not have any valid context. Activity somehow implements the template pattern, providing you key method like onCreate(...), onPause(...) etc and is instantiated by the Android OS.
If you still want to use the class, you have to pass in the context. Probably you're aiming for some MVC/MVP pattern structure, anyway.
public class Tester {
private Context context;
public Tester(Context context){
this.context = context;
}
public void test () {
final Intent myIntent = new Intent(context, NewActivity.class);
//guess this comes from somewhere, hope through a findViewById method
thebutton.setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
context.startActivity(myIntent);
}
}
)};
}
}
This would be a proposed solution from my side. A problem I still see here is on how you retrieve the button in that test() method. In order to have that work properly you have to retrieve it from some View class (with view.findViewByid(R.id.myButton)) or to create it dynamically and associate it with the view during the onCreate(...) of your Activity (probably using an Inflater).

Categories

Resources