This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I am working on an android project and ran into problems. I have an activity which has a "Write a Review" button which opens a dialog, which in turn has two buttons "Done" and "No Thanks". The "Done" button executes an AsyncTask which stores data to server but it causes the app to crash with a NullPointerException error. Here's the code:
writeReviewBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try{
// Create custom dialog object
final Dialog dialog = new Dialog(GetReviewActivity.this);
// Include dialog.xml file
dialog.setContentView(R.layout.write_review_activity);
// Set dialog title
dialog.setTitle("Your review is valuable");
// set values for custom dialog components - text, image and button
TextView text = (TextView) dialog.findViewById(R.id.tvWR);
//text.setText("Custom dialog Android example.");
ImageView image = (ImageView) dialog.findViewById(R.id.smiley);
dialog.show();
Button writeButton = (Button) dialog.findViewById(R.id.buttonWR);
writeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new WriteReviewAsyncTask().execute();
}
});
Button declineButton = (Button) dialog.findViewById(R.id.buttonNoThanks);
// if decline button is clicked, close the custom dialog
declineButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Close dialog
dialog.dismiss();
}
});
}catch (Exception e){
e.printStackTrace();
}
}
});
The writeButton is the "Done" button.
Here's the AsyncTask implementation:
public class WriteReviewAsyncTask extends AsyncTask<Void,Void,Void>{
final EditText etWR = (EditText)findViewById(R.id.etWR);
String Review = etWR.getText().toString();
#Override
protected Void doInBackground(Void... params) {
ArrayList<NameValuePair> dataToSend = new ArrayList<>();
try {
Log.i("HAPPENED: ","Working");
userLocalStore = new UserLocalStore(GetReviewActivity.this);
User user = userLocalStore.getLoggedInUser();
dataToSend.add(new BasicNameValuePair("reviewer_name",user.username));
dataToSend.add(new BasicNameValuePair("item_name",ItemName));
dataToSend.add(new BasicNameValuePair("review",Review));
HttpParams httpParams = getHttpRequestParams();
HttpClient httpClient = new DefaultHttpClient(httpParams);
HttpPost httpPost = new HttpPost(SERVER_ADDRESS+"StoreReview.php");
httpPost.setEntity(new UrlEncodedFormEntity(dataToSend));
httpClient.execute(httpPost);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
UpdateRecyclerView();
}
private HttpParams getHttpRequestParams() {
HttpParams httpRequestParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpRequestParams,
CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(httpRequestParams,
CONNECTION_TIMEOUT);
return httpRequestParams;
}
}
And the LogCat error:
09-23 22:12:22.110 30716-30716/app.usrete.jayant.delvemitt E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at app.usrete.jayant.delvemitt.childscreen.getreviews.getreview.GetReviewActivity$WriteReviewAsyncTask.<init>(GetReviewActivity.java:330)
at app.usrete.jayant.delvemitt.childscreen.getreviews.getreview.GetReviewActivity$2$1.onClick(GetReviewActivity.java:133)
at android.view.View.performClick(View.java:4475)
at android.view.View$PerformClick.run(View.java:18786)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
Please help me out guys!
Why are you passing return null in protected Void doInBackground(Void... params)
That passes that arguement to onPostExecute(Void params) which wont take any Argument,its type Void,so avoid writing return null,just remove that line
Related
This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 6 years ago.
I am getting android.os.NetworkOnMainThreadException in my Login Activity. Basically I am simply trying to check if the user id and password entered by the user are correct i.e., is the user allowed to sign in or not. I have searched for a solution and know that the exception has got something to do with networking on main thread. But I am using AsyncTask. I am still getting this exception. Here is my LoginActivity.java
public class LoginActivity extends AppCompatActivity {
JSONParser jsonParser = new JSONParser();
// single product url
private static final String url_user_check_login = "##########################/android_connect/db_connect.php";
int success=0;
String id="";
String password="";
private static final String TAG_SUCCESS = "success";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Defining onClickListener for Login Button
Button loginBtn=(Button) findViewById(R.id.login_btn);
loginBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Check credentials
EditText phone=(EditText)findViewById(R.id.phone_txt);
EditText pwd=(EditText)findViewById(R.id.password_txt);
id=phone.getText().toString();
password=pwd.getText().toString();
new CheckUserLogin().execute();
if (success == 1) {
Intent intent=new Intent(getApplicationContext(), RideDetailsActivity.class);
startActivity(intent);
}else{
// product with id not found
}
}
});
}
class CheckUserLogin extends AsyncTask<String, String, String> {
protected String doInBackground(String... params) {
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
// Check for success tag
try {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("id", id));
// getting product details by making HTTP request
// Note that product details url will use GET request
JSONObject json = jsonParser.makeHttpRequest(
url_user_check_login, "GET", params);
// check your log for json response
// Log.d("Single Product Details", json.toString());
// json success tag
success = json.getInt(TAG_SUCCESS);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return null;
}
}
}
I don't know if this is important but I tried debugging and put break points inside the doInBackground method but my debugger just ignores the break points and it just blows past the new CheckUserLogin().execute(); statement.
Also here is my exception stack trace.
FATAL EXCEPTION: main
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1128)
at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
at java.net.InetAddress.getAllByName(InetAddress.java:214)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:587)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:511)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:489)
at com.heycabs.heycabs.JSONParser.makeHttpRequest(JSONParser.java:65)
at com.heycabs.heycabs.LoginActivity$CheckUserLogin$1.run(LoginActivity.java:98)at android.os.Handler.handleCallback(Handler.java:800)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5409)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:606)
at dalvik.system.NativeStart.main(Native Method)
You are incorrectly using Asynktask. success == 1 will never excute, since synchronous commands would happen in nanoseconds, and network, would take several milliseconds.
Do startActivity(intent) on the Asynk completion.... finally you created a new Thread, and in it, went back to the UI one:
runOnUiThread(new Runnable()
This is incorrect. Please read documentation on AsynkTask. And read this example
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I'm getting NullPointerException while adding data from android app to MySQL database, so when I click to create a new product this exception occurs. This is my code to add new product in my database:
public class NewProductActivity extends Activity {
// Progress Dialog
private ProgressDialog pDialog;
JSONParser jsonParser = new JSONParser();
EditText inputName;
EditText inputPrice;
EditText inputDesc;
// url to create new product
private static String url_create_product = "http://192.168.56.1/products/create_product.php";
// JSON Node names
private static final String TAG_SUCCESS = "success";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_product);
// Edit Text
inputName = (EditText) findViewById(R.id.inputName);
inputPrice = (EditText) findViewById(R.id.inputPrice);
inputDesc = (EditText) findViewById(R.id.inputDesc);
// Create button
Button btnCreateProduct = (Button) findViewById(R.id.btnCreateProduct);
// button click event
btnCreateProduct.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String name = inputName.getText().toString();
String price = inputPrice.getText().toString();
String description = inputDesc.getText().toString();
// creating new product in background thread
new CreateNewProduct().execute(name,price,description);
}
});
}
/**
* Background Async Task to Create new product
* */
class CreateNewProduct extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(NewProductActivity.this);
pDialog.setMessage("Creating Product..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
/**
* Creating product
* */
protected String doInBackground(String... args) {
String name = args[0],
price = args[1],
description = args[2];
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("name", name));
params.add(new BasicNameValuePair("price", price));
params.add(new BasicNameValuePair("description", description));
// getting JSON Object
// Note that create product url accepts POST method
**line 102** JSONObject json = jsonParser.makeHttpRequest(url_create_product,
"POST", params);
// check log cat fro response
Log.d("Create Response", json.toString());
// check for success tag
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// successfully created product
Intent i = new Intent(getApplicationContext(), AllProductsActivity.class);
startActivity(i);
// closing this screen
finish();
} else {
// failed to create product
}
} 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 done
pDialog.dismiss();
}
}
}
I checked out my PHP code and it works fine:
<?php
$con = mysql_connect('localhost', 'root','');
mysql_select_db('database',$con);
$name = $_POST['name'];
$price = $_POST['price'];
$description = $_POST['description'];
$sql = "insert into products(name, price, description)
values('$name','$price','$description')";
mysql_query($sql);
?>
Logcat:
FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:299)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
at java.util.concurrent.FutureTask.run(FutureTask.java:239)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856)
aused by: java.lang.NullPointerException
at com.example.hanen.test1.NewProductActivity$CreateNewProduct.doInBackground(NewProductActivity.java:102)
at com.example.hanen.test1.NewProductActivity$CreateNewProduct.doInBackground(NewProductActivity.java:68)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856)
I don't have the answer to your question, because you haven't included line numbers on your listing, and I'm not going to hand-number them. Finding and fixing this type of error, though, is dead simple. Here are the steps:
Turn on line numbers in your IDE
Find the line in your code that corresponds to the topmost line in the stacktrace that refers to a line in your code. In this case that is line 102 in the file NewProductActivity.java
On that line, there will be an expression that looks like variable.something.
When that line is executed variable is null. Find out why.
I basically just call this in the android:onClick function in my XML for this particular ImageView: android:onClick="SendGetStartedNotification". But because my function has two parameters, I get this error Method has incorrect signature. It wants me to removed the ParseUser class.
public void SendGetStartedNotification(View view, ParseUser user) {
// initiate installation query
ParseQuery<ParseInstallation> query = ParseInstallation.getQuery();
query.whereEqualTo("userId", user.getUserObject());
// send push notification
ParsePush push = new ParsePush();
push.setQuery(query);
push.setMessage(ParseUser.getCurrentUser().getUsername() + " " + "thinks you should create something!");
push.sendInBackground();
// send notification to NotificationsActivity
ParseObject notification = createGetStartedMessage(view, user);
send(notification);
}
The problem is my error message:
12-20 22:22:37.349 29251-29251/com.app.testE/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.app.test, PID: 29251
java.lang.IllegalStateException: Could not find method SendGetStartedNotification(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.widget.ImageView with id 'messageGallerySave2'
at android.view.View$DeclaredOnClickListener.resolveMethod(View.java:4485)
at android.view.View$DeclaredOnClickListener.onClick(View.java:4449)
at android.view.View.performClick(View.java:5204)
at android.view.View$PerformClick.run(View.java:21153)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
What are my alternatives? Setting an onClick listener programatically doesn't seem to be working either. What should I do?
Update: I'm using an AsyncTask to bring user information in my class.
private class GetParseUserInformationTask extends AsyncTask<Void, Design, ParseUser> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(GalleryActivity.this);
// Set progressdialog message
mProgressDialog.setMessage("Loading Designs...");
mProgressDialog.setIndeterminate(false);
// Show progressdialog
mProgressDialog.show();
}
#Override
protected ParseUser doInBackground(Void... params) {
ParseUser parseUser = null;
// gather User information and then fetch the designs for them
try {
parseUser = ParseHelper.GetUserInformation(userObjectId);
} catch (ParseException e) {
e.printStackTrace();
}
return parseUser;
}
#Override
protected void onPostExecute(ParseUser user) {
if(user == null) {
//todo: some error message
return;
}
((TextView)findViewById(R.id.fullName)).setText(user.getName());
((TextView)findViewById(R.id.bio)).setText(user.getBio());
((TextView)findViewById(R.id.websiteLink)).setText(user.getWebsiteLink());
((TextView)findViewById(R.id.username)).setText(user.getUsername());
((TextView)findViewById(R.id.saves_number)).setText(user.getFeedDesignSaves().toString());
((TextView)findViewById(R.id.designs_number)).setText(String.valueOf(ParseHelper.GetUserDesignsCount(user.getUserObject())));
((ImageView)findViewById(R.id.profile_picture)).setImageDrawable(Drawable.createFromPath(user.getProfilePictureURL()));
// asynchronously display the profile picture downloaded from parse
if(user.getProfilePictureURL() != null) {
profilePictureImageLoader.DisplayImage(user.getProfilePictureURL(), ((ImageView) findViewById(R.id.profile_picture)), null);
}
new GetParseUserDesignsTask().execute(user);
mProgressDialog.dismiss();
}
}
On Click listener on button.
imageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
SendGetStartedNotification(ParseUser user);
}
} );
Make your method like this:
public void SendGetStartedNotification(ParseUser user) {
// initiate installation query
ParseQuery<ParseInstallation> query = ParseInstallation.getQuery();
query.whereEqualTo("userId", user.getUserObject());
// send push notification
ParsePush push = new ParsePush();
push.setQuery(query);
push.setMessage(ParseUser.getCurrentUser().getUsername() + " " + "thinks you should create something!");
push.sendInBackground();
// send notification to NotificationsActivity
ParseObject notification = createGetStartedMessage(view, user);
send(notification);
}
I have an activity that is displayed in portrait only and in my tablet it causes the following:
android.view.WindowLeaked: Activity com.spicycurryman.getdisciplined10.app.InstalledAppActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{53210b88 V.E..... R.....ID 0,0-1520,192} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:354)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:216)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
at android.app.Dialog.show(Dialog.java:281)
at com.spicycurryman.getdisciplined10.app.InstalledAppActivity$LoadApplications.onPreExecute(InstalledAppActivity.java:306)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
at android.os.AsyncTask.execute(AsyncTask.java:534)
at com.spicycurryman.getdisciplined10.app.InstalledAppActivity.onCreate(InstalledAppActivity.java:105)
at android.app.Activity.performCreate(Activity.java:5104)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
I am using an AsyncTask to load a listview of installed apps on the phone and using a progressdialog.
I have researched this problem:
Progress dialog and AsyncTask error
android.view.WindowLeaked exception
Android Error: Window Leaked in AsyncTask
I was able to produce this code so that the whole app doesn't crash and burn, but the exception is still thrown and the activity screen is kind of shaky after the button click and the whole transition is not really smooth.
#Override
protected void onPostExecute(Void result) {
apkList.setAdapter(new ApkAdapter(InstalledAppActivity.this, packageList1, packageManager));
try {
if ((this.pDialog != null) && this.pDialog.isShowing()) {
this.pDialog.dismiss();
}
} catch (final IllegalArgumentException e) {
// Handle or log or ignore
} catch (final Exception e) {
// Handle or log or ignore
} finally {
this.pDialog = null;
}
super.onPostExecute(result);
}
Dismissing the progress dialog or calling finish() doesn't really solve the problem either...
How would I fix this?
Here is most of the AsyncTask code:
private class LoadApplications extends AsyncTask<Void, Void, Void> {
private ProgressDialog pDialog;
List<PackageInfo> packageList1 = new ArrayList<PackageInfo>();
public LoadApplications(Context context){
Context mContext = context;
}
#Override
protected Void doInBackground(Void... params) {
List<PackageInfo> packageList = packageManager
.getInstalledPackages(PackageManager.GET_PERMISSIONS);
List<PackageInfo> packageList2 = packageManager
.getInstalledPackages(PackageManager.GET_PERMISSIONS);
for(PackageInfo pi : packageList) {
boolean b = isSystemPackage(pi);
boolean c = isSystemPackage1(pi);
boolean d = isSystemPackage2(pi);
if ((!b || !c ) && d ){
packageList1.add(pi);
}
}
//here you got email and message apps in the
for(PackageInfo pi : packageList) {
boolean b = isSystemPackage3(pi);
boolean c = isSystemPackage4(pi);
if (b || c){
packageList1.add(pi);
}
}
//sort by application name
final PackageItemInfo.DisplayNameComparator comparator = new PackageItemInfo.DisplayNameComparator(packageManager);
Collections.sort(packageList1, new Comparator<PackageInfo>() {
#Override
public int compare(PackageInfo lhs, PackageInfo rhs) {
return comparator.compare(lhs.applicationInfo, rhs.applicationInfo);
}
});
return null;
}
#Override
protected void onCancelled() {
super.onCancelled();
}
#Override
protected void onPreExecute() {
pDialog = new ProgressDialog(InstalledAppActivity.this);
pDialog.setMessage("Loading your apps...");
pDialog.show();
}
//Inefficient patch to prevent Window Manager error
#Override
protected void onPostExecute(Void result) {
apkList.setAdapter(new ApkAdapter(InstalledAppActivity.this, packageList1, packageManager));
try {
if ((this.pDialog != null) && this.pDialog.isShowing()) {
this.pDialog.dismiss();
}
} catch (final IllegalArgumentException e) {
// Handle or log or ignore
} catch (final Exception e) {
// Handle or log or ignore
} finally {
this.pDialog = null;
}
super.onPostExecute(result);
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
}
try this :
#Override
public Object onRetainNonConfigurationInstance() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog = null;
}
if (asynTask!= null) {
asynTask.detach();
}
return ayncTask;
}
Declaring a non-static inner AsyncTask in your activity is not a good idea because it holds a reference to the activity and this could be a couse of the leak. However, various configuration changes could cause the OS to destroy and recreate the activity. There are a number of solutions and Rustam's anser is an example.
However, I prefer to user either AsyncTaskLoader or use some sort of asynchronous callback, like a broadcast. The asynchronous callback decouples your AsyncTask from the Activity.
We are making an Android app that has a login function and mySQL database stored on the server. I found a piece of code and got it to work fine on Android device lower than API level 3.0. Anything beyond that will crash. I was told to use Asynctask to solve my issue. To seperate UI code from the network code? Was told it should be easy but I have no idea how to get it to work. Can anyone should me exactly what I need to do to make this code work? I have spent countless of hours researching into this problem and still no luck. I appreciate any help. Thank you
public class RegisterActivity extends Activity {
Button btnRegister;
Button btnLinkToLogin;
EditText inputFullName;
EditText inputEmail;
EditText inputPassword;
TextView registerErrorMsg;
// JSON Response node names
private static String KEY_SUCCESS = "success";
private static String KEY_ERROR = "error";
private static String KEY_ERROR_MSG = "error_msg";
private static String KEY_UID = "uid";
private static String KEY_NAME = "name";
private static String KEY_EMAIL = "email";
private static String KEY_CREATED_AT = "created_at";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.register);
// Importing all assets like buttons, text fields
inputFullName = (EditText) findViewById(R.id.registerName);
inputEmail = (EditText) findViewById(R.id.registerEmail);
inputPassword = (EditText) findViewById(R.id.registerPassword);
btnRegister = (Button) findViewById(R.id.btnRegister);
btnLinkToLogin = (Button) findViewById(R.id.btnLinkToLoginScreen);
registerErrorMsg = (TextView) findViewById(R.id.register_error);
// Register Button Click event
btnRegister.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
String name = inputFullName.getText().toString();
String email = inputEmail.getText().toString();
String password = inputPassword.getText().toString();
UserFunctions userFunction = new UserFunctions();
JSONObject json = userFunction.registerUser(name, email, password);
// check for login response
try {
if (json.getString(KEY_SUCCESS) != null) {
registerErrorMsg.setText("");
String res = json.getString(KEY_SUCCESS);
if(Integer.parseInt(res) == 1){
// user successfully registred
// Store user details in SQLite Database
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
JSONObject json_user = json.getJSONObject("user");
// Clear all previous data in database
userFunction.logoutUser(getApplicationContext());
db.addUser(json_user.getString(KEY_NAME), json_user.getString(KEY_EMAIL), json.getString(KEY_UID), json_user.getString(KEY_CREATED_AT));
// Launch Dashboard Screen
Intent dashboard = new Intent(getApplicationContext(), DashboardActivity.class);
// Close all views before launching Dashboard
dashboard.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(dashboard);
// Close Registration Screen
finish();
}else{
// Error in registration
registerErrorMsg.setText("Error occured in registration");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
// Link to Login Screen
btnLinkToLogin.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent i = new Intent(getApplicationContext(),
LoginActivity.class);
startActivity(i);
// Close Registration View
finish();
}
});
}
}
Here is also the logCatError
D/AndroidRuntime(10040): Shutting down VM
W/dalvikvm(10040): threadid=1: thread exiting with uncaught exception (group=0x416f2930)
E/AndroidRuntime(10040): FATAL EXCEPTION: main
E/AndroidRuntime(10040): android.os.NetworkOnMainThreadException
E/AndroidRuntime(10040): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
E/AndroidRuntime(10040): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
E/AndroidRuntime(10040): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
E/AndroidRuntime(10040): at libcore.io.IoBridge.connect(IoBridge.java:112)
E/AndroidRuntime(10040): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
E/AndroidRuntime(10040): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
E/AndroidRuntime(10040): at java.net.Socket.connect(Socket.java:842)
From the ICS and above versions Android won't allowed any network operation in the UI thread.It should be done in separate thread so it won't hang the UI.Try your network communication code in the separate thread.
Refer this Link.It explains why this occurs on Android 3.0 and above.
It is true that android has become very strict about UI thread and wont allow you to perform background calculations on UI thread as it decrease the performance.You were told right to use async task for performing network communications. You can do it by executing asyncTask at onCLick of your register button using new yourTask().execute();.
Then write an asyncTask class like this
private class yourTask extends AsyncTask<Integer, Void, Integer> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//show a progress bar
}
#Override
protected String doInBackground(Integer... params) {
// your network communication code will be here.
return 0;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
//show the result here
}
}