SubActivites with return value - The InputBox

Basic Tutorials concerning: GUI, Views, Activites, XML, Layouts, Intents, ...

SubActivites with return value - The InputBox

Postby plusminus » Sat Nov 24, 2007 1:35 pm

SubActivites with return value - The InputBox


What you learn: You will learn how to start a SubActivity, that will return a String (+ extra Data), what is in the end exactly like an InputBox.

:?: Problems/Questions: Write them right below...

Difficulty: 1 of 5 :)

What it will look like:
Image Image Image


Description
This has been a very common question, as in "normal" Java you can make a blocking a MessageBox was displayed with code like:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public static String JOptionPane.showInputDialog(Component parentComponent, Object message);
  2. // Example implementation:
  3. String retString = JOptionPane.showInputDialog(this,"Enter your name:");
Parsed in 0.031 seconds, using GeSHi 1.0.8.4

in Android you can't really do fully blocking Dialogs, imagine what should happen if there is an incoming phone-call :?:
showAlert, will not help us, as it is a non-blocking dialog. Remember:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. showAlert("A funny title", "MessageBoxes rule extremely!", "Hit Me!", false);
Parsed in 0.031 seconds, using GeSHi 1.0.8.4


But there is a pretty easy workaround for doing so...

0. Lets quickly define the Strings we are going to use
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3.     <string name="main_app_name">MainActivity - anddev.org</string>
  4.     <string name="main_cmd_opensub">Open SubActivity</string>
  5.     <string name="sub_app_name">SubActivity returning Result - anddev.org</string>
  6.     <string name="subactivity_cmd_return">Return to MainActivity</string>
  7. </resources>
Parsed in 0.002 seconds, using GeSHi 1.0.8.4


1. What we need to do is the follwoing:
  1. Override the onActivityResult(...)-method coming from Activity to react on a Activity we opened, that returned sth. .
  2. Start that Activity that will return sth. to us, using: startSubActivity(...)
  3. Call setResult(int resultCode, String data) within our (sub)Activity and close it.
:arrow: The onActivityResult(...)-method in our MainActivity will be called :!:

2. So this is the layout-file of the MainActivity (we simply need a button, nothing more):
We need to add the id-attribute to the Button, because we need to add an OnClickListener to it.
For basic information about XML-Layouting, take a look :arrow: here.


"/res/layout/main.xml"
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.    android:orientation="vertical"
  4.    android:layout_width="fill_parent"
  5.    android:layout_height="fill_parent"
  6. >
  7.         <Button  id="@+id/mainactivity_cmd_opensub"
  8.                 android:layout_width="fill_parent"
  9.                 android:layout_height="wrap_content"
  10.                 android:text="@string/main_cmd_opensub"
  11.    />
  12. </LinearLayout>
Parsed in 0.002 seconds, using GeSHi 1.0.8.4


"/src/your_package_structure/MainActivity.java"
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package org.anddev.android.subactivitywithresult;
  2.  
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.os.Bundle;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.widget.Button;
  9.  
  10. public class MainActivity extends Activity {
  11.     protected static final int SUB_ACTIVITY_REQUEST_CODE = 1337;
  12.  
  13.         /** Called when the activity is first created. */
  14.     @Override
  15.     public void onCreate(Bundle icicle) {
  16.         super.onCreate(icicle);
  17.         // Apply our main.xml-Layout
  18.         setContentView(R.layout.main);
  19.        
  20.         // Find the button defined in the main.xml
  21.         Button cmd_opensub = (Button)findViewById(R.id.mainactivity_cmd_opensub);
  22.         // Add an OnClickListener to it, that will open the SubActivity
  23.         cmd_opensub.setOnClickListener(new OnClickListener(){
  24.                         // @Override
  25.                         public void onClick(View arg0) {
  26.                                 Intent i = new Intent(MainActivity.this,
  27.                                                                         SubActivityWithResult.class);
  28.                                 // We use SUB_ACTIVITY_REQUEST_CODE as an 'identifier'
  29.                                 startSubActivity(i, SUB_ACTIVITY_REQUEST_CODE);
  30.                         }
  31.         });        
  32.     }
  33.    
  34.         @Override
  35.         protected void onActivityResult(int requestCode, int resultCode,
  36.                                                                 String data, Bundle extras) {
  37.                 super.onActivityResult(requestCode, resultCode, data, extras);
  38.                 // Here We identify the subActivity we starte
  39.                 if(requestCode == SUB_ACTIVITY_REQUEST_CODE){
  40.                         // And show its result
  41.                         showAlert("SubActivity returned", "ReturnValue: " + data,
  42.                                                         "OK", false);
  43.                 }
  44.         }
  45. }
