Loading an array from a .txt file? (Android) - android

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.

Related

Blank/black screen on app startup due data downloading?

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.

Trouble opening file with getAssets() inside AsyncTask

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

File after leaving an activity where it was saved, does not refresh in other activities

I have a specific problem. I have an application with many activities. In activity "settings.class" I create "config.txt" file and I save it - everything is OK. When I try to read from this file in the same activity, I get a string which I saved into this file. BUT when I close this activity "settings.class" and I return back to the "MainActivity.class" and I try to read from this "config.txt" file I get an old string which was stored before NOT actually saved...
I solved my problem with restart my application and after that everything is OK. But I want to know why this happens.
Here is my code:
This is in class utilities:
public void WriteSettingFile(String txt_msg, Context ctx) throws IOException
{
FileOutputStream fp = null;
fp = ctx.openFileOutput("edog_con.txt",Context.MODE_PRIVATE);
fp.write(txt_msg.getBytes());
fp.close();
}
private String ReadSettingFile(Context ctx) throws IOException
{
FileInputStream fp;
String tmp_string;
StringBuilder sb = null;
fp = ctx.openFileInput("edog_con.txt");
if (fp != null)
{
InputStreamReader isr = new InputStreamReader(fp);
BufferedReader br = new BufferedReader(isr);
sb = new StringBuilder();
while( (tmp_string = br.readLine()) != null)
{
sb.append(tmp_string);
}
fp.close();
}
return sb.toString();
}
// Vrati ulozene telefonne cislo
public String GetPhoneNumber (Context ctx)
{
String tmp = "";
String[] casti;
// Nacitanie suboru. Ak nie je, tak vrat chybu
try
{
tmp = ReadSettingFile(ctx);
}
catch (IOException e)
{
return "err";
}
// Ak retazec obsahuje ',' - mal by - tak pokracuj. Ak nie chyba
if (tmp.contains(","))
{
// rozdel string na dve casti - pred a po ciarke. pred je tel. cislo
casti = tmp.split(",");
}
else
return "err";
return casti[0];
}
This is in the Setting.class where I am writing to the .txt file. When I try to read from file in this activity class, everything is OK and I have an actual data saved into .txt file
public class Settings extends Activity
{
....
// Save button and so on
...
Utilities ut = new Utilities();
try
{
ut.WriteSettingFile(save_info, Settings.this);
}
catch (IOException e)
{
alert_msg.setMessage(R.string.alert_bad_file).show();
}
// I have to reset the application instead of this - and then it works
Settings.this.finish();
....
}
And when I try to read from file in this fragment Water.class , I read previous saved string not actually saved. I have to reset application so previous "Settings.this.finish()"
I dont use, and I reset a whole application programatically.
Water.class
public class Water extends Fragment
{
...
Utilities ut = new Utilities();
String data;
...
// This gets an old saved string in .txt file
data = ut.GetPhoneNumber(this.getActivity())
}

Need a simple tutorial for android/webservice work?

I'm really new working with Android, so there's a lot that's confusing me. I've looked at what seems like 100 tutorials and examples of how to get information from a web service on Android, but what I need is something for a guy that doesn't have a clue. Here are a couple of things in particular that I'm not getting:
I don't know what to do with XML files.. meaning, once I do the Java work, is that all that needs to be done? or does anything need to be changed in the XML files?
Seems like maybe I'm supposed to create a new class for some of these tutorials, but I'm not sure, and if so, I'm not sure what to do once I've made the class
I want to retrieve the information in JSON format. For right now as long as I can get just that information that's fine, I can learn how to work with JSON later.
It seems like kSoap2 is the best way to do this. I have the jar file that's needed to work with it
I've delved a little into phonegap, so if there's an answer that uses that, then I can work with that
My web service is working properly, and is essentially the same as what I've seen in a number of tutorials, so there's no problem there.
If anyone can point me to a tutorial that will help me out to learn ALL that I need to know to create a sample app that gets information from my web service, or if anyone is willing to walk me through it, I would greatly appreciate it!
Thanks in advance!
Initially you have to make an http connection so that you can get the response from your api be it xml response or json response. You can use the following code for it.
Keep the class separate than activity. :-
public class Response {
String get_url, response;
Activity activity;
public Response(String url){
this.get_url = url;
}
public String getResponse(){
InputStream in = null;
byte[] data = new byte[1000];
try {
URL url = new URL(get_url);
URLConnection conn = url.openConnection();
conn.connect();
/* conn.*/
in = conn.getInputStream();
Log.d("Buffer Size +++++++++++++", ""+in.toString().length());
BufferedReader rd = new BufferedReader(new InputStreamReader(in),in.toString().length());
String line;
StringBuilder sb = new StringBuilder();
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
response = sb.toString();
in.read(data);
Log.d("INPUT STREAM PROFILE RESPONSE",response);
in.close();
} catch (IOException e1) {
Log.d("CONNECTION ERROR", "+++++++++++++++++++++++++++");
// TODO Auto-generated catch block
e1.printStackTrace();
}
return response;
}
}
You may call the class in your activity like this :-
Response res = new Response("your_url");
String getResponse = res.getResponse();
So here you get the response from the api.
Now Lets make the parser
//Extend the class with Default Handler
public class XMLParser extends DefaultHandler {
//You must have basic knowledge about Array List and setter/getter methods
// This is where the data will be stored
ArrayList<Item> itemsList;
Item item;
String data;
String type;
private String tempVal;
//Create the Constructor
public XMLParser(String data){
itemsList = new ArrayList<Item>();
this.data = data;
}
public byte parse(){
SAXParserFactory spf = null;
SAXParser sp = null;
InputStream inputStream = null;
try {
inputStream = new ByteArrayInputStream(data.getBytes());
spf = SAXParserFactory.newInstance();
if (spf != null) {
sp = spf.newSAXParser();
sp.parse(inputStream, this);
}
}
/*
* Exceptions need to be handled MalformedURLException
* ParserConfigurationException IOException SAXException
*/
catch (Exception e) {
System.out.println("Exception: " + e);
e.printStackTrace();
} finally {
try {
if (inputStream != null)
inputStream.close();
} catch (Exception e) {
}
}
if (itemsList != null && itemsList.size() > 0) {
// //Log.d("Array List Size",""+tipsList.get(4).getTitle());
return 1;
} else {
return 0;
}
}
public ArrayList<Item> getItemList(){
return itemsList;
}
// Here you can check for the xml Tags
#Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(localName.equalsIgnoreCase("item")){
item = new Item();
Log.d("Working", "+++++++++++++++++++++++");
}
}
//tempVal is the variable which stores text temporarily and you
// may save the data in arraylists
public void characters(char[] ch, int start, int length)
throws SAXException {
tempVal = new String(ch, start, length);
}
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(localName.equalsIgnoreCase("item")){
itemsList.add(item);
Log.d("Working in endelement", "+++++++++++++++++++++++");
item.setTitle(tempVal);
}
}
Combining all this :-
Now lets see the activity
public void oncreate(){
// Do something or mostly the basic code
// Call the class to initate the connection and get the data
FetchList fl = new FetchList();
fl.execute();
}
//Always better to use async task for these purposes
public class FetchList extends asyncTask<Void,Void,Byte>{
doinbackground{
// this was explained in first step
Response res = new Response("url");
String response = res.getResponse();
XmlParser xml = new XmlParser(response);
ArrayList<item> itemList = xml.getItemList();
xml.parse();
}
}
Well that is all to it.

