I have a difficulty with my database connection. I have a DataManager which creates the Database connection etc. I also created an Application class which creates this DataManager so the UI Thread can get the data. Now the problem is that there is a background thread which also needs access to the database, and I am not exactly sure how to do this (currently I get an error when trying to create a new DataManager in the AsyncActivity because the database was not closed (and this is correct, as the UIThread has it open).
So I thought that (and this might not be the right way to do it as it is a different thread) I would get access to the Application and use the same DataManager on a new session. But how can I get access to the Application from an 'ordinary' class without Context or Activity (I have done it before I think, but cannot remember).
The code of the background task is:
public class SyncTask extends AsyncTask<String, Integer, String> {
private static final String TAG = "Sync";
/** application context. */
private Context context;
private ProgressDialog dialog;
public SyncTask(Context aContext) {
//this.activity = activity;
this.context = aContext;
dialog = new ProgressDialog(context);
}
protected void onPreExecute() {
this.dialog.setMessage("Loading...");
this.dialog.setMax(100);
this.dialog.setProgress(0);
this.dialog.show();
}
#Override
protected void onPostExecute(final String errMessage) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (errMessage == null) {
Toast.makeText(context, "Update completed", Toast.LENGTH_LONG).show();
} else {
AlertDialog alertDialog = new AlertDialog.Builder(context).create();
alertDialog.setTitle("Error...");
alertDialog.setMessage(errMessage);
alertDialog.show();
}
}
protected void onProgressUpdate(Integer... progress) {
Log.d(TAG, "Progress Update: " + progress[0].toString());
super.onProgressUpdate(progress[0]);
dialog.setProgress(progress[0]);
}
protected String doInBackground(final String... args) {
try{
publishProgress( new Float(50).intValue());
iDomsAndroidApp app = ((iDomsAndroidApp) ?? cannot remember ??);
DataManager manager = app.getDataManager();
manager.updateData();
return null;
} catch (Exception e){
Log.e(TAG, "error", e);
return e.getMessage();
}
}
}
You can use getApplicationContext() method of any Context instance you have and cast return to YouApplication. It is absolutelly eligible.
You should use a ContentProvider for accessing the database, it is thread safe and the preferred way to handle your data.
http://developer.android.com/guide/topics/providers/content-providers.html
Related
I am busy with an application where i am getting data from my azure database with sql and storing it in an array. I created a separate class where i get my data and my main activity connects to this class and then displays it.
Here is my getData class:
public class GetData {
Connection connect;
String ConnectionResult = "";
Boolean isSuccess = false;
public List<Map<String,String>> doInBackground() {
List<Map<String, String>> data = null;
data = new ArrayList<Map<String, String>>();
try {
ConnectionHelper conStr=new ConnectionHelper();
connect =conStr.connectionclass(); // Connect to database
if (connect == null) {
ConnectionResult = "Check Your Internet Access!";
} else {
// Change below query according to your own database.
String query = "select * from cc_rail";
Statement stmt = connect.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
Map<String,String> datanum=new HashMap<String,String>();
datanum.put("NAME",rs.getString("RAIL_NAME"));
datanum.put("PRICE",rs.getString("RAIL_UNIT_PRICE"));
datanum.put("RANGE",rs.getString("RAIL_RANGE"));
datanum.put("SUPPLIER",rs.getString("RAIL_SUPPLIER"));
datanum.put("SIZE",rs.getString("RAIL_SIZE"));
data.add(datanum);
}
ConnectionResult = " successful";
isSuccess=true;
connect.close();
}
} catch (Exception ex) {
isSuccess = false;
ConnectionResult = ex.getMessage();
}
return data;
}
}
And in my Fragmentactivity.java I simply just call the class as shown here:
List<Map<String,String>> MyData = null;
GetValence mydata =new GetValence();
MyData= mydata.doInBackground();
String[] fromwhere = { "NAME","PRICE","RANGE","SUPPLIER","SIZE" };
int[] viewswhere = {R.id.Name_txtView , R.id.price_txtView,R.id.Range_txtView,R.id.size_txtView,R.id.supplier_txtView};
ADAhere = new SimpleAdapter(getActivity(), MyData,R.layout.list_valence, fromwhere, viewswhere);
list.setAdapter(ADAhere);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
HashMap<String,Object> obj=(HashMap<String,Object>)ADAhere.getItem(position);
String ID=(String)obj.get("A");
Toast.makeText(getActivity(), ID, Toast.LENGTH_SHORT).show();
}
});
My problem comes when I want to include the onPreExecute and onPostExecute because I am relatively new to android studio and I do not know where to put the following lines of code:
#Override
protected void onPreExecute() {
ProgressDialog progress;
progress = ProgressDialog.show(MainActivity.this, "Synchronising", "Listview Loading! Please Wait...", true);
}
#Override
protected void onPostExecute(String msg) {
progress.dismiss();
}
You need to get the data from your azure database using a background service or AsyncTask. However, you are defining a class GetData which does not extend AsyncTask and hence the whole operation is not asynchronous. And I saw you have implemented doInBackground method which is not applicable here as you are not extending AsyncTask. I would suggest an implementation like the following.
You want to get some data from your azure database and want to show them in your application. In these kind of situations, you need to do this using an AsyncTask to call the server api to get the data and pass the data to the calling activity using an interface. Let us have an interface like the following.
public interface HttpResponseListener {
void httpResponseReceiver(String result);
}
Now from your Activity while you want to get the data through an web service call, i.e. AsyncTask, just the pass the interface from the activity class to the AsyncTask. Remember that your AsyncTask should have an instance variable of that listener as well. So the overall implementation should look like the following.
public abstract class HttpRequestAsyncTask extends AsyncTask<Void, Void, String> {
public HttpResponseListener mHttpResponseListener;
private final Context mContext;
HttpRequestAsyncTask(Context mContext, HttpResponseListener listener) {
this.mContext = mContext;
this.mHttpResponseListener = listener;
}
#Override
protected String doInBackground(Void... params) {
String result = null;
try {
// Your implementation of getting data from your server
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(final String result) {
mHttpResponseListener.httpResponseReceiver(result);
}
#Override
protected void onCancelled() {
mHttpResponseListener.httpResponseReceiver(null);
}
}
Now you need to have the httpResponseReceiver function implemented in the calling Activity. So the sample activity should look like.
public class YourActivity extends AppCompatActivity implements HttpResponseListener {
// ... Other code and overriden functions
public void callAsyncTaskForGettingData() {
// Pass the listener here
HttpRequestAsyncTask getDataTask = new HttpRequestGetAsyncTask(
YourActivity.this, this);
getDataTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
#Override
public void httpResponseReceiver(String result) {
// Get the response callback here
// Do your changes in UI elements here.
}
}
To read more about how to use AsyncTask, you might consider having a look at here.
I want to check if a user is registered or not in a database, and if it is get the information of the user.
Normally, when I retrieve the information from the server, I put in the Json a variable saying if the user exists or not. Then in onPostExecute(Void result) i treat the Json, so i don't need the AsyncTask to return any value.
Before I was calling the AsyncTask as follows:
task=new isCollectorRegistered();
task.execute();
But now i'm trying a different approach. I want my asynktask to just return a boolean where i called the AsyncTask.
the AsyncTask looks as follows:
public class isCollectorRegistered extends AsyncTask<Void, Void, Void> {
private static final String TAG_SUCCESS = "success";
int TAG_SUCCESS1;
private static final String TAG_COLLECTOR = "collector";
public String collector;
JSONArray USER = null;
JSONObject jObj = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
// Checks on the server if collector is registered
try {
jObj = ServerUtilities.UserRegistered(context, collector);
return null;
} finally {
return null;
}
}
#Override
protected void onPostExecute(Void result) {
try {
String success = jObj.getString(TAG_SUCCESS);
Log.d(TAG_COLLECTOR, "Final Info: " + success);
//This if sees if user correct
if (Objects.equals(success, "1")){
//GOOD! THE COLLECTOR EXISTS!!
}
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG_COLLECTOR, "JSON parsing didn't work");
}
}
}
I have checked several posts, but I still havent found out the way to retrieve the boolean where I call the Asynktask, something like this :
task=new isCollectorRegistered();
task.execute();
boolean UserRegistered = task.result();
What would be the right approach? Any help would be appreciated
To use AsyncTask you must subclass it. AsyncTask uses generics and varargs. The parameters are the following AsyncTask <TypeOfVarArgParams , ProgressValue , ResultValue> .
An AsyncTask is started via the execute() method.
The execute() method calls the doInBackground() and the onPostExecute() method.
TypeOfVarArgParams is passed into the doInBackground() method as input, ProgressValue is used for progress information and ResultValue must be returned from doInBackground() method and is passed to onPostExecute() as a parameter.
In your case you are passing Void to your AsyncTask : isCollectorRegistered extends AsyncTask<Void, Void, Void> so you can't get your result from the thread.
please read this tutorial to a deep understand of the AsyncTask in Android
I think the following is exactly what you were looking for, Alvaro...NOTE: I tweaked your code to make it more sensible, but I tried to stick to as much of your original code as possible...
public class RegisterCollector extends AsyncTask<String, Void, Boolean> {
private static final String TAG_SUCCESS = "success";
private static final String TAG_COLLECTOR = "collector";
int TAG_SUCCESS1;
String[] strArray;
JSONArray USER = null;
JSONObject jObj = null;
public String collector;
private AppCompatActivity mAct; // Just incase you need an Activity Context inside your AsyncTask...
private ProgressDialog progDial;
// Pass data to the AsyncTask class via constructor -> HACK!!
// This is a HACK because you are apparently only suppose to pass data to AsyncTask via the 'execute()' method.
public RegisterCollector (AppCompatActivity mAct, String[] strArray) {
this.mAct = mAct;
this.strArray = strArray;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
// AHAH!! - So we do need that Activity Context after all...*TISK* *TISK* # Google **sigh**.
progDial = ProgressDialog.show(mAct, "Please wait...", "Fetching the strawberries & cream", true, false);
}
#Override
protected Boolean doInBackground(String... params) {
// Checks on the server if collector is registered
try {
jObj = ServerUtilities.UserRegistered(context, collector);
return true; // return whatever Boolean you require here.
} finally {
return false; // return whatever Boolean you require here.
}
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
progDial.dismiss();
try {
String success = jObj.getString(TAG_SUCCESS);
Log.d(TAG_COLLECTOR, "Final Info: " + success);
// This 'if' block checks if the user is correct...
if (Objects.equals(success, "1")){
//GOOD! THE COLLECTOR EXISTS!!
}
// You can then also use the Boolean result here if you need to...
if (result) {
// GOOD! THE COLLECTOR EXISTS!!
} else {
// Oh my --> We need to try again!! :(
}
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG_COLLECTOR, "JSON parsing didn't work");
Toast.makeText(mAct, "JSON parsing FAILED - Please try again.", Toast.LENGTH_LONG).show();
}
}
}
...then if you want to use the generated Boolean data outside the AsyncTask class try the following:.
RegisterCollector regisColctr = new RegisterCollector((AppCompatActivity) this, String[] myStrArry);
AsyncTask<String, Void, Boolean> exeRegisColctr = regisColctr.execute("");
Boolean isColctrRegistered = false;
try {
isColctrRegistered = exeRegisColctr.get(); // This is how you FINALLY 'get' the Boolean data outside the AsyncTask...-> VERY IMPORTANT!!
} catch (InterruptedException in) {
in.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
if (isColctrRegistered) {
// Do whatever tasks you need to do here based on the positive (i.e. 'true') AsyncTask Bool result...
} else {
// Do whatever tasks you need to do here based on the negative (i.e. 'false') AsyncTask Bool result...
}
There you go - I think this is what you were looking for (originally). I always use this approach whenever I need Async data externally, and it has yet to fail me....
Hello i'm developing an application that performs database queries on a remote server. so far i've successfully interacted with the PHP script on the server side and my code is sending string values without a problem, but i'm not sure how to check if i'm recieving back the values i'm sending back through my PHP script, as my OnPostExecute function is not responding.
Please Help.
Here's the code that's facing problem :
public void submit_data(View V){
try{
new DoSocketProgramming().execute("10.0.2.2");
}
catch(Exception e){
Toast.makeText(getApplicationContext(), "problem here", Toast.LENGTH_SHORT).show();
}
Toast.makeText(getApplicationContext(), "created till here", Toast.LENGTH_SHORT).show();
}
public class DoSocketProgramming extends AsyncTask<String, Void, String>
{
String sendsentence=" this message is sent\n";
String recvsentence=null;
protected void onPreExecute()
{
Toast.makeText(getApplicationContext(), "this is preExecute", Toast.LENGTH_LONG).show();
}
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
try{
Socket con=new Socket(addr,1678);
DataInputStream dis=new DataInputStream(con.getInputStream());
DataOutputStream dos=new DataOutputStream(con.getOutputStream());
dos.writeUTF(sendsentence);
recvsentence=dis.readUTF();
}catch(Exception e){
e.printStackTrace();
}
return recvsentence;
}
protected void onPostExecute(String result) {
try{
Toast.makeText(getApplicationContext(), "this is post execute"+ recvsentence, Toast.LENGTH_LONG).show();
}catch(Exception e){
e.printStackTrace();
}
}
}
It probably is, actually. The problem is that you're using getApplicationContext() as the Context and this is almost always wrong, you shouldn't use this unless you know exactly what you're doing.
When creating an AsyncTask, the constructor receives the Context of the Activity that invoked it, you should store this Context in your AsyncTask class and use it in your onPostExecute() method.
This would be an example:
public class MyAsyncTask extends AsyncTask {
Context context;
private MyAsyncTask(Context context) { this.context = context; }
#Override
protected void onPostExecute(...) {
super.onPostExecute(result);
Toast.makeText(context, "this is post execute"+ recvsentence, Toast.LENGTH_LONG).show();
}
}
I'm writting an app that uses WebServices to retrieve data. Initially I had a private AsyncTask class for each activity that needed data from the WebService. But I've decided to make the code simpler by creating AsyncTask as a public class. All works fine, but my problem is when I want to access the retrieved data from the AsyncTask.
For example this is my AsyncTask class.
public class RestServiceTask extends AsyncTask<RestRequest, Integer, Integer> {
/** progress dialog to show user that the backup is processing. */
private ProgressDialog dialog;
private RestResponse response;
private Context context;
public RestServiceTask(Context context) {
this.context = context;
//...Show Dialog
}
protected Integer doInBackground(RestRequest... requests) {
int status = RestServiceCaller.RET_SUCCESS;
try {
response = new RestServiceCaller().execute(requests[0]);
} catch(Exception e) {
//TODO comprobar tipo error
status = RestServiceCaller.RET_ERR_WEBSERVICE;
e.printStackTrace();
}
return status;
}
protected void onPreExecute() {
response = null;
}
protected void onPostExecute(Integer result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
switch (result) {
case RestServiceCaller.RET_ERR_NETWORK:
Toast.makeText(
context,
context.getResources().getString(
R.string.msg_error_network_unavailable),
Toast.LENGTH_LONG).show();
break;
case RestServiceCaller.RET_ERR_WEBSERVICE:
Toast.makeText(
context,
context.getResources().getString(
R.string.msg_error_webservice), Toast.LENGTH_LONG)
.show();
break;
default:
break;
}
}
public RestResponse getResponse() throws InterruptedException {
return response;
}
}
RestServiceCaller, RestRequest and RestResponse are clasess that I've created.
I'm using the task like this:
RestRequest request = new JSONRestRequest();
request.setMethod(RestRequest.GET_METHOD);
request.setURL(Global.WS_USER);
HashMap<String, Object> content = new HashMap<String, Object>() {
{
put(Global.KEY_USERNAME, username.getText().toString());
}
};
request.setContent(content);
RestServiceTask task = new RestServiceTask(context);
task.execute(request);
This code works fine and is calling the web service correctly, my problem is when I want access to the response. In the AsyncTask I've created the method getResponse but when I use it, it returns a null object because the AsyncTask is still in progress, so this code doesn't work:
//....
task.execute(request);
RestResponse r = new RestResponse();
r = task.getResponse();
r will be a null pointer because AsyncTask is still downloading data.
I've try using this code in the getResponse function, but it doesn't work:
public RestResponse getResponse() throws InterruptedException {
while (getStatus() != AsyncTask.Status.FINISHED);
return response;
}
I thought that with the while loop the thread will wait until the AsyncTask finishes, but what I achieved was an infinite loop.
So my question is, how could I wait until AsyncTask finishes so the getResponse method will return the correct result?
The best solution is use of the onPostExecute method, but because AsyncTask is used by many activities I have no clue what to do.
try creating a callback interface. The answer to this async task question Common class for AsyncTask in Android? gives a good explanation for it.
In my app I performing loading data from web and then displaying it to user. Before loading data app shows progress dialog. I have problem if user locks phone in the middle of loading operation, or server is overloaded and can't respond in time my application freezes, because it doesn't dismiss progress dialog, or in some cases it crashes because lack on needed data.
If some error happened while loading data I want show some dialog to user to let him know about error and ask him should application repeat last request. I tried to use AlertDialog for it, but I haven't succeed.
Here is code of one activity (There is no progress dialog here, but it demonstrates how I loading data):
#EActivity(R.layout.layout_splash)
#RoboGuice
public class SplashScreenActivity extends Activity {
#Inject
private AvtopoiskParserImpl parser;
#Bean
BrandsAndRegionsHolder brandsAndRegionsHolder;
#ViewById(R.id.splash_progress)
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadData();
}
#Background
protected void loadData() {
publishProgress(10);
LinkedHashMap<String, Integer> brands = null;
try {
brands = parser.getBrands();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(50);
LinkedHashMap<String, Integer> regions = null;
try {
regions = parser.getRegions();
} catch (IOException e) {
Log.e(e.getMessage());
}
publishProgress(70);
populateData(brands, regions);
}
#UiThread
protected void populateData(LinkedHashMap<String, Integer> brands, LinkedHashMap<String, Integer> regions) {
Intent intent = new Intent(SplashScreenActivity.this, SearchActivity_.class);
brandsAndRegionsHolder.brandsMap = brands;
brandsAndRegionsHolder.regionsMap = regions;
publishProgress(100);
startActivity(intent);
finish();
}
#UiThread
void publishProgress(int progress) {
progressBar.setProgress(progress);
}
}
parser.getBrands() and parser.getRegions() are loading data from the web.
I want to do something like this:
boolean repeatRequest = true;
while (repeatRequest) {
try {
brands = parser.getBrands();
repeatRequest = false;
} catch (IOException e) {
Log.e(e.getMessage());
repeatRequest = showErrorDialog();
}
}
But I didn't manage to do so because this code executes in background thread, but dialog should be shown in UI thread.
I believe that it should be standard approach of doing so, but didn't manage to find it.
Any ides how can I implement this?
The best way is to use AsyncTask.
private class LoadDataTask extends AsyncTask<Void, Integer, Object> {
private ProgressDialog mProgress;
protected Object doInBackground(Void... params) {
// This method runs in background
Object result = null;
try {
result = parser.parse();
} catch (Exception e) {
result = e.getMessage();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
// This method runs in UI thread
mProgress.setProgress(progress[0]);
}
protected void onPreExecute() {
// This method runs in UI thread
mProgress = new ProgressDialog(context);
mProgress.show();
}
protected void onPostExecute(Object result) {
// This method runs in UI thread
mProgress.dismiss();
if (result instance of String) {
// Here you can launch AlertDialog with error message and proposal to retry
showErrorDialog((String) result);
} else {
populateData(result);
}
}
}