Android - AsyncTask, SQLite and Context - android

I'm using AsyncTask to download and parse data in a separate thread and I need to pass in the values returned by loadXml into the database.
The problem is that I can't instantiate the database because it requires a context and my DownloadXmlTask is in a separate class to the activity class where it is instantiated.
How do I use pass the values into the database if I can't instantiate the database class?
Code Sample:
public class DownloadXmlTask extends AsyncTask<String,Void,Void>{
public static final String TAG = "VotingApp";
#Override
protected Void doInBackground(String... urls) {
try {
// Get the parsed list of Candidate objects
ArrayList<Candidate> candidatesList = loadXml(urls[0]);
CandidatesDatabaseHelper db = new CandidatesDatabaseHelper(getApplicationContext()); <---- ERROR (I know I can't use getApplicationContext() here)
// Insert the candidates into the database
for(Candidate c : candidatesList){
//NOT FINISHED
}
} catch (IOException e) {
Log.d(TAG, "Error " + e);
} catch (XmlPullParserException e) {
Log.d(TAG, "Error " + e);
}
Log.d(TAG, "NOT WORKING");
return null;
}

You could solve that problem by making AsyncTask an inner class, but if you just do it the way you are currently doing it then technically you could do AsyncTask<Object,Void,Void>:
#Override
protected Void doInBackground(Object... urls) {
Context context = (Context)urls[0]; //should always be true by your own rules
/*then you can also loop the urls for the rest of the Strings to cast
**if there are going to be more. Or not. Your choice*/
//.....
instead of String. When calling .execute(this, someString), send it the Context first and the String second. Then you just cast each of them into their appropriate variables. Try that and let me know if it works. Can't test it out right now unfortunately so you're going to have to test it.

Related

Android: exception thrown in one activity is not caught in another activity

I have a ReaderActivity.java class from where I call signString in signData.java class. If all is well then a new activity named ProductActivity is created. If there is exception in signString method, then ProductActivity is not supposed to be created.
The issue is, I still see ProductActivity is created even though I see the KSIEXCEPTION message in the log. What am I missing here?
public class ReaderActivity extends AppCompatActivity {
.....
public void setGlobal(String actualData) {
signData sign = new signData();
try {
sign.signString(getBaseContext(), finalResults, countToSend, locToSend, typeToSend);
Intent productIntent = new Intent(getBaseContext(), ProductActivity.class);
startActivity(productIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now in the signData class I have the method
public class signData extends Activity{
public void signString(Context context, String data, String count, String loc, String type){
try {
/*some http connection code here*/
/*some computation related to specific API*/
}
catch (KSIException e) {
Log.i("KSIEXCEPTION","here");
e.printStackTrace();
}
}
}
You cant create object for an activity like this. signData sign = new signData();
2.
The issue is, I still see ProductActivity is created even though I see
the KSIEXCEPTION message in the log. What am I missing here?
Yes you just catching the exception in signString method, so after execution of this method definitely, it will create next activity.
If you dont want to go to next activity, you can move that method to some utility class and you can get some return value(boolean at-least) and based on that you can move to next activity

How to Call a Another Activity AsyncTask Class from a Android Activity Getting NPE

ABC.class First activity Class.
XYZ.class is AsyncTask Activity Class.
having More than 10 Async task in my application ,So i kept Async task in Separate Class.
I am Calling the Another Activity Asynctask Class(XYZ.class) from a Activity(ABC.class).
Problem:
1.I Can call that Async Task from ABC.class but, I Kept Some Instance values inside OnCreate of XYZ.class Class(Getting Azure Local Database Data) .
So Asynctask Getting NPE.
2.Oncreate Method is Not Running, When that Async task is calling From Other Activity.
3.Inside doinbackgroud iam getting NPE Error.
help me how to Solve this ,else Suggest me Any other Solution.
EDIT:1
In my Async task Iam fetching Data from Azure Server to Local DB,so i need Instances what i kept inside Oncreate.
ABC.class
Calling the Async Task
AsyncTaskload_UserGroupMappingTableClass myClass = new AsyncTaskload_UserGroupMappingTableClass(getApplicationContext());
myClass.execute();
XYZ.class
th_tbusergroupmapping is my Database Name
/*CLient for Table5 */
private static MobileServiceClient mClient_UserGroupMapping;
//ONLINE CLIENT AZURE
public static MobileServiceTable<th_tbusergroupmapping> mToDoTable_UserGroupMapping_ServerAzure;
//Offline CLient FOr LOCAL Datbase.
public static MobileServiceSyncTable<th_tbusergroupmapping> mToDoTable_UserGroupMapping_Local_Database;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
try {
// Create the Mobile Service Client instance, using the provided
// Mobile Service URL and key
mClient_UserGroupMapping = new MobileServiceClient(
"***********",
"**************",
this).withFilter(new ProgressFilter());
/*UserGroupMapping*/
// Get the Mobile Service Table instance to use
mToDoTable_UserGroupMapping_ServerAzure = mClient_UserGroupMapping.getTable(th_tbusergroupmapping.class);
// LOCAL DATABASE TABLE Instance to use
mToDoTable_UserGroupMapping_Local_Database= mClient_UserGroupMapping.getSyncTable("th_tbusergroupmapping", th_tbusergroupmapping.class);
//Init local storage
initLocalStore().get();
}
catch (MalformedURLException e)
{
Log.i("Oncreate", "There was an error creating the Mobile Service. Verify the URL......!");
} catch (Exception e) {
Log.i("Oncreate", "Exception Occur......!");
}
}
public static class AsyncTaskload_UserGroupMappingTableClass extends AsyncTask<Void, String, Void>
{
private Context context;
public AsyncTaskload_UserGroupMappingTableClass(Context context) {
this.context = context;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params)
{
}
#Override
protected void onPostExecute(Void result)
{
try
{
Log.i("DONE ", "Data Sync Done Successfully UserGroupMapping 1");
} catch (Exception e)
{
e.printStackTrace();
Log.i("Exception ", "Post Excecute");
}
}
}
Do not keep AsyncTask in an activity then; just keep it in an ordinary Java class and do not try to keep the data inside the instances of that class; store your information elsewhere: in a singleton class, or in sharedpreferences, or sqlite database, etc.

on Android, wrapper method for logging Crashlytics events with calling class as source of event

I have a utility method inside Utility.class which is a wrapper for sending Crashlytics events.
public static void logCrashlyticsEvent(String message) {
...
Crashlytics.getInstance().core.logException(new Exception(message));
...
}
The issue is whenever I use it from another class the Crashlytics dashboard shows the source for the event as Utility.class like this:
Utility.java line 106
com.myApp.util.Utility.logCrashlyticsEvent
Instead of the showing the it as the actual class who called it.
Is there a way wrap the call to Crashlytics so it will still show the calling class as the source for the event?
Thanks.
Edit:
Just to improve on #Andre Classen solution.
public static void logCrashlyticsEvent(HandledException e) {
Crashlytics.getInstance().core.logException(e);
Timber.e("Message: %s", e.getMessage());
// More stuff
}
HandledException:
public class HandledException extends Exception {
public HandledException(#NonNull String message, Object... args) {
super(String.format(message, args));
}
}
Usage:
Utility.logCrashlyticsEvent(new HandledException("Cast exception, input value1: %s, value2: %s", someValue, anotherValue));
You are creating a new Exception instead of logging the source exception , so the solution is easy:
public static void logCrashlyticsEvent(Exception e) {
.
.
Crashlytics.getInstance().core.logException(e);
.
.
}
To use it:
try{
String s=null;
int size=toString().length();
}
catch (NullPointerException e){
com.myApp.util.Utility.logCrashlyticsEvent(e);
}
This way the exception is logged the way you want it.

Android Fragment + AsyncTask

In a fragment I'm using an 'AsyncTask' to retrieve data from a URL. The main purpose of my code is to access the data (via AsyncTask) and to pass a 'JSONArray' to the fragment.
Problem is, on the fragment side, that when I check the variable that should have the result i get an error saying that the variable is null.
Here is the code:
public class MyFragment extends ListFragment {
//this is the variable that should have the result from the AsyncTask
JSONArray myResult = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
(...)
//execute the asyncTask
new GetResult().execute(email, password);
(...)
}
//The AsyncTask
private class GetResult extends AsyncTask<String, Void, JSONArray> {
#Override
protected JSONArray doInBackground(String... params) {
(...)
JSONArray jsonArray = (JSONArray) json.get("customer");
return jsonArray;
}
protected void onPostExecute(JSONArray result){
(...)
//this is where I try to pass the data to the fragment
MyFragment.this.myResult = result;
}
}
}
Can someone can help me with that? Thank you in advance.
Are you using the value after postExecute method. You should know that after calling execute, your code on the main thread still runs and only after postExecute has completed, will you have the value.
Try to use this code, and make sure that your jsonstring is not null, because you won't post your complete code and I can't see if myResult variable was changed:
try {
JSONArray json = new JSONArray(jsonstring);
JSONObject json_customer = json.getJSONObject("customer");
return json_customer;
} catch (JSONException e) {
return null
}
For me it looks like problem with deserialization from String data to json's. We are lack of information what exactly data you are parsing. Consider using for this some more advanced json processing library lika Gson or Jackson. Usually its easier with them.
It sounds like you are trying to read from myResult variable before the AsyncTask finishes retrieving it. To make sure it populates properly, put this into your onPostExecute function, after this line MyFragment.this.myResult = result;:
Log.i("my result value is: ", MyFragment.this.myResult.toString())
It should print it out in the LogCat if you are retrieving it correctly, and you should be able to access that variable after that.
On a separate note, consider using Volley or Retrofit or another networking plugin to make your life easier.
Maybe you can use a clear way to transfer data back from the task to the fragment.
1) define an interface as the event listener to be called in the AsyncTask, like
public interface TaskEventListener(){
public void onTaskStarted(int messageId);
public void onTaskStopped(int messageId, int resultCode);
public void onDataReady(Object parameter);
}
2) let the fragment implement this EventListener, put the processing code in the onDataReady() function.
3) pass the fragment instance as the EventListener instance.
4) in the class extended from the AsyncTask, call the onTaskStarted() in the onPreExecute() function, call the onDataReady() and onTaskStopped() in the onPostExecute() function, and call the onTaskStopped() only in the onCancelled() function.
5) please use the weak references in the background task class to prevent crashing for referring the invalid UI component.

