Android: Launching new activity from dialog - android

I'm trying to use a custom dialog to get user input for a title String, and then if the user clicks OK, it will fire up a new Activity (basically a notepad) with that title String as the title. However, when I try to call the method that fires the new activity inside onClick(), it gives me an error.
Here's the code
class NewListDialog extends Dialog implements OnClickListener {
Button search;
EditText text;
public NewListDialog(Context context) {
super(context);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.newlist_dialog);
search = (Button) findViewById(R.id.dialog_confirm);
text = (EditText) findViewById(R.id.dialog_editable);
search.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v == search) {
String title_name = text.getText().toString();
// method for launching new activity
fireListEdit(title_name);
}
}
}
void fireListEdit(String title_name) {
Intent i = new Intent(this, ListEdit.class);
i.putExtra(InvenDB.KEY_TITLE, title_name);
startActivityForResult(i, ACTIVITY_CREATE);
}
And I call this dialog with
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch(item.getItemId()) {
case INSERT_ID:
NewListDialog dialog = new NewListDialog(this);
dialog.show();
return true;
case QUIT_ID:
finish();
return true;
}
return super.onMenuItemSelected(featureId, item);
}
Edit: when I run it on emulator, when I click OK on the custom dialog it just gives me "the application stopped unexpectly" error
EDIT:
This is the logcat, I'm not really sure what they mean :\
01-12 17:39:27.668: ERROR/AndroidRuntime(426): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.jin.inventoryapp/com.jin.inventoryapp.ListEdit}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0

From what I can tell there is a problem with the Adapter (data) part of your application. Whatever Adapter class you used to back your com.jin.inventoryapp.ListEdit, it has a problem accessing the data. i.e. if you are using an array or database to populate your ListView, check there first.
This is useful to figure out who is throwing an exception.

Related

Changing from Activities to Fragments

I am trying to fix up my app code and transition from Activities to Fragments, in order to transition to the navigation draw and eventually have some sliding tabs too.
Currently for navigation I am using the 3 dots drop down menu from the action bar which I know is not really right. Which is why I am trying to transition to fragments.
I want to keep my action bar menu so I can keep my search icon in the action bar but I want to add a navigation draw to it.
I currentley have a class called ActionBarMenu which extends activity. All my activities come form this because this class holds all the functions which open new activities for the action bar menu I have set up right now.
public class ActionbarMenu extends Activity {
public void goToSearch (MenuItem item) {
// go to search page
Intent i = new Intent(this,Search.class);
startActivity(i);
}
public void goToStatistics (MenuItem item) {
// go to search page
Intent i = new Intent(this,StatisticsPage.class);
startActivity(i);
}
public void goToFindBrewery (MenuItem item) {
// go to search page
Intent i = new Intent(this,FindBrewery.class);
startActivity(i);
}
public void goToContact (MenuItem item) {
// go to search page
Intent i = new Intent(this,ContactPage.class);
startActivity(i);
}
public void goToPortfolio (MenuItem item) {
// go to search page
Intent i = new Intent(this,Portfolio.class);
startActivity(i);
}
public void goToDiscover (MenuItem item) {
// go to search page
Intent i = new Intent(this,Discover.class);
startActivity(i);
}
public void scanBarcode (MenuItem item) {
//open scanner
IntentIntegrator scanIntegrator = new IntentIntegrator(this);
scanIntegrator.initiateScan();
}
//get result value
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// retrieve scan result
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
// we have a result
String scanContent = scanningResult.getContents();
// launch async task for results
String url = "http://api.brewerydb.com/v2/search/upc?code=" + scanContent + "&key=0cdb22f84315834cc807c0176a927060&format=json&withBreweries=y";
new GetBeerDataFromUPCJSON(this).execute(url);
} else {
Toast toast = Toast.makeText(getApplicationContext(), "No scan data received!", Toast.LENGTH_SHORT);
toast.show();
}
}
}
I tried to change it to a fragment by changing extends activity to extends Fragment and all intents I build to launch new activities all get the red squiggly underline. I am just experimenting and trying to learn what's going on and whats the best way to transition my app from activities to Fragments, without having to recode everything.
Your problem is probably because in a line such as
Intent i = new Intent(this, Discover.class);
this now refers to a Fragment instead of an Activity. Intent() expects a Context as the first argument; Activity extends Context, but Fragment does not. To fix your problem, you should change this to getActivity().
For future reference, mousing over the little red x that appears next to the error should tell you exactly what the problem is.
Instead of using intents, you'll use the fragment manager to load new fragments. Read this page on the android website about fragments.
The finished code for quick replacement would be:
Intent i = new Intent(getActivity(), Discover.class);
startActivity(i);
you just need to make it same like backpressed if the activity is just next from your fragment like... it should work ....
#Override
public void onClick(View view) {
onBackPressed();
}
Intent i = new Intent(this, Discover.class);

