1

I used to be somewhat active on this forum but i became busy and had no time to program anymore, anyway i am back into it now and i need some help...

How would i go about having my app take live stats from a CSV file that is located on my network.... The CSV file is updated about every minute so i need a way to read directly from the network.... The program also has to sort through the csv file and only pull out certain values but i am going to worry about that aspect later after i figure out this issue. could anyone help? Thanks!

Mr. Pivirotto
  • 281
  • 2
  • 6
  • 23
  • 1
    Give us a clue... How is the CSV exposed. "On a network" Do you mean in a windows share? Exposed through a webserver? Is the android client going to be connected directly to the network in question (eg wifi) or routing via the internet? – Basic Jan 16 '13 at 20:42
  • @Basic The android client is going to be connected directly to the network from the wifi. The csv file that i am trying to reach is located on a G:/ drive – Mr. Pivirotto Jan 16 '13 at 21:25
  • If the csv file is just stored on a local drive on a computer and not shared/exposed any way, you won't be able to access it - imagine what a security risk that would be - you'll need to expose the file some way either using a webserver, a windows share (aka UNC or Samba share), ftp server, etc, etc... The mechanism you pick will will inform the implementation of your app. The most flexible is probably a webserver but the easiest to set up is likely to be a Samba share – Basic Jan 16 '13 at 21:55

4 Answers4

2

Assuming you are interested in a file on the web server. You have 2 solutions here. Make your G: drive a network share or install Apache for windows and use a derivation of my code to get the csv file from the webserver.

Network share route:

You'll need a Samba client like AndSMB for your Android device. This will be used to mount the shared drive from your windows box and copy the file to your device. You'll then need to open the file like you would any other. Use this Q/A as a starting point: reading a specific file from sdcard in android

Apache route:

Install and configure Apache: http://httpd.apache.org/docs/2.2/platform/windows.html

This should be adaptable to what you want to do. Your caller would implement something like my callback. The caller instantiates the class that implements the AsyncTask. This is used to keep the network traffic off of the main GUI thread. You'll have issues on 3.0(?) and above if you don't. Slice and dice the code to your needs. I really do need to get this up as a project on github. The project is here for anyone who would need the full code: https://github.com/nedwidek/Android-Rest-API

Callback:

package com.hatterassoftware.restapi;

import java.net.URL;
import java.util.HashMap;

import android.os.AsyncTask;
import android.util.Log;

/**
 * An AsyncTask implementation for performing POSTs on the Hypothetical REST APIs.
 */
public class GetTask extends AsyncTask<String, String, HttpReturn>{
    private String restUrl;
    private RestCallback callback;
    private HashMap<String, String> headers;
    private String username;
    private String password;

    final String TAG = "GetTask";

    /**
     * Creates a new instance of PostTask with the specified URL, callback, and
     * request body.
     * 
     * @param restUrl The URL for the REST API.
     * @param callback The callback to be invoked when the HTTP request
     *            completes.
     * @param requestBody The body of the POST request.
     * 
     */
    public GetTask(String restUrl, RestCallback callback, HashMap<String, String> headers, String username, String password){
        this.restUrl = restUrl;
        this.callback = callback;
        this.headers = headers;
        this.username = username;
        this.password = password;
    }

    @Override
    protected HttpReturn doInBackground(String... params) {
        try {
            RestHttpUrlConnection request = new RestHttpUrlConnection(new URL(restUrl), headers, username, password);
            return request.doGetRequest();
        } catch (Throwable t) {
            Log.e(TAG, "Exception in doInBackground", t);
            return new HttpReturn(new RestException(t));
        }
    }

    @Override
    protected void onPostExecute(HttpReturn result) {
        Log.d(TAG, "Entered onPostExecute");
        Log.d(TAG, "result.status = " + result.status);
        Log.d(TAG, "result.content = " + result.content);
        callback.onTaskComplete(result);
        super.onPostExecute(result);
    }
}
package com.hatterassoftware.restapi;

import java.net.URL;
import java.util.HashMap;

import android.os.AsyncTask;
import android.util.Log;

/**
 * An AsyncTask implementation for performing POSTs on the Hypothetical REST APIs.
 */
public class GetTask extends AsyncTask<String, String, HttpReturn>{
    private String restUrl;
    private RestCallback callback;
    private HashMap<String, String> headers;
    private String username;
    private String password;

    final String TAG = "GetTask";

    /**
     * Creates a new instance of PostTask with the specified URL, callback, and
     * request body.
     * 
     * @param restUrl The URL for the REST API.
     * @param callback The callback to be invoked when the HTTP request
     *            completes.
     * @param requestBody The body of the POST request.
     * 
     */
    public GetTask(String restUrl, RestCallback callback, HashMap<String, String> headers, String username, String password){
        this.restUrl = restUrl;
        this.callback = callback;
        this.headers = headers;
        this.username = username;
        this.password = password;
    }

    @Override
    protected HttpReturn doInBackground(String... params) {
        try {
            RestHttpUrlConnection request = new RestHttpUrlConnection(new URL(restUrl), headers, username, password);
            return request.doGetRequest();
        } catch (Throwable t) {
            Log.e(TAG, "Exception in doInBackground", t);
            return new HttpReturn(new RestException(t));
        }
    }

    @Override
    protected void onPostExecute(HttpReturn result) {
        Log.d(TAG, "Entered onPostExecute");
        Log.d(TAG, "result.status = " + result.status);
        Log.d(TAG, "result.content = " + result.content);
        callback.onTaskComplete(result);
        super.onPostExecute(result);
    }
}

