I have a custom progress dialog that seems to work everywhere except here in my code:
My login activity (relevant snippets):
#Override
protected void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
context = this;
pd = AUtils.getProgressDialog(context, false);
UserExistsAuthenticateAndRoute = getIntent().getBooleanExtra("UserExistsAuthenticateAndRoute", false);
RouteToActivity = getIntent().getStringExtra("RouteToActivity");
//make sure there is no token in APrefs in memory during login
APrefs pref = new APrefs();
if (pref != null) {
pref.putNMToken(null);
pref.putNMRefreshToken(null);
}
ClickableSpan span = new ClickableSpan() {
#Override
public void onClick(View widget) {
}
};
setActionBar();
initUi();
mToolbarTitle.setText("Log In");
} catch (Exception exc) {
exc.printStackTrace();
}
}
#Override
protected Void doInBackground(Void... voids) {
GDDataManager.get().login(GDUser, new DataCallBack() {
#Override
public void update(DataUpdate update) {
if (update.code == 0) {
final GDUser _gdUser = pref.getMember();
//call get status
if (_gdUser != null) {
Log.i(TAG, "getUserStatus()");
GDDataManager.get().getUserStatus(_gdUser, new DataCallBack() {
#Override
public void update(DataUpdate update) {
if (update.code == 0) {
setGdUserStatus((GDUserStatus) update.data);
loginController(getGdUserStatus(), _gdUser);
} else {
Log.e(TAG, "getUserStatus(), error response msg " + update.message);
if (update.message.contains("error")) {
App.toast(getString(R.string.general_server_error_message));
}
}
}
});
}
} else {
Log.e(TAG, "update message:" + update.message);
if (update.message.contains("error")) {
App.toast(getString(R.string.general_server_error_message));
} else if (update.message.contains("could not verify password")) {
App.toast(getString(R.string.could_not_verify_password));
} else if (update.message.contains("no user found")) {
App.toast(getString(R.string.no_user_found));
} else {
App.toast(update.message);
}
if (btnLogIn != null) {
//disable is valid in order to prevent double click
btnLogIn.setEnabled(false);
btnLogIn.setTextColor(ContextCompat.getColor(context, R.color.colorGrey));
}
edtEmail.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(context, R.drawable.cross_icon), null);
edtEmail.setBackground(ContextCompat.getDrawable(context, R.drawable.textfield_red));
edtPassword.setBackground(ContextCompat.getDrawable(context, R.drawable.textfield_red));
}
}//end update getUserStatus
}
);
return null;
}
};
try {
tryLoginTask.execute();
} catch (Exception exc) {
Log.d(TAG, exc.getMessage());
exc.printStackTrace();
//cancel task on exception , DISMISS DIALOG to avoid locking screen
tryLoginTask.cancel(true);
}
}//end tryLogin()
The static code from utility class, were the dialog is returned (relevant snippet):
public static Dialog getProgressDialog(Context c, boolean isCancelable) {
Dialog pd = new Dialog(c,c.getApplicationInfo().theme);
pd.setCanceledOnTouchOutside(isCancelable);
pd.requestWindowFeature (Window.FEATURE_NO_TITLE);
pd.setContentView (R.layout.progress_dialog);
pd.getWindow().setBackgroundDrawable(new ColorDrawable(Color.argb(150,0,0,0)));
return pd;
}
Im not seeing any errors, exceptions, and the dialog is showiong in other places using the same approach. Sometimes I see it for fraction of a second however the task hasn't completed.
Any suggestions.
Thanks
AlertDialogs are foreground things. You should show your Dialogs in your UI thread. So if you want to show your Dialog in an AsyncTask you should approach with runOnUiThread:
runOnUiThread(new Runnable() {
#Override
public void run() {
// Show your dialog here
}
});
Documentations:
https://developer.android.com/reference/android/os/AsyncTask.html
https://developer.android.com/guide/components/processes-and-threads.html
Related
Sorry I know this question has been asked several time and has lots of answer but none of them solved my problem.
I'm calling web service and showing dialog, which is working ok. But I'm unable to dismiss the progressDialog. Although the same method is working inside fragment but this time I'm using it in Activity. Please point me where I'm making the mistake.
public void signupServiceResponse(String phNum,String password){
progressDialog = createProgressDialog(this, false);
//progressDialog.show();
final ContentServiceCall request = ServiceGenerator.createService(ContentServiceCall.class, "Empty");
final Call<UserServiceResponse> call = request.signUp(Constants.WS_VERSION,Constants.LOCAL_EN,Constants.PLATFORM, phNum,password);
call.enqueue(new Callback<UserServiceResponse>() {
#Override
public void onResponse(Call<UserServiceResponse> call, final Response<UserServiceResponse> response) {
if(response!=null && response.isSuccessful())
{
if(response.body()!=null && response.body().getResponse()!=null)
{
if(response.body().getResponse().getResponseCode()== Constants.RESPONSE_CODE_SUCCESS) {
if(response.body().getUser() != null && response.body().getUserSubscription()!= null && response.body().getUserSubscription() !=null) {
userEntity = response.body().getUser();
userProfileEntity = response.body().getUserProfile();
userSubscriptionEntity = response.body().getUserSubscription();
//insert in user table
int tableCode = 1; //table code 1 for user table
dbHelper.insertUserRegistration(userEntity, userProfileEntity, userSubscriptionEntity, tableCode);
dbHelper.close();
progressDialog.dismiss();
Intent i = new Intent(RegistrationActivity.this, ActivateAccountActivity.class);
startActivity(i);
}
} else if((response.body().getResponse().getResponseCode()== Constants.USERAlREADYEXIST_RESPONSE_CODE_SUCCESS)) {
// in case user data is cleared or app is reinstalled
boolean userCount = dbHelper.getUserCount();
if (userCount) {
Intent i = new Intent(RegistrationActivity.this, MainActivity.class);
startActivity(i);
} else if(!userCount){
// if user exist and data is cleared
userEntity = response.body().getUser();
userProfileEntity = response.body().getUserProfile();
userSubscriptionEntity = response.body().getUserSubscription();
int tableCode = 1;
dbHelper.insertUserRegistration(userEntity, userProfileEntity, userSubscriptionEntity, tableCode);
dbHelper.close();
}
} else if((response.body().getResponse().getResponseCode()== Constants.RESPONSE_CODE_PASSWORD_INCORRECT)){
Toast.makeText(RegistrationActivity.this,"Password incorrect",Toast.LENGTH_LONG).show();
btnForgetPassword.setVisibility(View.VISIBLE);
progressDialog.dismiss();
}
else {
}
}
else {
// leave it
}
}
else
{
// Display proper message
//Toast.makeText(getActivity(),getString(R.string.error_webservice_response),Toast.LENGTH_LONG).show();
}
progressDialog.dismiss();
}
#Override
public void onFailure(Call<UserServiceResponse> call, Throwable t) {
Log.e("Fail", "Failure");
Log.e("ERROR", t.getMessage());
progressDialog.dismiss();
Toast.makeText(RegistrationActivity.this,getString(R.string.error_internet_connectivity),Toast.LENGTH_LONG).show();
}
});
}
public ProgressDialog createProgressDialog(Context mContext, Boolean cancelable) {
final ProgressDialog dialog = new ProgressDialog(mContext);
try {
dialog.show();
} catch (WindowManager.BadTokenException e) {
}
dialog.setCancelable(cancelable);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.setContentView(R.layout.dialog);
return dialog;
}
Make your dialog a global variable and initialize it in the onCreate() (If you're inside an Activity).
dialog = new ProgressDialog(mContext);
Add this method.
public ProgressDialog dismiss() {
if(dialog != null) {
dialog.dismiss();
}
}
Finally, instead of calling progressDialog.dismiss() simply call dismiss().
You have to check /write like this.
if(progressDialog!=null &&
progressDialog.isshowing){
progressDialog.dismiss();
}
I am using and it is working.
I am currently writing an Android app in Android Studio for the Microsoft band that will record data from the GSR, HR, and Skin Temp.
I have the data for GSR and Skin Temp. currently reading on the application but the rate that it is updated is very slow, especially for the Skin Temp. I was wondering if there was a way to make these sensors send data more frequently because the data I have now has too long of intervals for the purpose I am using it for. Here is my MainPage.java file.
public class MainPage extends Activity {
private BandClient client = null;
TextView tvGSR;
TextView tvHeartRate;
TextView tvTemperature;
Button updateTest;
private BandGsrEventListener mGsrEventListener = new BandGsrEventListener() {
#Override
public void onBandGsrChanged(final BandGsrEvent event) {
if (event != null) {
appendGSRToUI(String.format("%d kΩ\n", event.getResistance()));
}
}
};
private BandSkinTemperatureEventListener tempEventListener = new BandSkinTemperatureEventListener() {
#Override
public void onBandSkinTemperatureChanged(final BandSkinTemperatureEvent event) {
if (event != null) {
appendTempToUI(String.format("%.2f ºF\n", event.getTemperature()*1.800 + 32.00));
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_page);
tvGSR = (TextView) findViewById(R.id.tvGSR);
tvTemperature = (TextView) findViewById(R.id.tvTemperature);
updateTest = (Button) findViewById(R.id.updateTest);
updateTest.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
tvGSR.setText("");
tvTemperature.setText("");
new GsrSubscriptionTask().execute(); // Put first (runs connection)
new TempSubscriptionTask().execute();
}
});
}
#Override
protected void onResume() {
super.onResume();
tvGSR.setText("");
tvTemperature.setText("");
}
#Override
protected void onPause() {
super.onPause();
if (client != null) {
try {
client.getSensorManager().unregisterGsrEventListener(mGsrEventListener);
client.getSensorManager().unregisterSkinTemperatureEventListener(tempEventListener);
} catch (BandIOException e) {
appendGSRToUI(e.getMessage());
appendTempToUI(e.getMessage());
}
}
}
#Override
protected void onDestroy() {
if (client != null) {
try {
client.disconnect().await();
} catch (InterruptedException e) {
// Do nothing as this is happening during destroy
} catch (BandException e) {
// Do nothing as this is happening during destroy
}
}
super.onDestroy();
}
private class GsrSubscriptionTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
if (getConnectedBandClient()) {
int hardwareVersion = Integer.parseInt(client.getHardwareVersion().await());
if (hardwareVersion >= 20) {
appendGSRToUI("Band is connected.\n");
client.getSensorManager().registerGsrEventListener(mGsrEventListener);
} else {
appendGSRToUI("The Gsr sensor is not supported with your Band version. Microsoft Band 2 is required.\n");
}
} else {
appendGSRToUI("Band isn't connected. Check Bluetooth.\n");
}
} catch (BandException e) {
String exceptionMessage="";
switch (e.getErrorType()) {
case UNSUPPORTED_SDK_VERSION_ERROR:
exceptionMessage = "SDK Version Outdated.\n";
break;
case SERVICE_ERROR:
exceptionMessage = "GSR Not Supported\n";
break;
default:
exceptionMessage = "Unknown error occured: " + e.getMessage() + "\n";
break;
}
appendGSRToUI(exceptionMessage);
} catch (Exception e) {
appendGSRToUI(e.getMessage());
}
return null;
}
}
private class TempSubscriptionTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
if (true) {
int hardwareVersion = Integer.parseInt(client.getHardwareVersion().await());
if (hardwareVersion >= 20) {
appendTempToUI("Band is connected.\n");
client.getSensorManager().registerSkinTemperatureEventListener(tempEventListener);
} else {
appendTempToUI("Temperature Not Supported.\n");
}
} else {
appendTempToUI("Band isn't connected. Check Bluetooth\n");
}
} catch (BandException e) {
String exceptionMessage="";
switch (e.getErrorType()) {
case UNSUPPORTED_SDK_VERSION_ERROR:
exceptionMessage = "SDK Version Outdated\n";
break;
case SERVICE_ERROR:
exceptionMessage = "Microsoft Health App Error\n";
break;
default:
exceptionMessage = "Unknown error occured: " + e.getMessage() + "\n";
break;
}
appendTempToUI(exceptionMessage);
} catch (Exception e) {
appendTempToUI(e.getMessage());
}
return null;
}
}
private void appendGSRToUI(final String string) {
this.runOnUiThread(new Runnable() {
#Override
public void run() {
tvGSR.setText(string);
}
});
}
private void appendTempToUI(final String string) {
this.runOnUiThread(new Runnable() {
#Override
public void run() {
tvTemperature.setText(string);
}
});
}
private boolean getConnectedBandClient() throws InterruptedException, BandException {
if (client == null) {
BandInfo[] devices = BandClientManager.getInstance().getPairedBands();
if (devices.length == 0) {
appendGSRToUI("Band isn't paired with your phone.\n");
return false;
}
client = BandClientManager.getInstance().create(getBaseContext(), devices[0]);
} else if (ConnectionState.CONNECTED == client.getConnectionState()) {
return true;
}
appendGSRToUI("Band is connecting...\n");
return ConnectionState.CONNECTED == client.connect().await();
}
}
There is currently no way to get data at a faster rate than provided by the Microsoft Band SDK.
Also, depending on what you want the data for, the skin temperature data might not be useful for you. Looking at the sensors you want to subscribe to, it looks like your application might be health related. But the skin temperature data contains the raw values from one of several thermometers inside of the band. And the band itself will generate some heat internally, so the data is unlikely to represent the skin temperature of the wearer exactly.
I want to fix error as follows:
"android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."
here are my code.
public class MainActivity extends Activity {
#SuppressLint("NewApi") #Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
onShowMessage();
}
public void removeContent() {
LinearLayout list = (LinearLayout) findViewById(R.id.linearlayout_list);
list.removeAllViews();
}
public void onShowMessage() {
Thread myThread = new Thread(new Runnable() {
#Override
public void run() {
String id = "id1";
String message = "message1";
String response = HTTPUtils.HTTPPost(Global.MESSAGE_URL,
"id", id,
"message", message);
process(response);
}
});
myThread.start();
}
private void process(String response) {
if (response == null || response.equals("")) {
return;
} else {
try {
JSONObject json = null;
try {
json = FbUtil.parseJson(response);
} catch (FacebookError e) {
showErrorMessage();
}
if (json.has("exception")) {
showErrorMessage();
return;
} else {
Global.list = JsonParser.getInfo(json);
removeContent();
initView();
return;
}
} catch (JSONException e) {
}
return;
}
}
}
error occur on removeContent();
please help me.
You are updating Views in a different thread
removeContent();
initView();
Call this two methods in a UI thread like.
runOnUiThread(new Runnable() {
#Override
public void run() {
removeContent();
initView();
}
});
I am using Parse in order to store my data. During the user 's registration, I create an AsyncTask to set the result in the calling activity if the user's email exists or not. Here is the code to trigger the validation
View.OnClickListener btnNextClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
if (etEmail == null) {
return;
}
final String email = etEmail.getText().toString();
if (email == null || email.length() == 0) {
etEmail.setError(getResources().getString(
R.string.error_email_is_null)
);
etEmail.requestFocus();
valid = false;
} else {
if (!Common.isValidEmailAddress(email)) {
etEmail.setError(getResources().getString(R.string.error_email_not_valid));
etEmail.requestFocus();
valid = false;
} else {
// validate Email from back end
new CheckEmailAsyncTask(CreateAccountActivity.this, email).execute();
if (emailValid == false) {
etEmail.setError(getResources().getString(R.string.error_email_existed));
etEmail.requestFocus();
valid = false;
}
}
}
if (valid) {
// if valid then going to the next step
Intent intent = new Intent(CreateAccountActivity.this, UpdateUserActivity.class);
intent.putExtra(AppConstant.PARAM_EMAIL, email);
startActivity(intent);
}
}
boolean emailValid;
public void setEmailValid (boolean emailValid) {
this.emailValid = emailValid;
}
};
and this is the code for CheckEmailAysncTask
public class CheckEmailAsyncTask extends AsyncTask<String, Void, Void> {
ProgressDialog progressDialog;
Context context;
CreateAccountActivity createAccountActivity;
String email;
public CheckEmailAsyncTask(CreateAccountActivity createAccountActivity, String email){
this.createAccountActivity = createAccountActivity;
this.context = createAccountActivity;
this.email = email;
progressDialog = new ProgressDialog(context);
}
#Override
protected void onPreExecute() {
this.progressDialog.show();
super.onPreExecute();
}
#Override
protected Void doInBackground(String... params) {
UserDAO userDAO = new UserDAO(context);
try {
int count = userDAO.isUserExists(email);
if (count > 0) {
createAccountActivity.setEmailValid(false);
} else {
createAccountActivity.setEmailValid(true);
}
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
super.onPostExecute(result);
}
}
}
and in UserDAO
public int isUserExists(String email) throws ParseException {
ParseQuery query = new ParseQuery("User");
query.whereEqualTo("email", email);
return query.count();
}
However, in my setup, the code below the AsyncTask will be executed first before the result are returned back to from Parse. How can I just let the rest of the code wait for future return and then continue ? One of the solution that I come up with is to keep looping the calling to the AsyncTask and sleep for while until the result is back
Try this:
if (email == null || email.length() == 0) {
...
}
else if (email != null & email.length() != 0) {
...
}
One solution that I just came up with is sending a callback to the DAO layer function so when the done action is triggered, it will trigger back the callback to move on.
public interface NavCallback {
public void finish();
}
public class MainActivity {
// inside click listener
NavCallback navCallbackError = new NavCallback() {
#Override
public void finish() {
setError();
}
.....
}
and the DAO function will take the callback as the parameters
public void checkExists(String email, NavCallback callback) {
.....
if (callback != null) callback.finish();
}
I am trying to pull data from Microsoft Azure with this method. The problem is that it can sometimes be really slow, and I need these data in the shared preferences to do anything else in the application. How can I create a loading dialog that will wait for the data to be fetched? I tried putting this method in the AsyncTask doInBackground() method, but the dialog would just appear and then disappear after a millisecond. What is the right way to do this? I was reading similar topics on stackoverflow, but never found a solution.
Thank you!
private class LoadViewTask extends AsyncTask<String, Void, Boolean>
{
private ProgressDialog dialog;
private MainActivity activity;
public LoadViewTask(MainActivity activity) {
this.activity = activity;
context = activity;
dialog = new ProgressDialog(context);
}
private Context context;
#Override
protected void onPreExecute()
{
//Create a new progress dialog
dialog = ProgressDialog.show(MainActivity.this,"Loading...",
"", false, false);
}
//The code to be executed in a background thread.
#Override
protected Boolean doInBackground(final String... args)
{
try
{
mClient.invokeApi("getsettings", jObj, new ApiJsonOperationCallback() {
#Override
public void onCompleted(JsonElement result, Exception error,
ServiceFilterResponse response) {
SharedPreferences settings = getSharedPreferences("SettingsPrefs", 0);
SharedPreferences.Editor editor = settings.edit();
if (error != null) {
System.out.println("Error");
} else {
JsonObject res = result.getAsJsonObject();
try {
if(res.get("gender").toString().equals("null")){
userGender = res.get("gender").toString();
editor.putString("gender", userGender);
} else {
int index1 = res.get("gender").toString().indexOf("\"");
int index2 = res.get("gender").toString().lastIndexOf("\"");
editor.putString("gender", res.get("gender").toString().substring(index1+1, index2));
}
if(res.get("dob").toString().equals("null")){
userDob = res.get("dob").toString();
editor.putString("dob", userDob);
} else {
editor.putString("dob", res.get("dob").toString().substring(1, 11));
}
if (res.get("club").isJsonNull()) {
userClub = 0;
editor.putInt("userClub", userClub);
System.out.println("userclub is null in MA: "+userClub);
} else {
editor.putInt("userClub", res.get("club").getAsInt());
}
editor.commit();
} catch (Exception e) {
Log.e("Error: ", e.toString());
}
}
}
});
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final Boolean success)
{
//close the progress dialog
dialog.dismiss();
}
}
Just follow this steps
1) Create Method say loadDataFromServer() and put code inside
public void loadDataFromServer() {
dialog = ProgressDialog.show(MainActivity.this, "Loading...", "", false, false);
try {
mClient.invokeApi("getsettings", jObj, new ApiJsonOperationCallback() {
#Override
public void onCompleted(JsonElement result, Exception error, ServiceFilterResponse response) {
SharedPreferences settings = getSharedPreferences("SettingsPrefs", 0);
SharedPreferences.Editor editor = settings.edit();
if (error != null) {
System.out.println("Error");
} else {
JsonObject res = result.getAsJsonObject();
try {
if (res.get("gender").toString().equals("null")) {
userGender = res.get("gender").toString();
editor.putString("gender", userGender);
} else {
int index1 = res.get("gender").toString().indexOf("\"");
int index2 = res.get("gender").toString().lastIndexOf("\"");
editor.putString("gender", res.get("gender").toString().substring(index1 + 1, index2));
}
if (res.get("dob").toString().equals("null")) {
userDob = res.get("dob").toString();
editor.putString("dob", userDob);
} else {
editor.putString("dob", res.get("dob").toString().substring(1, 11));
}
if (res.get("club").isJsonNull()) {
userClub = 0;
editor.putInt("userClub", userClub);
System.out.println("userclub is null in MA: " + userClub);
} else {
editor.putInt("userClub", res.get("club").getAsInt());
}
editor.commit();
dialog.dismiss(); // / DISMISS DIALOG HERE
} catch (Exception e) {
Log.e("Error: ", e.toString());
}
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
2) Call this method like
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadDataFromServer();
}
3) dismiss dialog inside onCompleted() method. (I have added that line). just copy the method and call it.
Create a ProgressDialog and show() it before you call mClient.invokeApi and dismiss() it on onCompleted after you have done all the required processes
Try setting indeterminate to true,
//Create a new progress dialog
dialog = ProgressDialog.show(MainActivity.this,"Loading...",
"", true, false);