Parsed in 0.041 seconds, using GeSHi 1.0.8.4


3.Now lets take a look at the SubActivity.xml (provides an EditText to enter the return-String and a "Return to Main"-Button and the SubActivityWithResult-Class, which is also well commented:

"/res/layout/subactivity.xml"
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.    android:orientation="vertical"
  4.    android:layout_width="fill_parent"
  5.    android:layout_height="fill_parent"
  6.    >
  7.     <EditText id="@+id/subactivity_edit_returnvalue"
  8.         android:layout_width="fill_parent"
  9.         android:layout_height="wrap_content"
  10.         android:background="@android:drawable/editbox_background"
  11.         android:singleLine="true"
  12.    />
  13.         <Button id="@+id/subactivity_cmd_return"
  14.             android:layout_width="fill_parent"
  15.             android:layout_height="wrap_content"
  16.             android:text="@string/subactivity_cmd_return"
  17.    />
  18. </LinearLayout>
Parsed in 0.003 seconds, using GeSHi 1.0.8.4


"/src/your_package_structure/SubActivityWithResult.java"
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package org.anddev.android.subactivitywithresult;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.view.View.OnClickListener;
  7. import android.widget.Button;
  8. import android.widget.EditText;
  9.  
  10.  
  11. public class SubActivityWithResult extends Activity{
  12.        
  13.         protected final int SUCCESS_RETURN_CODE = 1;
  14.     /** Called when the activity is first created. */
  15.     @Override
  16.     public void onCreate(Bundle icicle) {
  17.         super.onCreate(icicle);
  18.      // Apply our subactivity.xml-Layout
  19.         setContentView(R.layout.subactivity);
  20.        
  21.         // Find the button defined in the subactivity.xml
  22.         Button cmd_return = (Button)findViewById(R.id.subactivity_cmd_return);
  23.         /* Add an OnClickListener to it, that will
  24.          * read out the text in the EditBox set it
  25.          * as retrn-data and close this activity */
  26.         cmd_return.setOnClickListener(new OnClickListener(){
  27.                         // @Override
  28.                         public void onClick(View arg0) {
  29.                                 // Find the edittext defined in the subactivity.xml
  30.                                 EditText edit_returvalue = (EditText)findViewById(
  31.                                                 R.id.subactivity_edit_returnvalue);
  32.                                 SubActivityWithResult.this.setResult(SUCCESS_RETURN_CODE,
  33.                                                 edit_returvalue.getText().toString());
  34.                                 // Close this Activity
  35.                                 SubActivityWithResult.this.finish();
  36.                         }
  37.         });      
  38.     }
  39. }
Parsed in 0.040 seconds, using GeSHi 1.0.8.4


4. And finally the AndroidManifets.xml which was has to be altered like the following:
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3.    package="org.anddev.android.subactivitywithresult">
  4.     <application android:icon="@drawable/icon">
  5.         <activity class=".MainActivity" android:label="@string/main_app_name">
  6.             <intent-filter>
  7.                 <action android:value="android.intent.action.MAIN" />
  8.                 <category android:value="android.intent.category.LAUNCHER" />
  9.             </intent-filter>
  10.         </activity>
  11.         <activity class=".SubActivityWithResult" android:label="@string/sub_app_name">
  12.             <intent-filter>
  13.                 <action android:value="android.intent.action.VIEW" />
  14.                 <category android:value="android.intent.category.DEFAULT" />
  15.             </intent-filter>
  16.         </activity>
  17.     </application>
  18. </manifest>
Parsed in 0.004 seconds, using GeSHi 1.0.8.4


:arrow: Thats it, you can easily transform this into a generic InputBox, or just use it somewhere it fits.

Regards,
plusminus
Last edited by plusminus on Mon Dec 17, 2007 7:06 pm, edited 3 times in total.
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Top

Can we do it the other way round

Postby Nitinkcv » Mon Dec 03, 2007 10:03 am

Hi,

My query goes something like this.
1)
My first screen contains the textbox and the button. Next i input some code into the textbox and click on the button.
It opens up another activity which actually displays or shows an alert of whatever i had inputted in my first screen(activity)

2)
Also i require to send back an array of strings back to the calling intent. But the current method only allows me to send a string param.

Thanks,
Nitin
Nitinkcv
Developer
Developer
 
Posts: 29
Joined: Thu Nov 29, 2007 1:02 pm

Postby plusminus » Mon Dec 03, 2007 3:43 pm

Hey Nitinkcv,

the setResult(..) got another Overload, with a Bundle (what is just like a pimped HashMap):
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. Activity.setResult(int, java.lang.String, android.os.Bundle);
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