package com.hatterassoftware.restapi;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.ProtocolException;
import java.net.URL;
import java.util.HashMap;

import android.util.Base64;
import android.util.Log;

public class RestHttpUrlConnection {

    private HttpURLConnection connection;

    final String TAG = "RestHttpUrlConnection";

    protected RestHttpUrlConnection(URL url, HashMap<String,String> headers, final String username, final String password) throws IOException {
        connection = (HttpURLConnection) url.openConnection();

        if(headers != null) {
            for(String key: headers.keySet()) {
                Log.d(TAG, "Adding header: " + key + "; " + headers.get(key));
                connection.addRequestProperty(key, headers.get(key));
            }
        }

        if(username != null) {
            String auth = "Basic " + Base64.encodeToString((username + ":" + password).getBytes(), Base64.DEFAULT);

            connection.addRequestProperty("Authorization", auth);
        }
    }

    public HttpReturn doPostRequest(String postData) throws IOException {
        return doPostOrPut(true, postData);
    }

    public HttpReturn doGetRequest() throws IOException {
        return doGetOrDelete(true);
    }

    public HttpReturn doPutRequest(String putData) throws IOException {
        return doPostOrPut(false, putData);
    }

    public HttpReturn doDeleteRequest() throws IOException {
        return doGetOrDelete(false);
    }

    private HttpReturn doGetOrDelete(boolean isGet) throws ProtocolException, IOException {
        if (isGet) {
            connection.setRequestMethod("GET");
        } else {
            connection.setRequestMethod("DELETE");
        }

        String line;
        StringBuffer output = new StringBuffer(1024);
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            while ((line = in.readLine()) != null) output.append(line);
        } catch (Exception e) {
            HttpReturn httpReturn = new HttpReturn(connection.getResponseCode(), output.toString());
            httpReturn.restException = new RestException(e);
            return httpReturn;
        }

        return new HttpReturn(connection.getResponseCode(), output.toString());
    }

    private HttpReturn doPostOrPut(boolean isPost, String data) throws ProtocolException, IOException {
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setInstanceFollowRedirects(false);
        connection.setFixedLengthStreamingMode(data.getBytes().length);
        if (isPost) {
            connection.setRequestMethod("POST");
        } else {
            connection.setRequestMethod("PUT");
        }

        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        out.writeBytes(data);
        out.flush();
        out.close();

        connection.connect();

        String line;
        StringBuffer output = new StringBuffer(1024);
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            while ((line = in.readLine()) != null) output.append(line);
        } catch (Exception e) {
            HttpReturn httpReturn = new HttpReturn(connection.getResponseCode(), output.toString());
            httpReturn.restException = new RestException(e);
            return httpReturn;
        }

        return new HttpReturn(connection.getResponseCode(), output.toString());     
    }
}
Community
  • 1
  • 1
Erik Nedwidek
  • 6,134
  • 1
  • 25
  • 25
1

Make the disk that has the csv on it available to your device so you can use a url like

http://192.168.1.1/some.csv (run a webserver like apache)
or 
file://somedrive/somedir/some.csv (mount the disk). 

Then parse the the csv and store the data you are after.

After that sleep for X minutes and re call your open/parse function. Effectively your progam will now loop infinitely untill you tell it to stop or quit the application.

Hope this helps

Flunk
  • 283
  • 2
  • 4
0

Assuming your CSV file is accessible via HTTP(S), you can use HTTPURLConnection to access the resource, pulling the data out via the getBody() method of the Response object. Assuming you don't need to synchronously update the UI before or after, you can implement this as a new Runnable and then just call start() on it. Otherwise you'll want to read up on AsyncTask.

For the polling behavior, you'll need to express your wait criteria (i.e. does it do this all the while the Activity is running; does it need to run in the background? Should it stop after x tries or when y is true, etc.) but you can call sleep() on the thread before doing the network activity.

Sorry if the answers are vague - sounds like you're looking for some basic pointing-in-the-right-direction. Otherwise post more detail on what you need...

Bry M.
  • 135
  • 2
  • 13
0

Is there a chance you can publish a local web server and download the csv file to the device? After the download, you can read and parse the file accordingly.

In my opinion, you should create a Service in your Android app that sleeps X minutes and then resumes work. You can also get the job done via IntentService and programming alarms with the AlarmManager. In any of these cases, you update the screen (Activity) vía ResultReceivers.

Hope it helps.

If you can, be more specific on the app behavior you want to achieve in order to give you better directions.

Andres
  • 400
  • 3
  • 8
  • if i do publish it to a local web server wont i have to download the csv again every time it updates? plus this is one massive csv file.... we are talking a sheet that logs about 30 columns every minute and it runs year round... – Mr. Pivirotto Jan 16 '13 at 21:26
  • Yes. You will have to download it again on a local network. With the file downloaded, you will have better reading/buffering performance that accessing the file on the net. – Andres Jan 16 '13 at 21:47
  • If the Android phone will only be responsible of this periodic task, you should have no issues. Hope it helps. – Andres Jan 16 '13 at 21:48
  • 1
    I agree with the local webserver approach. You can't directly access the G: drive from within your program and the file will need to be transferred to your Droid each time you want to access it regardless of whether you use a network share, ftp, or webserver. If you're concerned about constant transfers, you can add the ability to my code above to only get the file if it has been modified since the last time you downloaded it. Just track the last time you grabbed it and send that in the if-modified-since header. If the HTTP return code is 304 (not modified), the file is the same as last time. – Erik Nedwidek Jan 16 '13 at 22:01