Using utility classes in the android programming

I have a little idea of the Utility Classes with a slight doubt on demand.
If I use a Utility class in my Application than to use that class in my main Activity do I have to create the object of that class or I can directly Import that class in my main activity?
I am Sorry if I am not making a clear sense.
In the nutshell, all I want to be clear about is that basically how can I use the utility class in my Main Activity?
Thanks,
david
It mainly depends on what your utility class does. But, most of the time, if you create an Utility class, you will want to create static methods and invoke them without creating an instance:
class MyUtilities{
public static String foo(String bar){
return bar.toUppercase;
}
}
Then, on your activity:
MyUtilities.foo("baz");
Of course, there are cases where you will want to create instance of a Utility class. For instance, if you have created a global Adapter which will be used by all your ListViews.
It heavily depends on what kind of utility you're referring to. There are
1) utility classes that implement static methods. In that case you just call them directly using class name
2) utility classes methods that are not static - requires creating and possibly initializing an instance of that class. Then the instance is used to call those methods.
3) utility classes that can be accessed thru Context. then you can call getApplicationContext() and then you can get access to the utility classes
public final class Utils
{
private Utils()
{
}
public static void makeToast(Context context, String text){
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
}
It's usually a class which only has static methods (possibly with a private constructor and marked abstract/final to prevent instantiation/subclassing). It only exists to make other classes easier to use - for example, providing a bunch of static methods to work with String values, performing extra actions which String itself doesn't support.
Utility classes generally don't operate on classes you have control over, as otherwise you'd usually put the behaviour directly within that class. They're not terribly neat in OO terms, but can still be jolly useful.
as answered by Jon Skeet
If the methods in your utility class are static then you can call them from your main activity. eg:
int i = Utility.RandInt();
If they are not static then you have to create an object:
Utility u = new Utility();
int i = u.randInt();
If your utility class is created in your Application then you can refer to it by first creating a getMethod in the application class, then going
Application mc = (Application) context.getApplicationContext();
mc.getUtilityClass().SomeMethod()
I dont know what yiur exact question is. But here is a code where I used Utility class in my activity. AnimationUtil is used to load animation onto a ImageView.
ImageView waitImg = (ImageView) findViewById(R.id.ImageView02);
Animation waitAnim = AnimationUtils.loadAnimation(this, R.anim.wait_rotate);
waitImg.startAnimation(waitAnim);
waitAnim.cancel();
waitAnim.reset();
public class Utils {
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager
.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
public static void unlockScreenOrientation(Activity activity) {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
public static void lockScreenOrientation(Activity activity) {
int currentOrientation = activity.getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_PORTRAIT)
{
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
else
{
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}
// Get Http Post response
#Nullable
public static String getHttpResponse(String url, List<NameValuePair> nameValuePairs) {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
UrlEncodedFormEntity entity;
try {
entity = new UrlEncodedFormEntity(nameValuePairs);
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
HttpEntity resEntity = response.getEntity();
String res = EntityUtils.toString(resEntity);
return res;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void CopyStream(InputStream is, OutputStream os) {
final int buffer_size=1024;
try
{
byte[] bytes=new byte[buffer_size];
for(;;)
{
int count=is.read(bytes, 0, buffer_size);
if(count==-1)
break;
os.write(bytes, 0, count);
}
}
catch(Exception ex){}
}
public static JSONObject getJsonObjectFromXmlResponse(String xmlString) {
JSONObject objectJson = new JSONObject();
//JSONArray arrayJson = new JSONArray();
XmlPullParser parser = Xml.newPullParser();
try {
parser.setInput(new StringReader(xmlString));
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
String name;
switch (eventType) {
case XmlPullParser.START_TAG:
name = parser.getName();
if (name.equalsIgnoreCase("string")) {
String yourValue = parser.nextText();
//arrayJson = new JSONArray(yourValue);
objectJson = new JSONObject(yourValue);
}
break;
}
eventType = parser.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return objectJson;
}
}

Categories

Resources