The Bundle you had filled somewhere in the SubActivity from above gets passed to the onActivityResult(...)-method of the calling Activity:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. protected void onActivityResult(int requestCode, int resultCode,
  2.                 String data, Bundle extras)
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


You can easily put/get various Types to a Bundle, even StringArrays:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. Bundle.putStringArray(java.lang.String, java.lang.String[])
  2. Bundle.getStringArray(java.lang.String)
Parsed in 0.036 seconds, using GeSHi 1.0.8.4

See Googles JavaDoc for Bundle: android.os.Bundle

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

ClassCastException!!

Postby Nitinkcv » Mon Dec 03, 2007 6:42 pm

Hi,

How silly of me.. i should have searched for the overloaded methods. thanks a lot.

Right now i have a main class(main.java) which extends activity and another class(sub.java) which extends
ListActivity. I pass a value from my main.java to the sub.java by using the Intent along with Bundle class.
Now in my sub.java based on the value passed i populate a listview:

one of the methods in the sub.java having the problem:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. protected void SearchForText(String searchText){
  2.        
  3.         for (Iterator iterator = codeEntries.iterator(); iterator.hasNext();) {
  4.                         String type = (String) iterator.next();
  5.                         if(type.contains(searchText)){
  6.                                 searchEntries.add(searchText);
  7.                         }
  8.                 }
  9.         ArrayAdapter<String> SearchList = new ArrayAdapter<String>(this,
  10.                 R.layout.filesearchlayout, this.searchEntries);
  11.      
  12.         this.setListAdapter(SearchList);
  13.     }
  14.  
  15. /*where*/
  16.     private List<String> codeEntries = new ArrayList<String>();
  17.     private List<String> searchEntries = new ArrayList<String>();
  18.    
  19.  
  20.  
Parsed in 0.038 seconds, using GeSHi 1.0.8.4


However on running the app i find that an classcastexception in thrown in the sub.java.
i debugged and everthing seemed ok till the line where searchList was being assigned. All the search entries were getting populated in the List searchEntries.

But after the line this.setListAdapter(SearchList), on hitting F6 it went into some source files and then the ClassCastException was being hit.

What could be the reason? :( is it because the Intent is served from the Activity class while its in the ListView that the Intent is received.

Also do we ALWAYS have to override the method onActivityResult in the class where StartSubActivity is called?

Thanks,
Nitin
Nitinkcv
Developer
Developer
 
Posts: 29
Joined: Thu Nov 29, 2007 1:02 pm

Re: ClassCastException!!

Postby plusminus » Mon Dec 03, 2007 8:46 pm

Hey Nitinkcv,

most of the time the solution is just one click away, or we just look right over it. I know what i'm talking about ... :roll:
Nitinkcv wrote:Hi,
...
But after the line this.setListAdapter(SearchList), on hitting F6 it went into some source files and then the ClassCastException was being hit.


Hm, that is strange... :!: Is the Exception thrown at or after the line you said :?:
I tried it with me and it works fine. Which of the parameters does the ClassCastException refer to :?: as it cannot be this.searchEntries (by logical thinking and its type). The others look also very right:!:

Nitinkcv wrote:What could be the reason? Sad is it because the Intent is served from the Activity class while its in the ListView that the Intent is received.

Don't think that it happens because of the Intent as it only starts your Activity (???) and thats it. But if it was so, there would probably be no ClassCastException...

Nitinkcv wrote:Also do we ALWAYS have to override the method onActivityResult in the class where StartSubActivity is called?

No you don't have to as there is sth. like a default-procedure in the onActivityResult(..) from the Baseclass: Activity we are overriding.

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

ClassCastException

Postby Nitinkcv » Tue Dec 04, 2007 2:38 pm

A trivial mistake. i had given the layout file which is being used by my main.java.
this had the relative layout :)

just had another query. is it possible for me to retain a layout having a textbox and then a list of items.
what i mean is that my sub.java which extends the listactivity would have a textbox at the top plus the list of all the search entries?

Similar to the sorts of MasterPages in .Net 2.0

Thanks,
Nitin
Nitinkcv
Developer
Developer
 
Posts: 29
Joined: Thu Nov 29, 2007 1:02 pm

Top

Postby plusminus » Tue Dec 04, 2007 3:52 pm

Hello Nitincv,

yes it it possible, like it is even possible, to have a EditText, a MapView and Buttons in one layout :!:
:arrow: Have a look here.

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Source code for Link.

Postby Nitinkcv » Tue Dec 04, 2007 4:43 pm

Hi,

Would be eagerly waiting to get my hands on the source code of that map app.

Thanks,
Nitin
Nitinkcv
Developer
Developer
 
Posts: 29
Joined: Thu Nov 29, 2007 1:02 pm