How to show a new screen from menu item

I'm new to android and trying to find out how to show a new screen when the user clicks something in the menu item.
I'm using ActionbarSherlock and looking at the sample github-android app.
When the user clicks on an item in the menu, I want to show them a new screen. Github code is doing that like so:
startActivityForResult(new Intent(getActivity(), CreateGistActivity.class), GIST_CREATE);
But I've seen some code samples do:
Intent i = new Intent(getApplicationContext(), SomeActivity.class);
My code looks like this:
public class MainActivity extends SherlockActivity {
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create) {
//show createactivity class
return true;
}
return true;
}
What is the right way to do ?
You can do it just like that:
public class MainActivity extends SherlockActivity {
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create) {
//show createactivity class
Intent i = new Intent(MainActivity.this, SomeActivity.class);
startActivity(i);
return true;
}
return true;
}
startActivityForResult is used when you have to return some value/data to the first screen like a user selection. More here
As far as the context to use getActivity() or getApplicationContext(), I prefer to use the context of current activity MainActivity.this its more straitforward similar to documentation example
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
Inside a fragment use getSherlockActivity() instead of getActivity() as getActivity() can cause crashes to older devices.
Of course getApplicationContext() would always work and not crash but I feel that it may mess the garbage collector and do not let activities to be cleared (but not sure about it)
Just use startActivityForResult
There is no 'right' way. The Github code doesn't first declare the variable. The onther does. I believe for a menu, you normally need to declare the Intent as a local variable, if not a field.
Create an intent: Intent i = new Intent(MainActivity.this, CreateGistActivity.class);
where MainActivity is the activity you're in, and CreateGistActivity is the class you want to launch.
Then use startActivity(Intent) to launch the new activity: startActivity(i);
Or just combine them:
startActivity(new Intent(MainActivity.this, CreateGistActivity.class));
Full code:
public class MainActivity extends SherlockActivity {
....
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.create)
{
Intent i = new Intent(MainActivity.this, CreateGistActivity.class);
startActivity(i);
return true;
}
return true;
}
startActivityForResult probably isn't needed in your case, unless you're expecting to send values between the classes.

Launching a new Activity from a Context Menu and automating another Activity in the onCreate relaunches the same Activity

