I have an Android application I'm working on, I've got the code working I'm just trying to clean it up a bit by moving certain functions into separate files. Whenever i try to call one of the functions from a separate file, however, it crashes saying FATAL EXCEPTION: AsyncTask #5. I have made a constructor in the separate file and I thought I was doing it correctly but I guess not. Any help is appreciated.
Here is my code:
DatabaseManager database;
public class loginTask extends AsyncTask<String, String, String> {
//check if server is online
protected String doInBackground(String... params) {
Log.d("test", "1");
String username = params[0];
String password = params[1];
URI absolute = null;
Log.d("test", "2");
try {
Log.d("test", "3");
absolute = new URI("http://link.com/webservice/");
} catch (URISyntaxException e) {
Log.d("test", "4");
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("test", "5");
database.test();//crashes at this line
return postHttpResponse(absolute,username,password);
}
//set status bar to offline if flag is false
protected void onPostExecute(String jsonstring) {
try {
//get values from jsonobject
JSONObject jsonobj=new JSONObject(jsonstring);
checkResponse(jsonobj);
//errorMessage.setText(checkResponse(jsonobj));
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
DatabaseManager.java
private final String LOGIN_TAG = "Login";
public DatabaseManager(){
}
public void test(){
Log.d(LOGIN_TAG, "this is a test");
}
You never instantiate DatabaseManager - so it stays null the entire time. Class scoped references stay null until they are given something to reference (either by pointing the new reference to an existing one or by making a new Object)
Consider doing
database = new DatabaseManager();
Log.d("test", "5");
database.test();//shouldn't crash at this line now
Related
I have tried Google Translate and Microsoft Translator. Both give the error:
[microsoft-translator-api] Error retrieving translation : null
Caused by: android.os.NetworkOnMainThreadException
I've set everything up according to references and tutorials. The only difference is that instead of calling Translate.execute() on click of a button, I'm trying to have it call as the JSON string data starts coming in.
Here's what I have:
In My Data Model Class
public String getName() throws Exception {
String trans = Translate.execute(prod_name, Language.ENGLISH, Language.fromString(Locale.getDefault().getLanguage()));
return trans;
}
I've also tried this:
In My Data Model Class
public String getName(){
return prod_name;
}
Along with this:
Main Activity
JsonArrayRequest request = new JsonArrayRequest(FEAT_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString()); try {
for(int i=0;i<response.length();i++){
String pid=response.getJSONObject(i).getString("pid");
String name=response.getJSONObject(i).getString("prod_name");
String img = response.getJSONObject(i).getString("prod_pic");
String lang = Locale.getDefault().getLanguage();
Log.d("Response: ", name);
String trans = Translate.execute(name, Language.SPANISH, Language.fromString(lang));
fdata.add(new FeaturedModel(pid, trans, img));
}
} catch (Exception e) {
e.printStackTrace();
} featAdapt=new FeaturedAdapter(MainActivity.this, fdata);
pageView.setAdapter(featAdapt);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "Error: " + error.getMessage());
}
});
VolleyController.getInstance().addToRequestQueue(request, TAG);
I have seen other SO questions regarding Translate API's on Android but all of them referred to clicking a view to get the translation. I haven't found anything that gives an example of translating the JSON string response from a Volley request. Any ideas? What would be the proper way to do this without overloading the main thread?
PER COMMENTS BELOW
I've added this AsyncTask class to my MainActivity:
class TranslateAsync extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... inTxt) {
try {
String lang = Locale.getDefault().getLanguage();
translatedText = Translate.execute(inTxt, Language.fromString(lang));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("Translate Error", e.toString());
}
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
And now getting an error that it can't resolve method setText(String[]) on this line in my adapter class:
holder.ftitle.setText(feature.get(position).getName());
Looking at both the Google and Microsoft Translator API's, they require String[]
The app i'm developing downloads a JSON file from remote address at every startup and then it parses the JSON Object and copies data to SQLite on the phone.
This operation is the cause for which the app hangs for some seconds on every startup showing blank screen (or sometime blank and then black screen), in fact if i tried to disable this part of code the app starts quickly, with no hang.
So, how could i do it better?
Here is the code (DataHandler class) related to file download, parsing and writing to local SQLite db:
public class DataHandler {
public DataHandler() {
}
public int storeData(Database db, int num) throws JSONException {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://www.example.com/data.json");
request.addHeader("Cache-Control", "no-cache");
long id = -1;
try {
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
InputStreamReader in = new InputStreamReader(entity.getContent());
BufferedReader reader = new BufferedReader(in);
StringBuilder stringBuilder = new StringBuilder();
String line = "";
while ((line=reader.readLine()) != null) {
stringBuilder.append(line);
}
JSONArray jsonArray = new JSONArray(stringBuilder.toString());
SQLiteDatabase dbWrite = db.getWritableDatabase();
ContentValues values = new ContentValues();
if (jsonArray.length() == num && num != 0)
return num;
SQLiteDatabase dbread = db.getReadableDatabase();
dbread.delete("mytable", "1", null);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jObj = (JSONObject) jsonArray.getJSONObject(i);
values.put("_id", jObj.optString("id").toString());
values.put("city", jObj.optString("city").toString());
values.put("country",jObj.optString("country").toString());
values.put("addr", jObj.optString("addr").toString());
values.put("title", jObj.optString("title").toString());
values.put("lon", jObj.optString("lon").toString());
values.put("email", jObj.optString("email").toString());
values.put("phone", jObj.optString("phone").toString());
values.put("web", jObj.optString("web").toString());
values.put("lat", jObj.optString("lat").toString());
values.put("desc", jObj.optString("desc").toString());
values.put("icon", jObj.optString("icon").toString());
values.put("category", jObj.optString("category").toString());
id = dbWrite.insert("merchants", null, values);
}
num = jsonArray.length();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (id > 0)
return num;
else
return -1;
}
}
You should probably to the download and parsing in the background and display some kind of splashscreen with progress information in the meantime.
To avoid an annoying splash screen, you could also cache the data and display your app normally on startup, and only refresh the data once the bakground update is finished.
There are several options to do the download and parse operations in the background :
use an AsyncTask
use a service
I cannot say what's the best solution in your specific case, but I would recommend reading the Processes and Threads and service documentation.
Her goes your Async Task Class
class AsyncClass extends AsyncTask<String,Void,String>
{
int result;
Context context;
ProgressDialog bar;
AsynclassListener<String> listener;
public AsyncClass(Context context, AsynclassListener listener) {//add more parameter as your method body has (i.e Database db, int num) . Don't forget to initialize them.
this.context=context;
this.listener=listener;
bar = new ProgressDialog(context);
bar.setIndeterminate(false);
//make your progressBar here I have just given a simple example for above PB there are more parameters to set.
}
protected String doInBackground(String... Param){
try{
result = storeData();//call your method here
}catch(Exception e){
// Do something when crash
}
return ""+result;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
bar.show();// By the time your data fetching and parsing will go on you this progress bar will be visible.
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
bar.dismiss();//As soon as the work is complete the this method is called.
listener.onTaskComplete(""+result);
/**
* In your case you can later typecast back in integer once you recieve the result.
* this listener will post the result to your main activity.
*/
}
}
Here is your Interface
public interface AsynclassListener<T>{
public void onTaskComplete(T result);
}
Now Let your Activity (Splash Class) implement the interface
This will implement the method as :
#Override
public void onTaskComplete(String result) {
// here the asynclass will post the result as 1 or -1 whatever you want.
//After that you may proceed with your next part i.e switching to next activity or so.
}
Edit: I forgot to mention about how this will be called :
new AsyncClass(getApplicationContext(), this).execute("");// here you have to enter the database and other parameter values that will be required to run the method. Change it accordingly.
As you can see here in your method you are fetching the data from net and parsing also :
There is again a second approach in which you can call the network cal in a separate thread and later the parsing can be done further on UIthread.
Also read about the Async Task Class so as to know about the arguments and the working of class.
I am trying to call AsyncTask from a loop.It is working properly but the issue is it taking quite more time to execute all the request.Please suggest me how could i make it more fast .
for (int i = 0; i < 6; i++) {
response = requestWeatherUpdate(location);
}
requestWeatherUpdate
private WeatherResponse requestWeatherUpdate(String location) {
url = ""+ location;
Log.d("URL for Weather Upadate", url);
WeatherUpdateAsyncTask weatherReq = new WeatherUpdateAsyncTask();
String weatherRequestResponse = "";
try {
weatherRequestResponse = weatherReq.execute(url).get();
if (weatherRequestResponse != "") {
parsedWeatherResponse = ParseWeatherResponseXML
.parseMyTripXML(weatherRequestResponse);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return parsedWeatherResponse;
}
Used CallBack
public class WeatherUpdateAsyncTask extends AsyncTask<String, Void, String> {
Context context;
CallBack callBack;
public WeatherUpdateAsyncTask(CallBack callBack) {
this.callBack = callBack;
}
#Override
protected String doInBackground(String... arg0) {
String responseString = "";
HttpClient client = null;
try {
client = new DefaultHttpClient();
HttpGet get = new HttpGet(arg0[0]);
client.getParams().setParameter("http.socket.timeout", 6000);
client.getParams().setParameter("http.connection.timeout", 6000);
HttpResponse responseGet = client.execute(get);
HttpEntity resEntityGet = responseGet.getEntity();
if (resEntityGet != null) {
responseString = EntityUtils.toString(resEntityGet);
Log.i("GET RESPONSE", responseString.trim());
}
} catch (Exception e) {
Log.d("ANDRO_ASYNC_ERROR", "Error is " + e.toString());
}
Log.d("ANDRO_ASYNC_RESPONSE", responseString.trim());
client.getConnectionManager().shutdown();
return responseString.trim();
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
callBack.run(result);
}
}
requestWeatherUpdate
private WeatherResponse requestWeatherUpdate(String location) {
url = ""
+ location;
Log.d("URL for Weather Upadate", url);
WeatherUpdateAsyncTask weatherReq = new WeatherUpdateAsyncTask(new CallBack() {
#Override
public void run(Object result) {
try {
String AppResponse = (String) result;
response = ParseWeatherResponseXML
.parseMyTripXML(AppResponse);
} catch (Exception e) {
Log.e("TAG Exception Occured",
"Exception is " + e.getMessage());
}
}
});
weatherReq.execute(url);
return response;
}
Frm here i calling
for (int i = 0; i < 4; i++) {
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
RelativeLayout layout = (RelativeLayout) inflater.inflate(
R.layout.sector_details, depart_arrivals_details, false);
depart_time = (TextView)layout.findViewById(R.id.depart_time);
depart_airport_city = (TextView)layout.findViewById(R.id.depart_airport_city);
temprature = (TextView)layout.findViewById(R.id.temprature);
humidity = (TextView)layout.findViewById(R.id.humidity);
flight_depart_image = (ImageView)layout.findViewById(R.id.flight_depart_image);
depart_time.setText("20:45");
depart_airport_city.setText("Mumbai");
/*
* This part will be updated when we will se the request and get the response
* then we have to set the temp and humidity for each city that we have recived
* */
temprature.setText("");//Here i have set the values from the response i recived from the AsynkTask
humidity.setText("");//Here i have set the values from the response i recived from the AsynkTask
flight_depart_image.setImageResource(R.drawable.f1);
depart_arrivals_details.addView(layout, i);
}
Calling get() on an AsyncTask blocks the calling thread. Don't do that. Instead pass the results to the caller in onPostExecute().
Starting with Honeycomb, the default implementation executes asynctasks sequentially on a serial executor. To run asynctasks parallely, use executeOnExecutor(THREAD_POOL_EXECUTOR, ...) instead of execute(...).
You should not use get() . Calling get() does not make the call asynchronous. Instead use execute
weatherRequestResponse = weatherReq.execute(url).get();
get()
public final Result get ()
Added in API level 3
Waits if necessary for the computation to complete, and then retrieves its result.
Returns
The computed result.
Throws
CancellationException If the computation was cancelled.
ExecutionException If the computation threw an exception.
InterruptedException If the current thread was interrupted while waiting.
For parallel execution use executeOnExecutor
weatherReq.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
If your asynctask is an inner class of your activity class you can update ui in onPostExecute. If its not you can use a interface as a callback.
Retrieving a returned string from AsyncTask in Android
How do I return a boolean from AsyncTask?
From the discussion you get NUllPointerException # temprature.setText(parsedWeatherResponse.getTempInC()+(char) 0x00B0);
You have not initialized parsedWeatherResponse. You have only declared it
parsedWeatherResponse = new WeatherResponse();
use executeOnExecutor(THREAD_POOL_EXECUTOR, ...) to run asynctasks parallely. also you can use HttpURLConnection instead of DefaultHttpClient/HttpGet
If you want to connect with network from UI thread , it is quitly difficult. "The exception that is thrown when an application attempts to perform a networking operation on its main thread.
This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness."
If you want to overcome this difficulty then following bellow instruction:
The solution is given below. I found it from another answer. It is working for me. And below import statement into your java file.
import android.os.StrictMode;
Write below code into onCreate
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
I'm new to android, please halp.
This is a really simple scenario, there's an actionbar, and when a tab is selected, I need to send an http request to get an article list, when the response arrives, update a listview and here's where I got this exception.
I'm aware that I should isolate network operations from UI thread, so I implement the network functions in an AsyncTask class.
The most weird part is, before I try to get the article list, I have actually called a network function once to log in, and that just works fine, no exceptions! And guess what, if I replace the get article list call with log in call, it works fine, too. All the code are just the same, except the arguments differ.
Here's how I do it, since too many modules will use the network module, I use a static wrapper:
UI -> Static Factory -> New AsyncTask -> Response arrives -> Call Static callback function in Static Factory -> Call callback function in UI
AsyncTask doInBackground
#Override
protected HttpResponse doInBackground(String... params) {
// TODO Auto-generated method stub
String uri = params[0];
HttpGet get = new HttpGet(uri);
try {
return _client.execute(get);
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
AsyncTask post execute
#Override
protected void onPostExecute(HttpResponse result) {
//Do something with result
if (result != null) {
try {
JSONObject json = FormJsonFromResponse();
Command.OnTaskComplete(json);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static wrapper code:
#Override
public static void OnTaskComplete(JSONObject json) {
// TODO Auto-generated method stub
if(_callback != null) {
_callback.OnCommandComplete(json);
}
}
Here's how I call asynctask in static wrapper:
public static void LogIn(String user, String pass) {
new NetworkTask().execute(_uriPrefix + login, _user, _pass);
}
Revise your AsyncTask following this pattern:
#Override
protected JSONObject doInBackground(String... params) {
// TODO Auto-generated method stub
String uri = params[0];
HttpGet get = new HttpGet(uri);
try {
HttpResponse response = _client.execute(get);
return FormJsonFromResponse();
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
AsyncTask post execute
#Override
protected void onPostExecute(JSONObject result) {
//Do something with result
if (result != null) {
try {
Command.OnTaskComplete( result );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I want to show listview from web directory file list. How to access web directory file list in android.
Ex:http://mp3.com/song/
this is the web directory.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// JSONObject json = JSONfunctions
// .getJSONfromURL("http://selangorbn.fm/song/");
// Log.d("TAG", "json" + json);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
new Getparse().execute();
}
private void parse() throws IOException {
String line = null, response;
URL url = new URL("http://selangorbn.fm/song/");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
while (rd.readLine() != null) {
line += rd.readLine();
}
System.out.println(line);
}
public class Getparse extends AsyncTask<Void, Void, integer> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
#Override
protected integer doInBackground(Void... params) {
// TODO Auto-generated method stub
try {
parse();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(integer result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
getting null value.
This does not work for you because you try to talk with Internet on the main application thread. Doing so would stall the application till the reply is received. Hence Android has internal checks. You should get network on main thread exception from your code.
You need to launch a separate thread and talk with the server from there. After you get your list, use runOnUiThread to update your results (you cannot touch any GUI elements from your network thread).
Parsing HTML is only reasonable if this is all you can get from the uncooperative third party server. As kumar suggests, use JSON or XML if you can.
try {
org.jsoup.nodes.Document doc = Jsoup.connect("https://test.com/appdata/0131").get();
doc.select("img").remove();
Elements links = doc.select("a");
List<String> listmainlinks = new ArrayList<>();
List<String> listweblinks = new ArrayList<>();
for (org.jsoup.nodes.Element link : links) {
String linkInnerH = link.html();
String linkHref = link.attr("href");
System.out.println("linkHref: "+ linkHref);
System.out.println("linkInnerH: "+ linkInnerH);
if(linkInnerH.equals("") ||linkInnerH.equals(" ")||linkInnerH.equals(null) || linkHref.contains("?C=N;O=D")|| linkHref.contains("?C=M;O=A")||linkHref.contains("?C=S;O=A") ||linkHref.contains("?C=D;O=A")){ }
else if(linkHref.contains("/"))
{
if(!linkInnerH.contains("Parent Directory"))
listmainlinks.add(linkHref);
}
else{
listweblinks.add("https://test.com/appdata/0131" + linkHref);
}
}
System.out.println("listmainlinks "+ listmainlinks);
System.out.println("listweblinks "+listweblinks);
/* Elements img = doc.getElementsByTag("img");
int counter = 0;
for (org.jsoup.nodes.Element el : img) {
// If alt is empty or null, add one to counter
if(el.attr("alt") == null || el.attr("alt").equals("")) {
counter++;
}
System.out.println("image tag: " + el.attr("src") + " Alt: " + el.attr("alt"));
}
System.out.println("Number of unset alt: " + counter);*/
} catch (IOException e) {
e.printStackTrace();
}
https://test.com/appdata/
I/System.out: listmainlinks [0216/, 0128/, 0131/]
I/System.out: listweblinks []
https://test.com/appdata/0131/
I/System.out: listmainlinks []
I/System.out: listweblinks [https://test.com/appdata/0131/logo.png]
Using JSOUP you can list all the files in the remote directory. But one problem i faced is if there is home page(Ex: index.html) in that directory, then it is not reading beyond that file. This is one drawback.
You can use jsoup to get the href tags linking with folders with their names
Document doc = Jsoup.connect(urltod).timeout(0).get();
doc.select("img").remove();
Elements links = doc.select("a");
List<String> listmainlinks = new ArrayList<>();
List<String> listnumberslinks = new ArrayList<>();
List<String> listweblinks = new ArrayList<>();
for (Element link : links) {
// String linkOuterH = link.outerHtml(); //allhreaf incl name
String linkInnerH = link.html(); // foldername
String linkHref = link.attr("href"); //folderlink
// System.out.println("linkHref "+linkInnerH );
if(linkInnerH.equals("") ||linkInnerH.equals(" ")||linkInnerH.equals(null) ){ }
else{
if(linkInnerH.contains("size=\"2\"")){
String[] afterfonttagarray =linkInnerH.split("\">");
String afterfonttag = afterfonttagarray[1];
String[] beforefonttagarray =afterfonttag.split("</font>");
String beforefonttag = beforefonttagarray[0];
listmainlinks.add(beforefonttag);
listweblinks.add("http://www.abc.com/audio/"+linkHref);
}
}
System.out.println("listmainlinks "+ listmainlinks); "+listnumberslinks);
System.out.println("listweblinks "+listweblinks);
this will give you the folder name as well as the links associated with them later you can use
ArrayList> albumsList to store and iterate to list or anything