Android parsing of XML file Null Pointer Exception

I have a method that reads in an XML file, parses it and loads the individual elements into an array. The code itself works when it is included with an Activity class. It needs to be used from 2 different Activities, so I created a utility class so I can call the one copy from each Activity needed. However, when it runs from the utility class, I get a null point exception. This tells me that I'm breaking a rule of what I can do, and from where. I suspect it's related to the access to the resources, as I also tried to access a string resources (just as a test) and that also throws a NPE.
Here is the utility class. The first Log.i appears in LogCat, but the 2nd does not.
class Utils extends MainActivity
{
String debugTag = DEBUG_TAG + "/Utils";
public void loadRankFile() throws XmlPullParserException, IOException
{
int eventType = -1;
boolean boolFoundRanks = false;
int intCounter = 0;
// this line appears in LogCat
Log.i(debugTag, "Inside loadRankFile utility.");
// this line causes the NPE
XmlResourceParser scoutRanks = getResources().getXml(R.xml.scoutranks);
// this line does not appear in LogCat
Log.i(debugTag, "xml file loaded");
.
.
.
}
This is the code from the Activity that calls the method, above:
public class RankProgressActivity extends MainActivity
{
String debugTag = DEBUG_TAG + "/RankProgressActivity";
Utils utilities = new Utils();
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.rank_progress);
try
{
initSelectScout();
utilities.loadRankFile();
initSelectRank();
}
catch (IOException e)
{
Log.i(debugTag, "Failure initializing Scout Progress activity items", e);
}
catch (XmlPullParserException e)
{
Log.e(debugTag, "Rank file parse error.", e);
}
.
.
.
}
I'm sure I'm making a classic mistake, but I don't see it, and I haven't been able to find guidance as of yet. Any feedback would be appreciated. I'm rather new to Java and Android, so this is very much a learning experience for me.
Thank you in advance.
Your Utils class should not be extending an Activity. Activities are your user facing interfaces, meaning that you implement an Activity when you want to display some sort of UI to the user.
Read up on the documentation for an Activity.
Your Utils class should look something like this:
class Utils
{
private static final String DEBUG_TAG = "Utils";
public ArrayList<String> parseRankFile(Context context) throws XmlPullParserException, IOException
{
ArrayList<String> scoutRanks = new ArrayList<String>();
Log.i(DEBUG_TAG, "Inside loadRankFile utility.");
XmlResourceParser scoutRanksParser = context.getResources().getXml(R.xml.scoutranks);
Log.i(DEBUG_TAG, "xml file loaded");
// do your parsing and populate the scoutRanks ArrayList
return scoutRanks;
}
}
Then in your Activity you would call your Utils method like this :
ArrayList<String> scoutRanks = Utils.parseRankFile(this);

Categories

Resources