I have two Activities in which I want to call the second one from the first one's Context Menu. This is what it should do.
Activity A Context Menu click should start Activity B.
In the onCreate of Activity B, depending on the extras passed in, automatically display a AlertBuilder dialog and then either take a picture or select an image.
What is happening is that when Activity A's Context Menu item is clicked, it launches Activity B and the AlertDialog displays. If I select the option to take a picture, the MediaStore.ACTION_IMAGE_CAPTURE intent is started and once the picture is taken, Activity B is re-launched again and the AlertDialog shows.
Activity A - Context Menu
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
final ItemClass selItem = (ItemClass)this.getListView().getItemAtPosition(info.position);
Intent intent;
SyncData sync;
switch (item.getItemId()) {
case R.id.start_activity_b:
Intent intent = new Intent(ActivityA.this, ActivityB.class);
intent.putExtra("data1", selItem.itemID);
intent.putExtra("data2", "AUTO");
Measurements.this.startActivityForResult(intent, REQUESTCODE_ACTIVITYB);
return true;
default:
return super.onContextItemSelected(item);
}
}
Activity B - onCreate Code
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.listview_main);
Bundle extras = getIntent().getExtras();
if ((extras != null) && (extras.containsKey("data1"))) {
this.itemID = extras.getString("data1");
}
if ((extras != null) && (extra.containsKey("data2"))) {
this.createAlertDialog();
}
}
As I stated in my comment, you shouldn't need runOnUiThread() since you are already on the UI Thread. There are a couple ways that may be better than doing this. Again, as in my comment, you should be able to call setResult and finish ActivityB when the Dialog dismisses since you are using startActivityForResult() to start ActivityB.
With just what I see that should be fine. But if it causes problems due to whatever you have in your Dialog or from something else, you can make your Dialog an Activity and give it aDialog themeby adjusting yourmanifest`. Use
<activity android:name=".ActivityName"
android:theme="#android:style/Theme.Dialog"> // add this line to give it the effect of a dialog
</activity>
You can start this Activity for result using startActivityForResult(). Then when that result returns to ActivityB you can finish and return to ActivityA or whatever you need to do.
Hope this helped.
I found the solution to it, after trying over and over to understand why. All that needs to be done is to create a runnable in the Context menu, as it seems to need to be returned quickly otherwise it recreates the Activity. I could be wrong and please feel free to correct me on this one.
Activity A - Context Menu
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
final ItemClass selItem = (ItemClass)this.getListView().getItemAtPosition(info.position);
Intent intent;
SyncData sync;
switch (item.getItemId()) {
case R.id.start_activity_b:
runOnUiThread(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(ActivityA.this, ActivityB.class);
intent.putExtra("data1", selItem.itemID);
intent.putExtra("data2", "AUTO");
Measurements.this.startActivityForResult(intent, REQUESTCODE_ACTIVITYB);
}
});
return true;
default:
return super.onContextItemSelected(item);
}
}

Android error in service: "Unable to add window -- token null is not for an application"

I am trying to create an application with a widget. When the user places the widget on the desktop a listview should come up with a list of items. The user selects an item then the widget is created with the respective text related to that item. I thought I should do this by showing a dialog in the Service but it throws me
Caused by: android.view.WindowManager$BadTokenException: Unable to add
window -- token null is not for an application
to the dialog_newitem.show(); line. For simplicity I am using now a simple alertdialog.
Is it the way to do this? I haven't found anyhing about this on the net.
public class UpdateWidgetService extends Service {
private static final String LOG = "de.vogella.android.widget.example";
public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget";
public static String ACTION_WIDGET_RECEIVER = "ActionReceiverWidget";
String value;
Dialog dialog_newitem;
EditText et_newitem;
#Override
public void onStart(Intent intent, int startId) {
Toast.makeText(this, "UpdateWidgetService", Toast.LENGTH_SHORT).show();
dialog_newitem = new Dialog(this); //I tried UpdateWidgetService.this, too
dialog_newitem.setContentView(R.layout.dialog_productlists_grp_capitalized);
dialog_newitem.setTitle("Select");
dialog_newitem.setCancelable(true);
et_newitem = (EditText) dialog_newitem.findViewById(R.id.et_item_name);
Button btn_Save = (Button) dialog_newitem.findViewById(R.id.btn_save_pr);
btn_Save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
value = et_newitem.getText().toString();
}
});
Button btn_Cancel = (Button) dialog_newitem.findViewById(R.id.btn_cancel_pr);
btn_Cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog_newitem.dismiss();
}
});
dialog_newitem.show(); //error
Toast.makeText(this, "value: " + value, Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I have used this alertdialog in some other part of the code, and there it is working fine. I think it has something to do with the service.
You can't show a dialog in the service.
if you really want to show a dialog.
try to start an Activity and set the Activity's Theme to Theme.Dialog.
There is a demo in The ApiDemo Project
I know this thread is old, but thought it would be worth contributing anyway for future sufferers.
Although most will say its not recommended to launch dialogs directly from a service, the following workaround works for me. Use the ServiceDialogBuilder class below to build your AlertDialog. Unlike the AlertDialog.Builder, this will work with a Service context and show() can be called directly from a service without having to start a new activity.
Just be wary that this is a bit of a hack, so there may well be some unintended side effects from doing this.
Hope this helps
public class ServiceDialogBuilder extends AlertDialog.Builder {
public ServiceDialogBuilder(Context context) {
super(context);}
#Override
public AlertDialog create() {
AlertDialog dialog=super.create();
//Change dialog window type from TYPE_CHANGED to TYPE_SYSTEM_ALERT
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
return dialog;
}
#Override
public AlertDialog show() {
return super.show();
}}
Just make sure your dialog's window is set to SYSTEM_ALERT:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

passing this to an outer class and starting an activity from alertdialog's list on Android

I am developing an Android app, this app has a dozen of Activities, each one is for a corresponding screen. Now I have this common subtitle bar on top of the screens.
this subtitle bar has a button to display an alert dialog which shows link list to go to a different screen.
I could write a same function for each activity to call the alert dialog, but that would be tedious if I want to modify them, so I created this class:
public class MenuAlertDialog extends Activity {
/*
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
*/
public void createMenu(final Context context){
AlertDialog.Builder dlg = new AlertDialog.Builder(context);
dlg.setTitle("menu");
String[] items = {"pageA", "pageB", "pageC", "pageD", "pageE"};
dlg.setItems(items, new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which){
switch(which){
case 0:
Intent intent = new Intent(context, MainActivity.class);
startActivity(intent);
break;
default:
break;
}
}
});
dlg.show();
}
}
and call it from each activity, like this:
MenuAlertDialog menu = new MenuAlertDialog();
menu.createMenu(this);
from inside of onCreate.
It can display the alertDialog, but whenever I press pageA link, it fails with an unexpected error.
Logcat says its a nullpointererror and the cause seems
startActivity(intent);
What am I doing wrong?
Remove the code
extends Activity
as you have no need to extend your class that you are creating since it does not rely on any activity related functionality.
Where you call startActivity(intent); replace it with
context.startActivity(intent);
You should change the class to Extends Dialog and not activity.
Also for Try this:
Check out this tutorial on how to create a custom dialog. Custom Dialog
Also Here Another Tutorial
And Here

Categories

Resources