Postby plusminus » Tue Dec 04, 2007 4:54 pm

Hi Nitinkcv,

I have nothing received so far. Will post it there immediately if lordhong finished cleaning up the code :)

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby venkat » Wed Dec 12, 2007 6:10 pm

i run above program and when i press the "Open Sub Activity" button it will show Error message:(. i have attached error screen shot. i can't fix that error. can u any one help me to solve this problem.

regads,
venkat.
Attachments
mainActivity.png
Error message.
mainActivity.png (23.51 KiB) Viewed 54959 times
venkat
Senior Developer
Senior Developer
 
Posts: 152
Joined: Tue Nov 27, 2007 5:42 am
Location: India

Postby plusminus » Wed Dec 12, 2007 6:43 pm

Hello venkat,

read closely between the lines, there it says: "plusminus forgot to append the altered AndroisManifest.xml :!: " ;)
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3.    package="org.anddev.android.subactivitywithresult">
  4.     <application android:icon="@drawable/icon">
  5.         <activity class=".MainActivity" android:label="@string/main_app_name">
  6.             <intent-filter>
  7.                 <action android:value="android.intent.action.MAIN" />
  8.                 <category android:value="android.intent.category.LAUNCHER" />
  9.             </intent-filter>
  10.         </activity>
  11.         <activity class=".SubActivityWithResult" android:label="@string/sub_app_name">
  12.             <intent-filter>
  13.                 <action android:value="android.intent.action.VIEW" />
  14.                 <category android:value="android.intent.category.DEFAULT" />
  15.             </intent-filter>
  16.         </activity>
  17.     </application>
  18. </manifest>
Parsed in 0.004 seconds, using GeSHi 1.0.8.4


Appended it above too.

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby venkat » Thu Dec 13, 2007 7:21 am

Thank you very much Plusminus :wink: :)
venkat
Senior Developer
Senior Developer
 
Posts: 152
Joined: Tue Nov 27, 2007 5:42 am
Location: India

Postby bloonlabs » Sun Jan 20, 2008 10:55 pm

Ok so I was working on my seperate class today for my app and I keep on coming to the same problem. When I finish the subActivity it just closes the entire program. According to my code it should go back to my main class which will then do stuff. Here is my code:

The subActivity finish():
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.         Button b_save = (Button) findViewById(R.id.b_save);
  3.  
  4.         b_save.setOnClickListener(new Button.OnClickListener() {
  5.  
  6.             public void onClick(View v) {
  7.  
  8.                 editor.commit();
  9.  
  10.                 Options.this.setResult(RESULT_OK);
  11.  
  12.                 Options.this.finish();
  13.  
  14.             }
  15.  
  16.         });
  17.  
  18.  
Parsed in 0.038 seconds, using GeSHi 1.0.8.4


The main class:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.     @Override
  3.  
  4.     protected void onActivityResult(int requestCode, int resultCode, String data, Bundle extras) {
  5.  
  6.         super.onActivityResult(requestCode, resultCode, data, extras);
  7.  
  8.         if (requestCode == ACTIVITY_OPTIONS) {
  9.  
  10.                 if (resultCode == RESULT_OK) restartWilfred();
  11.  
  12.                 else if (resultCode == RESULT_CANCELED) gotoMainScreen();
  13.  
  14.         }
  15.  
  16.     }
  17.  
  18.  
Parsed in 0.039 seconds, using GeSHi 1.0.8.4


More code can be found at the svn: http://projectwilfred.googlecode.com/svn/

Thanks!!
bloonlabs
Freshman
Freshman
 
Posts: 7
Joined: Tue Dec 04, 2007 12:05 am

Postby plusminus » Sun Jan 20, 2008 11:40 pm

Hello bloonlabs,

the debugger never reaches the onActivityResult(...) :?: Try to ensure such stuff with some logging ( Log.d(...) ).

Thats pretty strange... :?
Your code looks right :!: , but the error has to hide somewhere.
Perhaps you used some IDs that should not be used. :? Try the ID-Values from this tutorial, because they did work with me.

You could try to run exactly the same code from the tutorial, because I can ensure that it works. If it doesn't your problem is perhaps a problem of the emulator. :(

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby venkat » Mon Feb 04, 2008 12:27 pm

Hi plus minus,
Above code is very help full to me. now, I have a problem.
Can you tell me , how to pass value from "activity" to "sub Activity"? (or)
can you tell me how to declare global veriable?
Regards,
Venkat.
venkat
Senior Developer
Senior Developer
 
Posts: 152
Joined: Tue Nov 27, 2007 5:42 am
Location: India

Top
Next

Return to Novice Tutorials

Who is online

Users browsing this forum: No registered users and 6 guests