Getting an Android Activity To Run Non-Activity Code
I have an android app that basically just plots points on a map. These maps are determined from a totally different class. I originally wrote this class as its own program (it reads a CSV file and picks out points and gives back their longitude and latitude in an array).
So, what I have done is added this class to my Android App program. I want the app at some point to call up the class's method that will generate the array, return it, and use this new array to plot points on the map. As far as grabbing the array and pinpointing each of their latitudes and longitudes goes, I can do it.
However, when in my Android App's main class, I state:
String[][] bump = ReadCsv.getArray(fileToUse);
, my program will force close. (ReadCsv is the name of the class I put in the program - getArray in the only method in the class, and it returns an array[][]).
Does anyone think they see what my problem here is? Maybe an alternative solution is possible?
The LogCat is shown below:
07-27 15:19:25.105: ERROR/AndroidRuntime(12214): FATAL EXCEPTION: main 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): java.lang.RuntimeException: Unable to start activity ComponentInfo{net.learn2develop.GoogleMaps/net.learn2develop.GoogleMaps.MapsActivity}: java.lang.NullPointerException 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at android.app.ActivityThread.access$2300(ActivityThread.java:125) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at android.os.Handler.dispatchMessage(Handler.java:99) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at android.os.Looper.loop(Looper.java:123) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at android.app.ActivityThread.main(ActivityThread.java:4627) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at java.lang.reflect.Method.invokeNative(Native Method) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at java.lang.reflect.Method.invoke(Method.java:521) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at dalvik.system.NativeStart.main(Native Method) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): Caused by: java.lang.NullPointerException 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at net.learn2develop.GoogleMaps.MapsActivity.onCreate(MapsActivity.java:86) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) 07-27 15:19:25.105: ERROR/AndroidRuntime(12214): ... 11 more
And my code is:
package net.learn2develop.GoogleMaps;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.List;
import java.util.StringTokenizer;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.MapView.LayoutParams;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
public class MapsActivity extends MapActivity
{
MapView mapView;
MapController mc;
GeoPoint p;
GeoPoint p2;
GeoPoint p99;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mapView = (MapView) findViewById(R.id.mapView);
LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom);
@SuppressWarnings("deprecation")
View zoomView = mapView.getZoomControls();
mapView.setSatellite(true);
zoomLayout.addView(zoomView,
new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mapView.displayZoomControls(true);
mc = mapView.getController();
String coordinates[] = {"42.30936432", "-71.12162781"};
double lat = Double.parseDouble(coordinates[0]);
double lng = Double.parseDouble(coordinates[1]);
p = new GeoPoint(
(int) (lat * 1E6),
(int) (lng * 1E6));
mc.animateTo(p);
mc.setZoom(8);
//---Add a location marker---
MapOverlay mapOverlay = new MapOverlay();
List<Overlay> listOfOverlays = mapView.getOverlays();
//listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
// -- my own point ---
String coordinates2[] = {"42.20", "-71.20"};
double lat2 = Double.parseDouble(coordinates2[0]);
double lng2 = Double.parseDouble(coordinates2[1]);
p2 = new GeoPoint(
(int) (lat2 * 1E6),
(int) (lng2 * 1E6));
MapOverlay mapOverlay2 = new MapOverlay();
List<Overlay> listOfOverlays2 = mapView.getOverlays();
listOfOverlays2.add(mapOverlay2);
// Add points from ReadCsv.java
File fileToUse = new File("/Users/csrobot/Desktop/Training4.csv");
String[][] bump = ReadCsv.getArray(fileToUse);
for(int i = 0; i < bump.length; i++) {
String coordinates99[] = {bump[i][0], bump[i][1]};
double lat99 = Double.parseDouble(coordinates99[0]);
double lng99 = Double.parseDouble(coordinates99[1]);
p99 = new GeoPoint(
(int) (lat99 * 1E6),
(int) (lng99 * 1E6));
MapOverlay mapOverlay99 = new MapOverlay();
List<Overlay> listOfOverlays99 = mapView.getOverlays();
listOfOverlays99.add(mapOverlay99);
}
mapView.invalidate();
}
class MapOverlay extends com.google.android.maps.Overlay
{
@Override
public boolean draw(Canvas canvas, MapView mapView,
boolean shadow, long when)
{
super.draw(canvas, mapView, shadow);
//---translate the GeoPoint to screen pixels---
Point screenPts = new Point();
mapView.getProjection().toPixels(p, screenPts);
//---add the marker---
Bitmap bmp = BitmapFactory.decodeResource(
getResources(), R.drawable.redpin);
canvas.drawBitmap(bmp, screenPts.x, screenPts.y-44, null);
// --make my开发者_如何学Go own point---
Point screenPts2 = new Point();
mapView.getProjection().toPixels(p2, screenPts2);
Bitmap bmp2 = BitmapFactory.decodeResource(
getResources(), R.drawable.redpin);
canvas.drawBitmap(bmp2, screenPts2.x, screenPts2.y-44, null);
return true;
}
}
static class ReadCsv {
public static String[][] getArray(File file) {
try {
//
// Code That I know Works is Here
//
return arrayOfBumps;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(Exception e) {
// System.out.println("The following error occurred "+e);
}
return null;
}
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
}
EDIT: For Ravi Bhatt
private class MapPoint extends AsyncTask <String[][], String, String> {
@Override
protected String doInBackground(String[][]... <<What goes here...? >>) {
String << what am i making to return? >> = null;
try {
InputStream is = getAssets().open("Training4.csv");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
bump = getArray(reader);
if(bump == null){
setContentView(R.layout.deleteme);
} else {
for(int i = 0; i < bump.length; i++) {
String coordinates99[] = {bump[i][0], bump[i][1]};
double lat99 = Double.parseDouble(coordinates99[0]);
double lng99 = Double.parseDouble(coordinates99[1]);
p99 = new GeoPoint(
(int) (lat99 * 1E6),
(int) (lng99 * 1E6));
MapOverlay mapOverlay99 = new MapOverlay();
List<Overlay> listOfOverlays99 = mapView.getOverlays();
listOfOverlays99.add(mapOverlay99);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return << do I really need to return something? if so, what? >>;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
mapView.refreshDrawableState();
}
}
The best think for your needs is AsyncTask. use this link http://developer.android.com/reference/android/os/AsyncTask.html
you can pass params in doInBackground() methods. params can be the list of latitude and longitude.
-- make geopoing
-- create overlayitem
-- add it in itemized overlay
onPostExectute() method do following.
-- add it in to mapoverlay i.e. list of overlay. -- you can use refreshdrawablestate() method after that.
for putting that overlay from non activity class you can use mapactivity's reference or context and use it for adding the overlay.
EDIT :
for example, consider the example mapview from the link http://developer.android.com/resources/tutorials/views/hello-mapview.html
When using AsncTask, as you have array of coordinates, pass this array in AsyncTask as params like AsyncTask.
then doInBackGround() method use doInBackGroud < String[][]...varName > as you have string array. Put that for loop logic to derive coordinates and Geopoint in doInBackGround Method.
--add each of the overlayitem which u get from coordinate in itemizedOverlay (as per link of hello mapview).
--In onPostExecute() method add that itemized overlay in the List of the map and use mapview.refreshdrawablestate(). you can use onPostExecute with declaration like onPostExecute(Void result)
Do the above step with understanding and its DONE!!! :)
There could be many reasons you are seeing a force close. Have you tried stepping into the main method and seeing where it crashes? You might be using the parameter for something that is causing the crash when you pass null. ie were you passing the filename to use in your stand alone app?
This type of operation is typically not done inside an activity since it would make your app's UI janky. I would investigate IntentService and call your code from it. You can then invoke the IntentService whenever you want from your UI.
Are you using it from Source or a Jar file? If you're using it as a Jar file it could be dying because your program uses an API not available to Android. The other option might be it touches the args. I'd try passing ReadCSV.main(new String[] {}).
I see a java.lang.NullPointerException, but looking through the logcat is hard because of formatting. But Something inside ReadCSV is throwing a NPE. I'd suggest step through ReadCSV with a debugger, or find the line number of the line that's tossing that NPE. Actually found it:
net.learn2develop.GoogleMaps.MapsActivity.onCreate(MapsActivity.java:81)
So on line 81 in MapsActivity is the problem. It doesn't look like ReadCSV.main() is being reached yet.
I would also follow the suggestion of doing this inside a AsyncTask. Even I'd consider factoring out all of your code into a proper method that you can directly invoke and return the Array directly because ReadCSV.main() is a void return type. So what it produces must be a file or something so you can get that data. Instead of that just have it return a plain array. Something like:
public List<Row> readCSV( File f ) {
}
That's what you could do to make this easier on yourself.
精彩评论