I'm trying to write a class that iterates through a textfile, it looks like this (it's ~5000 lines):
Postnr Poststad Bruksområde Kommunenummer Lat Lon Merknad Nynorsk Bokmål Engelsk
0001 Oslo Postboksar 301 59.91160 10.75450 Datakvalitet: 2. Koordinatar endra 28.09.2012. Oppdatert 04.12.2012 url1 url2 url3
My trouble is: the method getassets is undefined for the type SearchTabTxt
I'm trying to read the file from the assets folder and I can't seem to find a solution to this. I tried to write a search class for this:
public class SearchTabTxt extends AsyncTask<String, Void, ArrayList<String[]>> {
protected ArrayList<String[]> doInBackground(String... inputString) {
ArrayList<String[]> list = new ArrayList<String[]>();
try {
InputStream is = getAssets().open("file.txt");
if (is != null) {
String search = inputString[0].toString();
InputStreamReader inputreader = new InputStreamReader(is,
"UTF-8");
BufferedReader buffreader = new BufferedReader(inputreader);
int antallTreff = 0;
while (buffreader.readLine() != null) {
ArrayList<String> placeInformation = new ArrayList<String>();
if (buffreader.readLine().contains(search)) {
antallTreff++;
System.out.println("Found: " + search);
placeInformation.clear();
for (String i : buffreader.readLine().split("\t")) {
placeInformation.add(i);
}
System.out.println(placeInformation.get(11));
// Sorry about the Norwegian will rewrite
if (antallTreff >= 3) {
System.out.println("Did I find something?");
break;
}
if (buffreader.readLine() == null) {
break;
}
}
}
}
} catch (ParseException e) {
Log.e("Error", e + "");
} catch (ClientProtocolException e) {
Log.e("Error", e + "");
} catch (IOException e) {
Log.e("Error", e + "");
}
return list;
}
}
Well it's simple. There is no method getAssets() in your SearchTabTxt class. To get the assets, you need a Context. Make a public constructor to your SearchTabTxt class, and pass a Context.
private Context context;
public SearchTabTxt (Context myContext) {
this.context = myContext;
}
Now in the doINbackground method you can do:
InputStream is = context.getAssets().open("file.txt");
Now in the Activity when you createyour AsyncTask you can start the task like this: new SearchTabTxt(this).execute(params); This works because your Activity (this) is a subtype of Context.
More on this here: getAssets(); from another class
Related
I am storing the data that I parsed from the JSON that is returned by my API request into the Firebase database.
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String APIURL = "https://api.github.com/users/" + idInput.getText().toString();
String repoURL = "https://api.github.com/users/" + idInput.getText().toString() + "/repos";
new JSONTask().execute(APIURL);
//new JSONTask().execute(repoURL);
String parsedUserID = idInput.getText().toString();
SM.sendDataToProfile(parsedUserID);
viewPager.setCurrentItem(1);
//addUser(parsedUserID);
}
});
When the button is clicked, it calls a new JSONTask (asynctask) on the APIURL.
JSONTask
public class JSONTask extends AsyncTask<String, String, String> {
#Override
// Any non-UI thread process is running in this method. After completion, it sends the result to OnPostExecute
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
// Pass in a String and convert to URL
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
// Reads the data line by line
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer strBuffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
strBuffer.append(line);
}
// If we are able to get the data do below :
String retreivedJson = strBuffer.toString();
return retreivedJson;
// When we are not able to retreive the Data
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
// close both connection and the reader
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
And it does parsing in another function.
My question is, as you can see on my setOnClickListener, I tried to make two JSONTask on two different URLs because the first URL gives me the information of the user and the second URL (repoURL) gives me the information of the user's repositories. I tried to fetch the repo info of the user and store it into the DB, but it seems like this is a wrong approach.
What is a right way to call two separate AsyncTasks on two different URLs?
EDIT
private void addUserRepo(final String githubID, final String[] repoList) {
DatabaseReference users = databaseReference.child("users");
users.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List list = new ArrayList<String>(Arrays.asList(repoList));
databaseReference.child("users").child(githubID).child("Repos").setValue(list);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Using data parsed from
public void formatJSONArray(String results){
try {
JSONArray jsonArray = new JSONArray(results);
RepoInfo[] repoList = new RepoInfo[jsonArray.length()];
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject=jsonArray.getJSONObject(i);
if(jsonObject.optString("name") != null) {
repoList[i].setRepoName(jsonObject.getString("name"));
//repoNameList.add(jsonObject.getString("name"));
}
if(jsonObject.optString("description") != null) {
repoList[i].setDescription(jsonObject.getString("description"));
//descriptionList.add(jsonObject.getString("description"));
}
if(jsonObject.optJSONObject("owner") != null){
JSONObject ownerObject=jsonObject.getJSONObject("owner");
if(ownerObject.optString("login")!=null) {
repoList[i].setOwner(ownerObject.getString("login"));
//userNameList.add(ownerObject.getString("login"));
}
}
}
} catch (JSONException jsonException){
}
}
The response of two different URLs will surely not be similar. So you need different parse methods for them.
One lazy way would be to use two different AsyncTasks subclasses for two different urls.
Another way would be to store a flag inside the asynctask indicating whether it is dealing with user or repo.
public class JSONTask extends AsyncTask <String , String , String> {
boolean fetchingRepo;
#Override
protected String doInBackground (String... params) {
fetchingRepo = params[0].endsWith("/repos");
//other statements
}
Now inside onPostExecute:
if(fetchingRepo){
//parse one way
} else {
//parse another way
}
So here in Java I've written a typical class, to send json to a rest server. (I'll include the whole class below for clarity.) So that's a file "Fetcher.java"
Now for the callback you need an interface. The interface is trivial, just one function with a string.
public interface FetcherInterface {
public void fetcherDone(String result);
}
Annoyingly you need a whole file for that, "FetcherInterface.java"
So this interface is nothing but "one callback with a string". Often all you need is just "one callback with no arguments".
In fact ........ are there some sort of standard interfaces I can use, or something like that?
It seems kind of annoying to have to put in a whole interface for such a simple "standard" interface.
What's the deal on this? What's the javaly solution?
It seems you CAN NOT put it in the same file:
Perhaps I misunderstand something there. If you could put it in the same file, that would be convenient at least.
(Lambdas are not yet practically available. Anyway, sometimes you want an interface.)
Just for clarity, here's how you call the class
JSONObject j = new JSONObject();
try {
j.put("height", 2.1);
j.put("width", 2.5);
j.put("command", "blah");
} catch (JSONException e) {
e.printStackTrace();
}
new Fetcher("mobile/login", j, new FetcherInterface() {
#Override
public void fetcherDone(String result) {
Log.d("DEV","all done");
doSomething(result);
}
}
).execute();
or indeed
public class HappyClass extends Activity implements FetcherInterface {
...
private void someCall() {
JSONObject j = new JSONObject();
try {
j.put("height", 2.1);
j.put("width", 2.5);
j.put("command", "blah");
} catch (JSONException e) {
e.printStackTrace();
}
new Fetcher("mobile/data", j, this).execute();
devBlank();
}
#Override
public void fetcherDone(String result) {
Log.d("DEV","all done" +result);
doSomething(result);
}
Here's the whole class... Fetcher.java file
public class Fetcher extends AsyncTask<Void, Void, String> {
private String urlTail;
private JSONObject jsonToSend;
private FetcherInterface callback;
// initializer...
Fetcher(String ut, JSONObject toSend, FetcherInterface cb) {
urlTail = ut;
jsonToSend = toSend;
callback = cb;
}
#Override
protected String doInBackground(Void... params) {
HttpURLConnection urlConnection = null; // declare outside try, to close in finally
BufferedReader reader = null; // declare outside try, to close in finally
String rawJsonResultString = null;
String json = jsonToSend.toString();
Log.d("DEV","the json string in Fetcher is " +json);
try {
URL url = new URL("https://falcon.totalfsm.com/" + urlTail);
Log.d("DEV","the full URL in Fetcher is " +url);
// open a json-in-the-body type of connection.......
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setConnectTimeout(5000);
// urlConnection.setDoOutput(false); // can be important?
urlConnection.connect();
OutputStream os = urlConnection.getOutputStream();
os.write(json.getBytes("UTF-8"));
os.close();
// annoyingly, you have to choose normal versus error stream...
InputStream inputStream;
int status = urlConnection.getResponseCode();
if (status != HttpURLConnection.HTTP_OK)
inputStream = urlConnection.getErrorStream();
else
inputStream = urlConnection.getInputStream();
if (inputStream == null) { // nothing to do.
return null;
}
StringBuffer buffer = new StringBuffer();
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) { // adding newlines makes debugging easier
buffer.append(line + "\n");
}
if (buffer.length() == 0) { // stream was empty
return null;
}
rawJsonResultString = buffer.toString();
return rawJsonResultString;
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d("DEV", "Fetcher done");
if (s==null) {
Log.d("DEV","applying anti-null measures in Fetcher!");
s = "message from app communications layer: 'null' returned from servers for that call at " +urlTail;
}
callback.fetcherDone(s);
}
}
I feel bad answering my own question, but as there were no other answers this info may be helpful.
DaveNewton and Rowtang have supplied the exact answers here:
(Point 1) If you want a genuinely public interface, it goes in its own file. That's how Java works. There's no alternative.
(Point 2) Normally, use protected interface and declare the interface inside the class. It can then be used throughout the app.
So...
public class Fetcher extends AsyncTask<Void, Void, String> {
protected interface FetcherInterface {
public void fetcherDone(String result);
}
private String urlTail;
private JSONObject jsonToSend;
private FetcherInterface callback;
Fetcher(String ut, JSONObject toSend, FetcherInterface cb) {
urlTail = ut;
jsonToSend = toSend;
callback = cb;
}
#Override
protected String doInBackground(Void... params) {
....
(c# programmers would maybe call it "IFetcher".)
I Googled alot, but no chance for this.
For now, i a have an Inner AsyncTask class that i want to use the return values in the upper class.
And it successfully work, cause i have put a Log.e() and it shows my value, Here is my code :
public class Consume extends AsyncTask<Void, Void, Void> {
private List<LatLng> latLngs = new ArrayList<>();
private List<ContactModel> contacts = new ArrayList<>();
InputStream inputStream = null;
String result = "";
#Override
protected Void doInBackground(Void... params) {
String URL = "http://x.x.x.x/MYWCF/Service1.svc/Json/getContact";
ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(URL);
post.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(post);
HttpEntity httpEntity = httpResponse.getEntity();
inputStream = httpEntity.getContent();
} catch (UnsupportedEncodingException e1) {
Log.e("UnsupportedEncoding", e1.toString());
e1.printStackTrace();
} catch (ClientProtocolException e2) {
Log.e("ClientProtocolException", e2.toString());
e2.printStackTrace();
} catch (IllegalStateException e3) {
Log.e("IllegalStateException", e3.toString());
e3.printStackTrace();
} catch (IOException e4) {
Log.e("IOException", e4.toString());
e4.printStackTrace();
}
try {
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sBuilder = new StringBuilder();
String line = null;
while ((line = bReader.readLine()) != null) {
sBuilder.append(line + "\n");
}
inputStream.close();
result = sBuilder.toString();
} catch (Exception e) {
Log.e("StringBuilding", "Error converting result " + e.toString());
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
List<ContactModel> contactModels;
List<LatLng> myLatLngs = new ArrayList<>();
try {
JSONObject object = new JSONObject(result);
JSONArray jArray = object.getJSONArray("getContactResult");
Type listType = new TypeToken<List<ContactModel>>() {
}.getType();
contactModels = new Gson().fromJson(String.valueOf(jArray), listType);
setContacts(contactModels);
setContacts(contactModels);
for(ContactModel contactModel : contactModels) {
Double latitude = Double.valueOf(contactModel.getLatitude());
Double longitude = Double.valueOf(contactModel.getLongitude());
LatLng latLong = new LatLng(latitude, longitude);
myLatLngs.add(latLong);
}
setLatLngs(myLatLngs);
Log.e("SizeOfArray", myLatLngs.size()+"");
} catch (JSONException e) {
e.printStackTrace();
}
}
public void setContacts(List<ContactModel> contacts) {
this.contacts = contacts;
}
public List<ContactModel> getContacts() {
return contacts;
}
public void setLatLngs(List<LatLng> latLngs) {
this.latLngs = latLngs;
}
public List<LatLng> getLatLngs() {
return latLngs;
}
And in my Activity Class :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.osmdroid_map);
Consume consume = new Consume();
consume.execute();
When i run the app, cause of the line :
Log.e("SizeOfArray", myLatLngs.size()+"");
it returns me the correct int number of array size in logcat, But i want to use that in my App,
I even do all stuff in doInBackground method, and even make a static variable,
No chance.
Can any one give a real sample by my code?
Thx
As far as your AsyncTask class is an inner class. It can directly access objects of outer class.
Create an object of below at your outer class level.
List<LatLng> myLatLngs = new ArrayList<>();
And remove same from inner class so that single object instance will be their.
Another approach will be to use callback from your inner asyntask you need to have interface callback to outer class to start further process.
interface CallBack {
public void processingDone();
}
Consume consume = new Consume(new CallBack() {
#Override
public void processingDone(List<LatLng> mLatLngs) {
// Do your stuff here
}
});
consume.execute();
And inside your Consume constructor store callback to pass data back to outer class.
class Consume {
private Callback mCallback;
public Consume(Callback callback) {
mCallback = callback;
}
}
And from below link you can do
if (mCallback != null) {
mCallback.processingDone(myLatLngs);
}
Log.e("SizeOfArray", myLatLngs.size()+"");
First of all I will say that you should use static inner class instead of non-static inner class to avoid memory leaks as non-static inner class holds reference to the outer class. Another thing is that you can pass a WeakReference of outer parent class so that you can return the value from onPostExecute() of AsyncTask like
public static class Consume extends AsyncTask<Void, Void, Void> {
WeakReference<MainActivity> mActivity;
public Consume(MainActivity activity){
mActivity = new WeakReference<SampleActivity>(activity);
}
}
In your AsyncTask's onPostExecute method it will be
mActivity.response(latLngs);
And in your other class it will be like
private static void response(List<LatLng> latLngs){
// handle response here in your outer class
}
Update: Here is how you can pass WeakReference of Activity to Inner or Anonymous class and use it.
Thx all, for all replies.
Thx, I really did not understand what the problem is and cause of that i asked this simple question ! And unfortunately none of you notice that.
After the code :
Consume consume = new Consume();
consume.execute():
Compiler goes to execute next code too,Cause consume.execute() start another thread but the main thread continues.
Cause of that i received the value i wanted with a delay and therefore i though the problem is how to get the value,
But actually the problem was that i could not handle the thread asynchronization.
So i moved all them in onPre and onPost methods of AsyncTask class,And then it worked !
I am currently working with the tab host and fragment. Currently I set fragment a to download json A and fragment B to download json B , the problem is when I switch fragment, the fragment A onPostExecute function will fall into the fragment B one , is there any way to fix this?
Thanks
Tab host:
tabHost = (FragmentTabHost) findViewById(R.id.tabhost);
tabHost.setup(this, getSupportFragmentManager(), R.id.tabcontent);
tabHost.addTab(
tabHost.newTabSpec("Home").setIndicator("",
res.getDrawable(R.drawable.btn_about)), Home.class,
null);
tabHost.addTab(
tabHost.newTabSpec("About").setIndicator("",
res.getDrawable(R.drawable.btn_about)), About.class,
null);
The async task
public class JSONReader {
public static final String TAG = "JSONReader";
public ArrayList<Record> records;
public Record myRecordObj;
public ArrayList<GalleryImage> images;
public String url;
public int failCount = 0; // retry twice
public Context ctx;
public String readCase;
public JSONReader(String _url, Context _ctx , String _readCase) {
url = _url;
ctx = _ctx;
readCase = _readCase;
}
public void getJSON() {
new JSONDownload().execute(url);
}
private class JSONDownload extends AsyncTask<String, Void, JSONObject> {
// TODO Auto-generated method stub
StringBuilder builder = new StringBuilder();
String temp = "";
String json = ""; // json content
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
#Override
protected JSONObject doInBackground(String... params) {
// TODO Auto-generated method stub
try {
Log.d(TAG, "Start reading: " + url);
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
return null;
// return "Server returned HTTP " + connection.getResponseCode()
// + " " + connection.getResponseMessage();
input = connection.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(input));
while ((temp = reader.readLine()) != null) {
builder.append(temp);
}
json = builder.toString();
} catch (Exception e) {
return null;
} finally {
try {
if (input != null)
input.close();
if (output != null)
output.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
try {
return new JSONObject(json);
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(JSONObject result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
onJSONDownloaded(result);
}
}
public void onJSONDownloaded(JSONObject result) {
// TODO Auto-generated method stub
if (result != null) {
failCount = 0;
if (readCase.equals("leaderBoard")){
records = new ArrayList<Record>();
try {
JSONObject myRecord = result.getJSONObject("myRecord");
if (myRecord != null) {
myRecordObj = new Record(myRecord.getString("pic"),myRecord.getString("name"),myRecord.getString("score"));
}
JSONArray topRecords = result.getJSONArray("topRecord");
for (int i = 0; i < topRecords.length(); i++) {
JSONObject topRecord = topRecords.getJSONObject(i);
String topName = topRecord.getString("name");
String topPic = topRecord.getString("pic");
String topScore = topRecord.getString("score");
records.add(new Record(topPic, topName, topScore));
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
((LeaderBoardDetail)ctx).setData(records,myRecordObj);
} else if (readCase.equals("galleryList")){
images = new ArrayList<GalleryImage>();
try {
JSONArray imageList = result.getJSONArray("images");
for (int i = 0; i < imageList.length(); i++) {
JSONObject image = imageList.getJSONObject(i);
images.add(new GalleryImage(image.getString("url"),image.getString("thumbUrl"),image.getString("category"),image.getString("userPic"),image.getString("name")));
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//exception
if (((FragmentActivity) ctx).getSupportFragmentManager().findFragmentById(R.id.tabcontent).getTag().equals("Gallery")) {
PhotoGallery galleryFragment = (PhotoGallery) ((FragmentActivity) ctx).getSupportFragmentManager().findFragmentById(R.id.tabcontent);
galleryFragment.setData(images);
}
}
} else {
if (failCount <= 1) { // check global_conf twice if fail
failCount++;
Log.d(TAG, "No of retry" + failCount);
new JSONDownload().execute(url); // Retry download json
} else {
failCount = 0;
}
}
}
}
I used it in my app this way which works for me and answer is a bit similar to another answer but few additions and more detail. Hope it help you too.
NOTE: This is just a idea, u need to try, it may vary as per your app architect.
At your activity make the task object global [make sure set task obj null once task is finish]
JSDownload js = null;
public void getJSON() {
if(js != null && js.getStatus() == AsyncTask.Status.RUNNING)
{
js.cancel(true);
if(js.isCancelled())
{
js = new JSONDownload();
js.execute(url);
}
else
{
js = new JSONDownload();
js.execute(url);
}
}
At the Async class side....[make sure u take care null result # onpostExcute]
class JSONDownload extends AsyncTask<String, Void, JSONObject>
{
protected JSONObject doInBackground(String... params) {
// TODO Auto-generated method stub
try {
if(!this.isCancelled())
{
//make http connection ..
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
//as we are in steps in bg check iscancel .. again
//if its a loop here we call break; and return null once only..
if(this.isCancelled())
return null;
// connection status check and get buffer etc .. code here
if(this.isCancelled())
return null;
//read data
return data;
}
} catch (Exception e) {
return null;
}
}
#Override
protected void onCancelled(){
// If you write your own implementation, do not call super.onCancelled(result).
}
}
Use the global async task variable
LongOperation LongOperationOdeme = new LongOperation();
and set:
LongOperationOdeme.cancel(true);
This will stop any async task running at that moment, it's what the back button does
If you are not looking for a simplest answer but for a maybe more interesting and elegant, have a peek at this article, especially if you find functional programming interesting.
It's easier than it looks, i was almost unfamiliar to FP before this article but it covers common problems related to AsyncTask and asynchronicity in Android in general, so I got the gist and consider to use Observables instead of AsyncTask in the future projects myself. It is RxJava and it can solve your problem gracefully: "The fromFragment call transforms the given source observable in such a way that events will only be emitted to the fragment if it’s still alive and attached to its host activity."
One more citation form the article: "What if the user decides to back out of the Activity that triggered the task, and we are holding on to a stale reference. This not only creates a substantial memory leak, but is also worthless because meanwhile it has been detached from the application window. A problem that everyone is well aware of."
I've searched around and haven't been able to coem up with a solution to this one..
my (first) problem is that i'm getting NPE on FileInputStream instream = context.getApplicationContext().openFileInput(textname);in the getLengthOfText(); method. I've debugged and the correct filename appears to be passed to this method. I've been stuck on this for weeks and really want it to work (newb).
this method is being called by another class. Also, the files are there in data/data and everything else is as it should be. please help!!
-Tricknology
/***** this class takes a text file and loads it into an array **/
public class loadArray {
Context context;
textWriter textwriter;
public loadArray (Context cxt) {
this.context = cxt;
textwriter = new textWriter (cxt);
context = cxt;
}
FileInputStream instream;
textWriter tw = new textWriter(context);
String[] choiceAry, dummyAry;
P p = new P(); // shared prefs helper
String Choice;
String comp = "notnull";
int addChoiceCount, length;
// Context context = this.getApplicationContext();
public void buildDummies(int length) {
// addChoiceCount = p.gisI("addChoiceCount");
choiceAry = new String[length];
p.pisI("length", length, context);
// dummyAry = new String[100];
}
public Integer getLengthOfText(String textname)
throws FileNotFoundException {// counts how many lines of text
// DataInputStream dis = new DataInputStream(openFileInput("file.dat"));
int length = 0;
instream = context.getApplicationContext().openFileInput(textname);
InputStreamReader inputreader = new InputStreamReader(instream);
BufferedReader buffreader = new BufferedReader(inputreader);
try {
// while (!comp.equals(null)){
while (buffreader.ready()) {
String temp = buffreader.readLine();
length++;
}
buffreader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return length;
}
public String[] laft(String textname) throws FileNotFoundException {
// loads a text file to an array...load array from text........
length = getLengthOfText(textname);
buildDummies(length);
try {
instream = context.getApplicationContext().openFileInput(textname);
InputStreamReader inputreader = new InputStreamReader(instream);
BufferedReader buffreader = new BufferedReader(inputreader);
// load array from text
for (int i = 0; i < (length); i++) {
try {
Choice = buffreader.readLine();
choiceAry[i] = Choice;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
buffreader.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return choiceAry;
}
public String getOrderName() {
// TODO Auto-generated method stub
return null;
}
}
I found the answer thanks to Leeds and billiard from #android-dev
what I was doing is also calling loadArry from another class that did not extend activity.. so it was activity >calling> class that doesnt extend activity >calling> class that doesnt extend activity. somehow in there the context was lost. I basically applied similar lines at the top starting with
Context context;
textWriter textwriter;
public loadArray (Context cxt) {
this.context = cxt;
textwriter = new textWriter (cxt);
context = cxt;
hope this saves someone a lot of time in the future.
You have made things much too complicated for yourself in the code. In the end, complicated code = harder debugging.
I load text files into arrays all the time.
Consider using the java.util.StringTokenizer class or the String split() method in class java.lang.String.
TenFour4 brings up another good point.
This is what the code should look like...
Context context;
textWriter textwriter;
public loadArray (Context cxt){
this.context = cxt;
textwriter = new textWriter (cxt);
}
--UPDATE--
A common mistake is that the file you are trying to read from has not been closed properly, therefore you are getting a NullPointerException whenever you try to access the still open file.
e.g.
PrintWriter pw = new PrintWriter (new FileWriter (fileName));
pw.println ("This is output data: " + data);
//new loadArray ().getLengthOfText (fileName); //ERROR Throws NPE
pw.close(); //Make Sure you Close Before trying to read the file again!
new loadArray ().getLengthOfText (fileName); //Works like a charm :)
As it seems to me, the only reason you may get NPE in the line you said you get it is that context is somehow NULL (openFileInput doesn't throw NPE) make sure that context is not NULL.
Your textWriter instance is getting instantiated while context is still null. Any definitions that occur outside of methods will happen before the constructor is called.
By the way, class names should start with a capital letter and not start with a verb, by convention. It will help you avoid errors and be easier for other people to understand.