I'm trying to retrive data using WiFi but the application is crashing. When I use the localHost Emulator it is working just fine but when I use mobile data or WiFi it crashes. I can save data to MySql on localhost using WiFi but I just cant receive the data. Some of the time I get android.os.NetworkonMainThreadException. I'm a very new programmer just borrowed most of the code and need to clearly state how this can be resolved.
/**
* Background Async Task to Get complete User details
* */
class GetUserDetails extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading details. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
/**
* Getting User details in background thread
* */
protected String doInBackground(String... params) {
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
// Check for success tag
int success;
try {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("user_ID", "2"));
// getting User details by making HTTP request
// Note that User details url will use GET request
JSONObject json = jsonParser.makeHttpRequest(
LOGIN_URL, "GET", params);
// check your log for json response
Log.d("Single User Details", json.toString());
// json success tag
success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// successfully received User details
JSONArray UserObj = json
.getJSONArray(TAG_User); // JSON Array
// get first User object from JSON Array
JSONObject User = UserObj.getJSONObject(0);
// User with this pid found
// Edit Text
txtlname = (EditText) findViewById(R.id.editText1);
txtfname = (EditText) findViewById(R.id.editText2);
// display User data in EditText
txtfname.setText(User.getString(TAG_FNAME));
txtlname.setText(User.getString(TAG_LNAME));
}else{
// User with pid not found
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
// dismiss the dialog once got all details
pDialog.dismiss();
}
}
Actually you shouldn't connect to internet in UI thread.
You connected to internet through JSONObject json = jsonParser.makeHttpRequest(
LOGIN_URL, "GET", params); in runOnUiThread( new Runnable.....
/**
* Background Async Task to Get complete User details
* */
class GetUserDetails extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading details. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
/**
* Getting User details in background thread
* */
protected String doInBackground(String... params) {
// updating UI from Background Thread
// Check for success tag
int success;
try {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("user_ID", "2"));
// getting User details by making HTTP request
// Note that User details url will use GET request
JSONObject json = jsonParser.makeHttpRequest(
LOGIN_URL, "GET", params);
// check your log for json response
Log.d("Single User Details", json.toString());
// json success tag
success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// successfully received User details
JSONArray UserObj = json
.getJSONArray(TAG_User); // JSON Array
// get first User object from JSON Array
final JSONObject User = UserObj.getJSONObject(0);
runOnUiThread(new Runnable() {
public void run() {
// User with this pid found
// Edit Text
txtlname = (EditText) findViewById(R.id.editText1);
txtfname = (EditText) findViewById(R.id.editText2);
// display User data in EditText
txtfname.setText(User.getString(TAG_FNAME));
txtlname.setText(User.getString(TAG_LNAME));
}
});
}else{
// User with pid not found
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
// dismiss the dialog once got all details
pDialog.dismiss();
}
}
As you can see I just returned to UI thread when I want to work with views (like text views). Pay attention to user variable. I made it final to make it reachable inside the Runnable object I used as the parameter of runOnUiThread method.
You shouldn't execute UI related code in doInBackground, you should move UI related code to onPostExecute or onProgressUpdate methods of your AsyncTask.
This answer might help you:
Android : Calling the methods on UI thread from AsyncTask doInBackground method
Related
I have a video downloader android application It's allow people to download videos from twitter and Something has changed in 2 months Downloaded videos are not playable on Android version <= 6.0 Error is : "Can't Play This Video" Some of these videos playable but most of it is not. same format mp4.
I didn't make any changes in my code. I tried download files manually from browser and still error is occurs.
// Progress Dialog
private ProgressDialog pDialog;
public static final int progress_bar_type = 0;
// File url to download
private static String file_url = "https://video.twimg.com/ext_tw_video/1122253815884001280/pu/vid/1280x720/xTTWb4wnRMvFzpXk.mp4";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DownloadFileFromURL().execute(file_url);
}
/**
* Showing Dialog
* */
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case progress_bar_type: // we set this to 0
pDialog = new ProgressDialog(this);
pDialog.setMessage("Downloading file. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setMax(100);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(true);
pDialog.show();
return pDialog;
default:
return null;
}
}
/**
* Background Async Task to download file
* */
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Bar Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(progress_bar_type);
}
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
int lenghtOfFile = conection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream(),
8192);
// Output stream
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/2011.mp4");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
/**
* Updating progress bar
* */
protected void onProgressUpdate(String... progress) {
// setting progress percentage
pDialog.setProgress(Integer.parseInt(progress[0]));
}
/**
* After completing background task Dismiss the progress dialog
* **/
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
dismissDialog(progress_bar_type);
}
}
I want to make these videos playable as others. Some of the mp4 videos plable and most of its is not. I don't know the reason is codec or not but I want to make these playable too.
This videos is example of situation.
https://video.twimg.com/ext_tw_video/1122253815884001280/pu/vid/1280x720/xTTWb4wnRMvFzpXk.mp4
Your example video uses H.264 profile of High #Level 3. Not supported in Android version <= 6.
H.264 is the "image" format of the video (where audio is MP3/AAC).
Lowest-to-high Profie order is: Baseline --> Main --> High.
See docs: https://developer.android.com/guide/topics/media/media-formats#video-codecs
MediaInfo analysis:
Video
ID : 1
Format : AVC
Format/Info : Advanced Video Codec
Format profile : High#L3.1
Normally you fix by offering alternate encodings of the video file from your site. Since you're not in charge of Twitter server, you'll have to check if Twitter itself is keeping any Low/Standard-Def versions of uploaded videos, for older devices that can't handle High-Def. If found, then just offer users a multiple choice of "quality" links.
Alternatively try to see if FFmpeg can play the format. Try VLC Player app (is FFmpeg powered) on a problematic device. If it plays okay, then try importing Android-FFmpeg into your app code, where you use it to decode/play the downloaded videos in your app.
I got some trouble using the asynctask to query in my cloud database.
Due the response delay to query I cant get the result correctly. Getting NULL.
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
this.mBox = new Box();
super.onCreate(savedInstanceState);
setContentView(R.layout.novomenu_layout);
InicializaAzure(); // init connection to azure mobile service
this.mPalletDao = new PalletDAO(this);
this.mBoxDao = new BoxDAO(this);
mBox = mBoxDao.AzureGetBoxById(1); // query the cloud database
}
BoxDAO.java
public Box AzureGetBoxById(final long id){
final Box[] box = new Box[1];
final boolean[] flag = {false};
new AsyncTask<Void, Void, Void>() {
private ProgressDialog pDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(mContext);
pDialog.setMessage("Just a moment...");
pDialog.setIndeterminate(true);
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
try {
final MobileServiceList<Box> result = mBoxTable.where().field("id").eq(id).execute().get();
Box mBox = result.get(0);
box[0] = mBox;
} catch (Exception exception) {
//createAndShowDialog(exception, "Error");
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
pDialog.dismiss();
flag[0] = true;
}
}.execute();
return box[0];
//return null;
}
I am getting always NULL until the asynctask has finished. but I need the result in the same time.
How can I solve that? I've searched about asynctask but I didnt find anything like this.
Thank you.
Your code is correct, and it works fine. However, if you want to get the result to show in the same time of UI displayed, you can not solve it easily by using the asynctask.
Per my experience, there are two ways can help solve that.
Remove the asynctask code and use the sync method to get data, but it will cause UI hang so that it not be recommended.
Use MobileServiceSyncTable to enable offline sync to solve it.
There is a sample doc https://azure.microsoft.com/en-us/documentation/articles/mobile-services-android-get-started-offline-data/ to help adding offline data sync into your app.
You alse can watch some vedio to learn it, please move to http://channel9.msdn.com/Shows/Cloud+Cover/Episode-155-Offline-Storage-with-Donna-Malayeri and http://azure.microsoft.com/documentation/videos/azure-mobile-services-offline-enabled-apps-with-donna-malayeri/.
My loging async task does the login process, it takes the user input, send it via webservices, verify it, and sends a session id if the user login detail was correct, and returns nothing and also an error if the user login details were wrong, I'm trying to show an alert dialog if the user login details were wrong, my logic is to have an IF statement in onPostExecute that checks if session id field is null or not, if null, it shows an alert dialog and prevent the user from logging in, THIS WORKS, however my issue is that even when the user enters the right detail, it shows the alert dialog box very quickly(flashes), and then directs me to the dashboard, I don't want that alert dialog to show even if it was for seconds, I think that it doesn't ready my IF statement
Thats my Login.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_login);
LB = (Button) findViewById(R.id.loginbutton);
LB.setOnClickListener(this);
}
public void onClick(View view){
switch (view.getId()){
case R.id.loginbutton: //When login button is clicked
new LongOperation().execute(""); //Starts the method called LongOperation
break;
}
}
public class LongOperation extends AsyncTask<String, Void, String>{ //string, void, string was added automatically
#Override
protected void onPreExecute() {
super.onPreExecute();
pdia = new ProgressDialog(Login.this);
pdia.setMessage("Loading...");
pdia.show();
}
#Override
protected String doInBackground(String... params) {
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
Editor editor = pref.edit();
editor.clear();
editor.commit();
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
usersusername = (EditText)findViewById(R.id.editusername);
userspassword = (EditText)findViewById(R.id.editpassword);
String user_Name = usersusername.getText().toString();
String user_Password = userspassword.getText().toString();
editor.putString("username",user_Name);
editor.commit();
PropertyInfo unameProp =new PropertyInfo();
unameProp.setName("userName");//Define the variable name in the web service method
unameProp.setValue(user_Name);//set value for userName variable
unameProp.setType(String.class);//Define the type of the variable
request.addProperty("username",user_Name);//Pass properties to the variable
//Using this to add parameters "username" grabbed from WSDL
PropertyInfo passwordProp =new PropertyInfo();
passwordProp.setName("password");
passwordProp.setValue(user_Password);
passwordProp.setType(String.class);
request.addProperty(passwordProp);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); // Declare the version of the soap request
envelope.setOutputSoapObject(request);
try {
HttpTransportSE aht = new HttpTransportSE(URL);
aht.call(SOAP_ACTION, envelope);
SoapPrimitive result =(SoapPrimitive)envelope.getResponse();
String SessionID= result.toString();
if (!TextUtils.isEmpty(SessionID))
{
Intent intent = new Intent(Login.this,Dashboard.class);
startActivity(intent);
}
}
catch (Exception e){
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String Something) {
pdia.dismiss();
super.onPostExecute(Something);
if(usersusername.getText().length()==0) {
usersusername.setError("Please enter your username");
}
if(userspassword.getText().length()==0) {
userspassword.setError("Please enter your password");
}
if(Something == null) {
Builder builder = new Builder(Login.this);
builder.setMessage("Invalid login details");
builder.setPositiveButton(R.string.ok_button, null);
builder.create().show();
// show dialog and prepare the fields for retry
}
}
}
}
In your webservice create a checker, like an integer success where if its 1 it successfully queried but if 0 it didn't query. Retrieve it in your asynctask then check in post execute if success == 1 go to dashboard if success == 0 call dialog.
Btw try using the new android Volley for networking as AsyncTask is prone to memory leaks. Cheers! :)
I am using this code to load data from online database to my android application .
I am wondering what can i add to make this code better ?
Sometimes the progress dialog keeps spinning and never gets the data, the application is stuck then, any ideas on how i can prevent that ?
class LoadAllSections extends AsyncTask<String, String, String>
{
// make a progress dialog appear with the selected specifics
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading all sections, please wait");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
// in the background run this code to retrieve data from the server
protected String doInBackground(String... args)
{
List<NameValuePair> params = new ArrayList<NameValuePair>();
JSONObject json = jParser.makeHttpRequest(url_Sections,"POST", params);
try
{
int success = json.getInt(TAG_SUCCESS);
sections = json.getJSONArray(TAG_SECTIONS);
if (success == 1)
{
for (int i = 0; i < sections.length(); i++)
{
JSONObject c = sections.getJSONObject(i);
section_id = c.getString(TAG_SECTION_ID);
section_name = c.getString(TAG_SECTION_NAME);
section_desc = c.getString(TAG_SECTION_DESC);
section_image = c.getString(TAG_SECTION_IMAGE);
section_valid = c.getString(TAG_SECTION_VALID);
HashMap <String,String> sectionmap = new HashMap<String,String>();
sectionmap.put(TAG_SECTION_ID, section_id);
sectionmap.put(TAG_SECTION_NAME, section_name);
sectionmap.put(TAG_SECTION_DESC, section_desc);
sectionmap.put(TAG_SECTION_IMAGE, section_image);
sectionmap.put(TAG_SECTION_VALID, section_valid);
sectionlist.add(sectionmap);
}
}
else
{
finish();
}
}
catch (JSONException e)
{
e.printStackTrace();
}
return null;
}
// disable the progress dialog and load data to the gridview
protected void onPostExecute(String file_url)
{
pDialog.dismiss();
adapter=new SectionAdapter(MainActivity.this,sectionlist);
SectionsGridView.setAdapter(adapter);
}
}
I wanted to add a comment, but I am not allowed to.
Don't have enough reputation :-(
Pass url_section as argument to doInBackground instead of making it global.
I would place the httpRequest insde a try catch block.
Did you set the timeout, if the httpRequest is not answering? I would set that to
60 seconds. I think by default this is set to 600 seconds.
Why do you pass the file_url to onPostExecute instead of passing the
sectionList?
Take a look at AsyncTask. If you don't want to pass anything between the methods, you can also use Void. So in your case AsyncTask would also do it.
First, i already know how to download, i can show the progress bar, but i cannot switch activity, by default of the download code, when download reach 100% ,it will dismiss the dialogue and remain on that page/layout, i want it to download, and then move to next activity not staying where it is.. So i added a runnable code to change activity after 2seconds of complete download, but it just move to next activity after 2seconds even when download does not excecute.. Help me check the code, and tell me what to do. Thanks
public class ClockWorkMod extends Activity {
// button to show progress dialog
Button btnShowProgress;
// Progress Dialog
private ProgressDialog pDialog;
ImageView my_image;
// Progress dialog type (0 - for Horizontal progress bar)
public static final int progress_bar_type = 0;
// File url to download
private static String file_url = "http://api.loadedgeek.com/myupgrade/clockworkmod.img";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.clockworkmod);
// show progress bar button
btnShowProgress = (Button) findViewById(R.id.btnProgressBar);
// Image view to show image after downloading
/**
* Show Progress bar click event
* */
btnShowProgress.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// starting new Async Task
new DownloadFileFromURL().execute(file_url);
}
});
}
/**
* Showing Dialog
* */
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case progress_bar_type: // we set this to 0
pDialog = new ProgressDialog(this);
pDialog.setMessage("Installing ClockWorkMod. Please Wait...");
pDialog.setIndeterminate(false);
pDialog.setMax(100);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(true);
pDialog.show();
return pDialog;
default:
return null;
}
}
/**
* Background Async Task to download file
* */
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread
* Show Progress Bar Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(progress_bar_type);
}
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// this will be useful so that you can show a tipical 0-100% progress bar
int lenghtOfFile = conection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream
OutputStream output = new FileOutputStream("/sdcard/MyUpgrade/clockworkmod.img");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress(""+(int)((total*100)/lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
/**
* Updating progress bar
* */
protected void onProgressUpdate(String... progress) {
// setting progress percentage
pDialog.setProgress(Integer.parseInt(progress[0]));
}
/**
* After completing background task
* Dismiss the progress dialog
* **/
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
dismissDialog(progress_bar_type);
new Handler().
postDelayed(new Runnable() {
#Override
public void run() {
Intent i= new Intent(ClockWorkMod.this, ClockWorkModFlash.class);
startActivity(i);
}
}, 2000);
}
}
{
} }
create intent to which activity you want to go and start that after download is completed like
suppose you want to go to com.ex.act onceit completes then do
Intent i=new Intent("com.ex.act");
startActivity(i);