I keep my alerts and dialog's in a seperate class to prevent clutter. In my activity, I have a webView and the HTML document has a button that executes a custom dialog in Android. I'm using the JavaScriptInterface to communicate between the JavaScript functions in the HTML Documents and Android Java methods. This all works fine with my toast messages and other functions between each other except for this custom dialog.
UPDATE:
I did some changes and now at least I get a NPE that I cant follow. I moved the Dialog method to the JavaInterface to make it easier to debug and a few other chages; see comments in the code.
I don't know what I have wrong. I get no error info in LogCat with this one; just force closes the app...?? Plz look thru my code below.
Thnx for your help!!
LogCat:
Miss a drag as we are waiting for WebCore's response for touch down.
threadid=9: thread exiting with uncaught exception (group=0x4024ee20)
FATAL EXCEPTION: WebViewCoreThread java.lang.NullPointerException
at android.app.Activity.findViewById(Activity.java:1745) at
com.andaero.JavaScriptInterface.onCreateDialog(JavaScriptInterface.java:45)
at android.app.Activity.onCreateDialog(Activity.java:2758) at
android.app.Activity.createDialog(Activity.java:936) at
android.app.Activity.showDialog(Activity.java:2851) at
android.app.Activity.showDialog(Activity.java:2810) at
com.andaero.JavaScriptInterface.showDashBoard(JavaScriptInterface.java:32)
at android.webkit.WebViewCore.nativeTouchUp(Native Method) at
android.webkit.WebViewCore.nativeTouchUp(Native Method) at
android.webkit.WebViewCore.access$3600(WebViewCore.java:52) at
android.webkit.WebViewCore$EventHub$1.handleMessage(WebViewCore.java:1340)
at android.os.Handler.dispatchMessage(Handler.java:99) at
android.os.Looper.loop(Looper.java:132) at
android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:723)
at java.lang.Thread.run(Thread.java:1020)
Alerts And Dialogs Class:
public class AlertsAndDialogs extends Activity
{
public final int CATEGORY_ID = 0;
. . .
//Moved to the JavaScriptInterface Class ----->
/* protected Dialog onCreateDialog(int id)
{
Dialog dialog;
switch (id)
{
case CATEGORY_ID:
AlertDialog.Builder builder;
Context mContext = this;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.dashboard_dialog, (ViewGroup) findViewById(R.id.webView));
builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
dialog = builder.create();
break;
default:
dialog = null;
}
return dialog;
}*/
}
The JavaScriptInterface Class:
public class JavaScriptInterface extends AlertsAndDialogs
{
public final int CATEGORY_ID = 0;
Context mContext;
/** Instantiate the interface and set the context */
JavaScriptInterface(Context c)
{
mContext = c;
}
. . .
/** Show the DashBoard from the web page */
public void showDashBoard()
{
showDialog(CATEGORY_ID);
}
protected Dialog onCreateDialog(int id)
{
Dialog dialog;
switch (id)
{
case CATEGORY_ID:
AlertDialog.Builder builder;
//Context mContext = this;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.dashboard_dialog, (ViewGroup) findViewById(R.id.layout_root));
builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
dialog = builder.create();
break;
default:
dialog = null;
}
return dialog;
}
. . .
}
In the Main Activity containing the WebView:
. . .
myWebView.addJavascriptInterface(new JavaScriptInterface(this), "Android");
. . .
The HTML Function:
<script type="text/javascript">
function showDashBoardFunction() {
Android.showDashBoard();
}
</script>
Try setting
View layout = inflater.inflate(R.layout.dashboard_dialog, (ViewGroup) findViewById(R.id.layout_root));
to
View layout = inflater.inflate(R.layout.dashboard_dialog, null);
I find that attaching views to a container rarely (if ever) works, and assuming "layout_root" is something to do with your activity, the Dialog won't be able to find this view anyway.
Remove from the AlertsAndDialogs Class:
protected Dialog onCreateDialog(int id)
{
Dialog dialog;
switch (id)
{
case CATEGORY_ID:
AlertDialog.Builder builder;
Context mContext = this;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.dashboard_dialog, (ViewGroup) findViewById(R.id.webView));
builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
dialog = builder.create();
break;
default:
dialog = null;
}
return dialog;
}
and add this:
public static void dashBoard(Context mContext)
{
AlertDialog.Builder builder;
Dialog dbDialog;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.dashboard_dialog, null);
builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
dbDialog = builder.create();
dbDialog.show();
}
Inside the JavaScriptInterface Class, Replace the call with:
public void showDashBoard()
{
AlertsAndDialogs.dashBoard(mContext);
}
Related
I'm creating an app with one Mainactivity and two class. It contains Listview adapter to show list of name with images and details. when click upon any image ...Alert Dialog Box will pop up and from option ,i want user could able to call or send email.
Earlier I used the code for Mainactivity class and it pretty much works but with ListviewAdapter it crashes.
Here is my Class
public class ListViewAdapter extends BaseAdapter {
// Declare Variables
Context mContext;
LayoutInflater inflater;
private List<WorldPopulation> worldpopulationlist = null;
private ArrayList<WorldPopulation> arraylist;
public ListViewAdapter(Context context,
List<WorldPopulation> worldpopulationlist) {
mContext = context;
this.worldpopulationlist = worldpopulationlist;
inflater = LayoutInflater.from(mContext);
this.arraylist = new ArrayList<WorldPopulation>();
this.arraylist.addAll(worldpopulationlist);
}
public class ViewHolder {
TextView rank;
TextView country;
TextView population;
ImageView flag;
}
#Override
public int getCount() {
return worldpopulationlist.size();
}
#Override
public WorldPopulation getItem(int position) {
return worldpopulationlist.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.listview_item, null);
// Locate the TextViews in listview_item.xml
holder.rank = (TextView) view.findViewById(R.id.rank);
holder.country = (TextView) view.findViewById(R.id.country);
holder.population = (TextView) view.findViewById(R.id.population);
// Locate the ImageView in listview_item.xml
holder.flag = (ImageView) view.findViewById(R.id.flag);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
// Set the results into TextViews
holder.rank.setText(worldpopulationlist.get(position).getRank());
holder.country.setText(worldpopulationlist.get(position).getCountry());
holder.population.setText(worldpopulationlist.get(position)
.getPopulation());
// Set the results into ImageView
holder.flag.setImageResource(worldpopulationlist.get(position)
.getFlag());
final String email = worldpopulationlist.get(position).getRank().toString();
final String phone = worldpopulationlist.get(position).getCountry().toString();
// Listen for ListView Item Click
final View finalView = view;
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
CharSequence options[] = new CharSequence[]{"Email", "Call"};
final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Select Options");
builder.setItems(options, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Click Event for each item.
if(i == 0){
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("plain/text");
intent.putExtra(Intent.EXTRA_EMAIL, new String[] { email });
intent.putExtra(Intent.EXTRA_SUBJECT, "subject");
intent.putExtra(Intent.EXTRA_TEXT, "mail body");
mContext.startActivity(Intent.createChooser(intent, ""));
}
if(i == 1){
Intent callIntent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:"+phone));
// callIntent.setData(Uri.parse("tel:"+uri));
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(callIntent);
}
}
});
builder.show();
}
});
return view;
}
// Filter Class
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
worldpopulationlist.clear();
if (charText.length() == 0) {
worldpopulationlist.addAll(arraylist);
} else {
for (WorldPopulation wp : arraylist) {
if (wp.getCountry().toLowerCase(Locale.getDefault())
.contains(charText)) {
worldpopulationlist.add(wp);
}
}
}
notifyDataSetChanged();
}
}
and error log is
Process: com.nepalpolice.test, PID: 30475
android.content.res.Resources$NotFoundException: Resource ID #0x0
at android.content.res.Resources.getValue(Resources.java:1123)
at android.content.res.Resources.loadXmlResourceParser(Resources.java:2309)
at android.content.res.Resources.getLayout(Resources.java:939)
at android.view.LayoutInflater.inflate(LayoutInflater.java:395)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at android.support.v7.app.AlertController$AlertParams.createListView(AlertController.java:988)
at android.support.v7.app.AlertController$AlertParams.apply(AlertController.java:964)
at android.support.v7.app.AlertDialog$Builder.create(AlertDialog.java:981)
at android.support.v7.app.AlertDialog$Builder.show(AlertDialog.java:1005)
at com.nepalpolice.test.ListViewAdapter$1.onClick(ListViewAdapter.java:125)
at android.view.View.performClick(View.java:4438)
at android.view.View$PerformClick.run(View.java:18422)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5018)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Please help.
Thanks in advance.
Android has its normal classes, like AlertDialog, and then it has support versions of some of those classes, one being AlertDialog. This is to provide backwards compatibility with older Android versions that may not have these classes natively. However it can get confusing sometimes.
The tutorial you linked is using an Activity and the normal AlertDialog. However, you are using an Activity and the support AlertDialog. This won't work. AlertDialog depends on a theme or style to know what it should make itself look like. Since you're using a normal Activity, the support AlertDialog is unable to infer what it should look like because Activity doesn't use support package themes.
There are a few things you can do to fix this.
The simplest way to fix this would be to just change from using the support AlertDialog to using the native one. Delete import android.support.v7.app.AlertDialog; from your Adapter class and then reimport the AlertDialog, making sure you don't import the support version again.
The second simplest way would be to follow this answer and add a specific AppCompat theme for your AlertDialog. However, this won't fix any future issues you may run into by mixing AppCompat and normal classes.
The most involved (but also most compatible) way of fixing this is to convert to using AppCompatActivity. You'll have to change your Activity to extend AppCompatActivity instead, and also change your theme (in styles.xml) to have a parent of Theme.AppCompat.Light (remove .Light if you want a dark theme).
I have an alert Dialog and I use a custom layout for this Alert Dialog, in this custom layout I have a TextView, so how can I set text for this TextView from MainActivity class?
Here is my code :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var btn_ShowAlert =findViewById<Button>(R.id.Button)
btn_ShowAlert.setOnClickListener {
txtlyric.text ="this Textview is all the problem xD "
val dialog = AlertDialog.Builder(this)
val dialogView = layoutInflater.inflate(R.layout.lyric,null)
dialog.setView(dialogView)
dialog.setCancelable(true)
dialog.show()
}
}
Initialize the widget as in your custom Dialog like this before findViewById:
txtlyric = (TextView) dialog.findViewById(R.id.yourtextviewindialog);
Then you'll be able to setText or your stuff in your custom dialog widgets.
P.s: Note that i used dialog since it's your Dialog view.
I would propose to use DialogFragment and pass necessary value into constructor
public class MyAlertDialogFragment extends DialogFragment {
public static final String TITLE = "dataKey";
public static MyAlertDialogFragment newInstance(String dataToShow) {
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putString(TITLE, dataToShow);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String mDataRecieved = getArguments().getString(TITLE,"defaultTitle");
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.alert_layout, null);
TextView mTextView = (TextView) view.findViewById(R.id.textview);
mTextView.setText(mDataRecieved);
setCancelable(false);
builder.setView(view);
Dialog dialog = builder.create();
dialog.getWindow().setBackgroundDrawable(
new ColorDrawable(Color.TRANSPARENT));
return dialog;
}
}
For more details please check here
I want to set the value of TextView in custom dialog box after I clicked in one of the fragments in Activity. Dialog was running fine with custom text view after it is being called. The problem is that it always shows NullPointerException when I tried to call changeMessageText("Hello") function.
ProgressDialogFragment.java
public class ProgressDialogFragment extends DialogFragment {
private TextView txtMessage;
private AlertDialog.Builder mBuilder;
public static ProgressDialogFragment newInstance(AlertDialog.Builder builder){
ProgressDialogFragment progressDialogFragment = new ProgressDialogFragment();
progressDialogFragment.mBuilder = builder;
return progressDialogFragment;
}
#Nullable
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View view = getLayoutInflater(savedInstanceState).inflate(R.layout.dialog_progress, null);
txtMessage = (TextView) view.findViewById(R.id.txtMessage);
changeMessageText("Hello World by default"); // this one works
mBuilder.setView(view);
return mBuilder.create();
}
public void changeMessageText(String text){
txtMessage.setText(text);
}
}
Sample Code after the button Clicked
AlertDialog.Builder builder = new AlertDialog.Builder(this);
ProgressDialogFragment progressDialogFragment = ProgressDialogFragment.newInstance(builder);
progressDialogFragment.show(getSupportFragmentManager(),"progress_dialog");
// dialog box shows until the following function is called.
progressDialogFragment.changeMessageText("Hello");
When progressDialogFragment.changeMessageText("Hello"); called, txtMessage is not created yet.
1) Add private String message; to ProgressDialogFragment.
2) Change changeMessageText
public void changeMessageText(String text){
message = text;
if(txtMessage != null){
txtMessage.setText(text);
}
}
3) add after mBuilder.setView(view);
if(message!=null && !message.isEmpty()){
txtMessage.setText(message);
}
4) Remove changeMessageText("Hello World by default"); in onCreateDialog
And. It Doesn't Work for Me.
View view = getLayoutInflater(savedInstanceState).inflate(R.layout.dialog_progress, null);
I change it.
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.dialog_progress, null);
Hope it will help you.
i am having an custom alert view which pop ups on a button click event.all the things are going fine.but the problem is:
if user clicks outside alert dialog it disappear.i want to restrict user for clicking out side.I am giving him the choice of cancel/cross button to close alert dialog.
so how to restrict user clicking outside the alert box?
code:
the code in onCreate for button click where i am calling show dialog:
final Button cdButton = (Button) findViewById(R.id.denonCdImage);
cdButton.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v)
{
showDialog(CD_CATG_ID);
}
});
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder;
Context mContext = this;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.categorydialog,(ViewGroup) findViewById(R.id.layout_root));
GridView gridview = (GridView)layout.findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
/** Check the id for the device type for image tobe change */
switch(id) {
case 1 : // for the cd image
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,final int position, long id) {
Toast.makeText(view.getContext(), "Image selected for CD", 3000).show();
cdImageId = getImageId(position);
int elementId = getApplicationContext().getResources().getIdentifier(cdImageId, "drawable", getPackageName());
cdImageView.setImageResource(elementId);
Log.d("CdImageid", ""+cdImageId);
closeDialog(view);
}
});
builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
dialog = builder.create();
break;
default:
dialog = null;
}
/** onclick listner for the close button */
ImageView close = (ImageView) layout.findViewById(R.id.close);
close.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){
dialog.dismiss();
}
});
return dialog;
}
any suggestions?
thanks!
There are two methods concerning this behaviour: setCancelable() and setCanceledOnTouchOutside() as you can see in the reference.
I've come across an issue which I've never had before. I have a Fragment containing a button. This button (ViewBookingButton) shows a popup dialog. When the dialog opens I would like to set a string in an EditText (AllBooking). Unfortunately it crashes and shows NullPointerExecption. What is going wrong? Here is my code:
ViewBookingButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
AlertDialog.Builder ViewBookingHelpBuilder = new AlertDialog.Builder(getActivity());
ViewBookingHelpBuilder.setTitle("view booking:");
LayoutInflater inflater = getActivity().getLayoutInflater();
View DialogLayout = inflater.inflate(R.layout.view_booking, null);
ViewBookingHelpBuilder.setView(DialogLayout);
TextView AllBooking = (TextView)view.findViewById(R.id.AllBooking);
AllBooking.setText("Hello World");//WHEN I REMOVE THIS THE DIALOG WORKS
ViewBookingHelpBuilder.setPositiveButton("Done", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which)
{
}
});
AlertDialog helpDialog = ViewBookingHelpBuilder.create();
helpDialog.show();
}
});
Change this
TextView AllBooking = (TextView)view.findViewById(R.id.AllBooking);
to
TextView AllBooking = (TextView)DialogLayout.findViewById(R.id.AllBooking);
TextView belongs to the inflated layout and `findViewById looks for the view in the current view hierarchy.