I've gotten my app to download content from a website but the intent asks you to open the link in the browser and downloads it from there. I wish to change that so when i tap the download button, instead of the intent directing to the browser it opens a popup in my app and shows the download progress.
How am I able to achieve this?
I have searched around stackoverflow and have only found ways that don't work for me. Here is my code -
txtLink = (EditText) findViewById(R.id.input_package);
btnOpenLink = (ImageButton) findViewById(R.id.download);
btnOpenLink.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String page = txtLink.getText().toString();
if (!TextUtils.isEmpty(page)) {
Uri uri = Uri.parse(defaultLink + page);
// Success Toast
LayoutInflater inflater = getLayoutInflater();
// Inflate the Layout
View layout = inflater.inflate(R.layout.custom_toast, null);
TextView text = (TextView) layout.findViewById(R.id.textToShow);
// Set the Text to show in TextView
text.setText("Your download should start shortly");
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.FILL_HORIZONTAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
} else {
// Fail Toast
LayoutInflater inflater = getLayoutInflater();
// Inflate the Layout
View layout = inflater.inflate(R.layout.custom_toast, null);
TextView text = (TextView) layout.findViewById(R.id.textToShow);
// Set the Text to show in TextView
text.setText("Please enter a package name");
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.FILL_HORIZONTAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
}
}
});
Could someone explain what is the best way to create a popup download progress?
Because i have an input field where one can enter the second part of the url and it downloads that. Eg- download.com/ but the user enters "download" so when he taps the button it changes to download.com/download and it downloads from that url.
Thanks
You can do something like this..
public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
private ProgressDialog mProgressDialog;
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_DOWNLOAD_PROGRESS:
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("waiting 5 minutes..");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
return mProgressDialog;
default:
return null;
}
}
Then write an async task to update progress..
private class DownloadZipFileTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(DIALOG_DOWNLOAD_PROGRESS);
}
#Override
protected String doInBackground(String... urls) {
//Copy you logic to calculate progress and call
publishProgress("" + progress);
}
protected void onProgressUpdate(String... progress) {
mProgressDialog.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected void onPostExecute(String result) {
dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
}
}
Write your download logic under the doInBackground method of Asynctask.This should solve your purpose and it wont even block UI tread..
Related
I've been searching around and tried different solutions but I can't seem to get this to work.
I have a MainActivity with a list and an "Add" button. When i click the addbutton i open a DialogFragment. In the dialog user inputs data and press "add" and i want a notification that says "xxxx has been added to list" but it never shows.
I have a seperate class for AddDialog which looks like this:
public class AddDialogFragment extends DialogFragment {
Button btnAdd;
Button btnCancel;
TextView etNewSerial, etNewBrand, etNewModel;
String newSerial, newBrand, newModel;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.dialog_add, container, false);
getDialog().setTitle("Add new serial!");
btnAdd = (Button) rootView.findViewById(R.id.btnAddNew);
etNewSerial = (TextView) rootView.findViewById(R.id.etNewSerial);
etNewBrand = (TextView) rootView.findViewById(R.id.etNewBrand);
etNewModel = (TextView) rootView.findViewById(R.id.etNewModel);
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
newSerial = etNewSerial.getText().toString();
newBrand = etNewBrand.getText().toString();
newModel = etNewModel.getText().toString();
String url = "MY_VOLLEY_URL"
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
int icon = 0;
CharSequence notiText = "Item Added!";
long notiTime = System.currentTimeMillis();
CharSequence notiTitle = "Item Added!";//Titel
CharSequence notiContent = newSerial + " added!";
PendingIntent pendingIntent = PendingIntent.getActivity(getActivity(), 0, new Intent(), PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notBuilder = new NotificationCompat.Builder(getActivity());
notBuilder.setSmallIcon(icon)
.setTicker(notiText)
.setWhen(notiTime)
.setAutoCancel(true)
.setContentText(notiContent)
.setContentTitle(notiTitle)
.setContentIntent(pendingIntent);
Notification notification = notBuilder.build();
NotificationManager myNotificationManager = (NotificationManager)getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
myNotificationManager.notify(1, notification);
getDialog().dismiss();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
Volley.newRequestQueue(getActivity()).add(request);
}
});
return rootView;
}
}
But the notification never shows. I've been trying to replace the "getActivity()" with different methods for context but it doesn't seem to matter. Does anyone has some tips to make this possible?
I wonder you are getting this error because your are passing 0 as the resourceId for the small icon (setSmallIcon). Maybe, NotificationManager is ignoring this notification since it can not built properly (there's no resource with 0 as ID.
So, try to change this:
notBuilder.setSmallIcon(icon)
....
To:
notBuilder.setSmallIcon(android.R.color.transparent)
....
I use android.R.color.transparent as example since you are not interested in show any icon anyway. But you can change to any color/drawable etc...
I want create content application, i load data from JSON and when users click on button save this content into SQLitedatabase.
I want use this library for button.
And for checkable button, I use this code
I write below codes, when click on button i save this content into SQLitedatabase, but i can't save button sate into SharedPreferences!
When click on button (boolean checked) button is turn on, and when click again on the button turn off this button.
I want when click on button, turn on this button and save in SharedPreferences and when go to other activity and again back this activity, see turn on this button NOT turn off. when click again this button at that time turn off button!
Activity codes:
private ShineButton postShow_favPost;
private String favData = "FavPrefsList";
private Boolean favState;
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.post_show_page);
bindActivity();
//Give Data
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
title = bundle.getString("title");
image = bundle.getString("image");
content = bundle.getString("content");
dateTime = bundle.getString("dateTime");
author = bundle.getString("author");
category = bundle.getString("category");
categoryID = bundle.getString("categoryID");
}
mAppBarLayout.addOnOffsetChangedListener(this);
//// Save Fav state
final SharedPreferences saveFavPrefs = getSharedPreferences(favData, MODE_PRIVATE);
final SharedPreferences.Editor editor = saveFavPrefs.edit();
favState = saveFavPrefs.getBoolean("isChecked", false);
postShow_favPost = (ShineButton) mToolbar.findViewById(R.id.post_FavImage);
postShow_favPost.init(this);
postShow_favPost.setOnCheckStateChangeListener(new ShineButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(View view, boolean checked) {
if (checked == true) {
editor.putBoolean("isChecked", true);
editor.commit();
//////////// Database
favDB = new FavHelper(context);
long addNewFAV = favDB.insertFAV(title, image, content, dateTime, author, category);
if (addNewFAV < 0) {
TastyToast.makeText(context, "Not save in database", TastyToast.LENGTH_LONG, TastyToast.ERROR);
} else {
TastyToast.makeText(context, "Save in database", TastyToast.LENGTH_LONG, TastyToast.SUCCESS);
}
////////////////////
} else {
editor.putBoolean("isChecked", false);
editor.commit();
Toast.makeText(context, "Checked False", Toast.LENGTH_SHORT).show();
}
}
});
How can i fix my issue ?
Well you need to save the state when you click the button.
For example :
postShow_favPost.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (postShow_favPost.isChecked()){
editor.putBoolean("isChecked", true);
editor.apply();
}
else{
editor.putBoolean("isChecked", false);
editor.apply();
}
}
});
Then you have to load it in your onCreate():
#Override
protected void onCreate(Bundle savedInstanceState)
{
SharedPreferences saveFavPrefs = getSharedPreferences(favData, MODE_PRIVATE);;
postShow_favPost.setChecked(saveFavPrefs.getBoolean("isChecked", true));
}
Maybe this example will help you.
EDIT
Ok let's presume in your f function you just finished doing whatever you're doing to your database, after that, set the state as on or off, let's say you want on.
So :
public void loadPrefs(SharedPreferences prefs){
favState = prefs.getBoolean("isChecked",false);
}
public void f(SharedPreferences.Editor editor){
//database stuff
editor.putBoolean("isChecked", true); // or false
editor.apply();
loadPrefs(prefs);
// in here your state will be saved for your button as soon as you
finish working with your database, after that in your onResume() you
may change that state to false(off) in case you want it just for that post
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I have a function which creates a button, which has an onClick event to bring up a custom dialog which just shows some information from the functions parameters. The dialog has two buttons on it as well, one to close the dialog, and one to add information to a file.
When I try to set onClick events for those buttons, the app crashes, and the error I get is a NullPointerException which says that I am trying to invoke a virtual method on a null object reference.
If I comment out the part where I set the onClickEventListener code for both buttons, then the dialog appears as normal, with the buttons on it.
Note: context is a variable declared in the class. It is simply Context context = this
Code is below:
public void addButton(String text, int id, String areas, String details, String notes) {
Button button = new Button(this);
final String title = "Add "+text;
final String dName = text;
final String dAreas = areas;
final String dDetails = details;
final String dNotes = notes;
button.setText(text);
button.setTextColor(ContextCompat.getColor(context, R.color.buttonText));
button.setTextSize(32);
button.setId(id);
if (isEven(id+1)) {
button.setBackgroundResource(R.drawable.buttonshapeother);
} else {
button.setBackgroundResource(R.drawable.buttonshape);
}
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Make custom dialog
final Dialog dialog = new Dialog(context);
Button add = (Button) dialog.findViewById(R.id.btnAddExer);
Button cancel = (Button) dialog.findViewById(R.id.btnCancel);
dialog.setContentView(R.layout.popup_exercise);
dialog.setTitle(title);
// Set the custom components now
TextView tName = (TextView) dialog.findViewById(R.id.lblNameData);
TextView tAreas = (TextView) dialog.findViewById(R.id.lblAreaData);
TextView tDetails = (TextView) dialog.findViewById(R.id.lblDetailsData);
TextView tNotes = (TextView) dialog.findViewById(R.id.lblNotesData);
tName.setText(dName);
tAreas.setText(dAreas);
tDetails.setText(dDetails);
tNotes.setText(dNotes);
// Add functions to buttons
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (addExercise(dName, dAreas, dDetails, dNotes)) { // Add exercise to user's workout
Toast.makeText(context, "Exercise was added to your workout", Toast.LENGTH_LONG).show();
dialog.dismiss(); // Close dialog
} else {
Toast.makeText(context, "There was an error adding your exercise", Toast.LENGTH_LONG).show();
}
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss(); // Close dialog
}
});
dialog.show(); // Actually show the dialog
}
});
LinearLayout lay = (LinearLayout) findViewById(R.id.innerLay);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lay.addView(button, params);
}
public boolean isEven(int num) {
if ((num&1) == 0) {
return true;
} else {
return false;
}
}
Because you are trying to find button view before setting the layout to it. So try like this:
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.popup_exercise);
dialog.setTitle(title);
Button add = (Button) dialog.findViewById(R.id.btnAddExer);
Button cancel = (Button) dialog.findViewById(R.id.btnCancel);
I've got an inputDialog, which allows for some text inputs. On clicking save, the inputDialog checks if the entered text is already available (to prevent double entries). If this is the case, a new AlertDialog is created, simply stating "The value you entered already exists", with just an "Ok" button to dismiss this AlertDialog. This all works.
I would like to have the inputDialog pop back up again, after dismissing the AlertDialog, with the values that were entered by the user before still in the editText fields.
I'm not expecting any problems on getting those values back in the editText fields (Store them in a variable on clicking save, if the double entry error occurs, set those variables on the editText's. If I'm doing this in a stupid way, please let me know).
I am however having trouble with getting the first (inputDialog) dialog to come back. The code you see below is the code for my inputDialog fragment (The code is simplified, so if something seems to be missing, it probably is. Let me know, so I can add it back in.)
So, to repeat myself: How can I return to the previous dialog after dismissing the second one?
StuffManagerInputDialogFragment.java:
public class StuffManagerInputDialogFragment extends DialogFragment {
EditText nameInputField;
EditText tagInputField;
DBHandler dbHandler;
StuffManagerFragment f = new StuffManagerFragment();
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
final View v_iew = inflater.inflate(R.layout.fragment_inputdialog, null);
nameInputField = (EditText) v_iew.findViewById(R.id.inputdialogname);
tagInputField = (EditText) v_iew.findViewById(R.id.inputdialogtag);
dbHandler = new DBHandler(getActivity(), null, null, 1);
final MainActivity ma = (MainActivity) getActivity();
final AlertDialog.Builder newLinkDialog = new AlertDialog.Builder(getActivity());
newLinkDialog.setView(v_iew)
.setTitle("New Link")
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String nameInputFieldText = nameInputField.getText().toString();
String tagInputFieldText = tagInputField.getText().toString();
ArrayList<String> nameArray = dbHandler.nameArrayMethod();
ArrayList<String> tagArray = dbHandler.tagArrayMethod();
NavigationView navigationView = (NavigationView) getActivity().findViewById(R.id.nav_view);
Menu menu = navigationView.getMenu();
if (nameArray.contains(nameInputFieldText) || tagArray.contains(tagInputFieldText)) {
if (nameArray.contains(nameInputFieldText) && tagArray.contains(tagInputFieldText)) {
AlertDialog.Builder errorBoth = new AlertDialog.Builder(getActivity())
.setTitle("Error")
.setMessage("The name and tag you entered are already in use.")
.setIcon(R.drawable.ic_error_black)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//Return to previous dialog here
}
});
errorBoth.show();
}
} else {
dbHandler.addLink(nameInputFieldText, tagInputFieldText);
nameArray = dbHandler.nameArrayMethod();
int nameArraySize = (nameArray.size() - 1);
MenuItem item = menu.add(R.id.group1, nameArraySize, 1, nameArray.get(nameArraySize));
Toast.makeText(getContext(), "'" + nameInputFieldText + " - " + tagInputFieldText + "' link saved.", Toast.LENGTH_SHORT).show();
ma.addSMVFFragments();
f.hideDeleteAllButton = false;
getActivity().invalidateOptionsMenu();
}
}
})
.setNegativeButton("Cancel", null);
return newLinkDialog.create();
}
}
A better solution is to have a dialog fragment for your input layout, and that dialog fragment would display an AlertDialog on OK if the text validation fails. The input dialog fragment would not dismiss in this case, it will remain in the background so when you dismiss the alert dialog to tell the user the input is invalid, you return to the input dialog as it was.
To prevent the dialog fragment from dismissing on OK you would override onStart and get a reference to the OK button and set the listener there, like this:
#Override
public void onStart() {
super.onStart();
AlertDialog alertDialog = (AlertDialog) getDialog();
if (alertDialog != null) {
mOKButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
mOkButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (field OK) {
// save data
dismiss();
} else {
// show error dialog
}
}
});
}
}
I am trying to add some text validation to an edit text field located within an alert dialog box. It prompts a user to enter in a name.
I want to add some validation so that if what they have entered is blank or null, it does not do anything apart from creating a Toast saying error.
So far I have:
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Record New Track");
alert.setMessage("Please Name Your Track:");
// Set an EditText view to get user input
final EditText trackName = new EditText(this);
alert.setView(trackName);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String textString = trackName.getText().toString(); // Converts the value of getText to a string.
if (textString != null && textString.trim().length() ==0)
{
Context context = getApplicationContext();
CharSequence error = "Please enter a track name" + textString;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, error, duration);
toast.show();
}
else
{
SQLiteDatabase db = waypoints.getWritableDatabase();
ContentValues trackvalues = new ContentValues();
trackvalues.put(TRACK_NAME, textString);
trackvalues.put(TRACK_START_TIME,tracktimeidentifier );
insertid=db.insertOrThrow(TRACK_TABLE_NAME, null, trackvalues);
}
But this just closes the Alert Dialog and then displays the Toast. I want the Alert Dialog to still be on the screen.
Thanks
I think you should recreate the Dialog, as it seems the DialogInterface given as a parameter in onClick() doesn't give you an option to stop the closure of the Dialog.
I also have a couple of tips for you:
Try using Activity.onCreateDialog(), Activity.onPrepareDialog() and of course Activity.showDialog(). They make dialog usage much easier (atleast for me), also dialog usage looks more like menu usage. Using these methods, you will also be able to more easilty show the dialog again.
I want to give you a tip. It's not an answer to your question, but doing this in an answer is much more readable.
Instead of holding a reference to an AlertDialog.Builder() object, you can simply do:
new AlertDialog.Builder(this)
.setTitle("Record New Track")
.setMessage("Please Name Your Track:")
//and some more method calls
.create();
//or .show();
Saves you a reference and a lot of typing ;). (almost?) All methods of AlertDialog.Builder return an AlertDialog.Builder object, which you can directly call a method on.
The same goes for Toasts:
Toast.makeText(this, "Please enter...", Toast.LENGTH_LONG).show();
I make a new method inside my class that shows the alert and put all the code for creating the alert in that one method. then after calling the Toast I call that method. Say I named that method createAlert(), then I have,
createAlert(){
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Record New Track");
alert.setMessage("Please Name Your Track:");
// Set an EditText view to get user input
final EditText trackName = new EditText(this);
alert.setView(trackName);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String textString = trackName.getText().toString(); // Converts the value of getText to a string.
if (textString != null && textString.trim().length() ==0)
{
Context context = getApplicationContext();
CharSequence error = "Please enter a track name" + textString;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, error, duration);
toast.show();
createAlert();
}
else
{
SQLiteDatabase db = waypoints.getWritableDatabase();
ContentValues trackvalues = new ContentValues();
trackvalues.put(TRACK_NAME, textString);
trackvalues.put(TRACK_START_TIME,tracktimeidentifier );
insertid=db.insertOrThrow(TRACK_TABLE_NAME, null, trackvalues);
}
}
What you should do is to create a custom xml layout including a textbox and an Ok button instead of using .setPositiveButton.
Then you can add a click listener to your button in order to validate the data and dismiss the dialog.
It should be used in CreateDialog:
protected Dialog onCreateDialog(int id)
{
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (id==EDIT_DIALOG)
{
final View layout = inflater.inflate(R.layout.edit_dialog, (ViewGroup) findViewById(R.id.Layout_Edit));
final Button okButton=(Button) layout.findViewById(R.id.Button_OkTrack);
final EditText name=(EditText) layout.findViewById(R.id.EditText_Name);
okButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v) {
String textString = trackName.getText().toString();
if (textString != null && textString.trim().length() ==0)
{
Toast.makeText(getApplicationContext(), "Please enter...", Toast.LENGTH_LONG).show();
} else
removeDialog(DIALOG_EDITTRACK);
}
});
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(layout);
builder.setTitle("Edit text");
AlertDialog submitDialog = builder.create();
return submitDialog;
}
Even though it's an old post, the code below will help somebody. I used a customized layout and extended DialogFragment class.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Get the layout inflater
LayoutInflater inflater = requireActivity().getLayoutInflater();
final View view = inflater.inflate(R.layout.Name_of_the_customized_layout, null);
final EditText etxtChamp = view.findViewById(R.id.editText);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Enter a Name")
.setTitle("Mandatory field ex.");
builder.setView(view);
final Button btnOk = view.findViewById(R.id.ok);
final Button btnCancel = view.findViewById(R.id.cancel);
btnOk.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(etxtChamp.getText().toString().isEmpty()){
etxtChamp.setError("Oups! ce champ est obligatoire!");
}else{
//Get the editText content and do whatever you want
String messageEditText = etxtChamp.getText().toString();
dismiss();
}
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dismiss();
}
});
return builder.create();
}
Use This code for displaying Dialog.
public void onClick(DialogInterface dialog, int whichButton) {
String textSt`enter code here`ring = trackName.getText().toString(); // Converts the value of getText to a string.
if (textString != null && textString.trim().length() ==0)
{
Context context = getApplicationContext();
CharSequence error = "Please enter a track name" + textString;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, error, duration);
toast.show();
new AlertDialog.Builder(this)
.setTitle("Message")
.setMessage("please enter valid field")
.setPositiveButton("OK", null).show();
}
This will create a Dialog for you, editText is empty or what are conditions you wants.
//if view is not instantiated,it always returns null for edittext values.
View v = inflater.inflate(R.layout.new_location_dialog, null);
builder.setView(v);
final EditText titleBox = (EditText)v.findViewById(R.id.title);
final EditText descriptionBox = (EditText)v.findViewById(R.id.description);