【问题标题】:Getting an Android Activity To Run Non-Activity Code让 Android Activity 运行非 Activity 代码
【发布时间】:2011-07-27 15:51:14
【问题描述】:

我有一个基本上只是在地图上绘制点的 Android 应用程序。 这些地图是从完全不同的类别中确定的。 我最初将这个类编写为它自己的程序(它读取一个 CSV 文件并挑选出点并在一个数组中返回它们的经度和纬度)。

所以,我所做的就是将这个类添加到我的 Android 应用程序中。我希望应用程序在某个时候调用将生成数组的类的方法,返回它,并使用这个新数组在地图上绘制点。至于抓取数组并精确定位它们的每个纬度和经度,我可以做到。

但是,在我的 Android 应用程序的主类中,我声明:

String[][] bump = ReadCsv.getArray(fileToUse);

,我的程序将强制关闭。 (ReadCsv是我在程序中放入的类名——类中唯一方法中的getArray,它返回一个数组[][])。

有人认为他们看到了我的问题吗?或许有替代解决方案?

LogCat 如下图所示:

07-27 15:19:25.105: 错误/AndroidRuntime(12214): 致命异常: main 07-27 15:19:25.105: 错误/AndroidRuntime(12214): java.lang.RuntimeException: 无法启动活动 ComponentInfo{net.learn2develop.GoogleMaps/net.learn2develop.GoogleMaps.MapsActivity}: java.lang.NullPointerException 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 android.app.ActivityThread.access$2300(ActivityThread.java:125) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 android.os.Handler.dispatchMessage(Handler.java:99) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 android.os.Looper.loop(Looper.java:123) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 android.app.ActivityThread.main(ActivityThread.java:4627) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 java.lang.reflect.Method.invokeNative(Native Method) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 java.lang.reflect.Method.invoke(Method.java:521) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 07-27 15:19:25.105:错误/AndroidRuntime(12214):在 dalvik.system.NativeStart.main(本机方法) 07-27 15:19:25.105:错误/AndroidRuntime(12214):引起:java.lang.NullPointerException 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 net.learn2develop.GoogleMaps.MapsActivity.onCreate(MapsActivity.java:86) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) 07-27 15:19:25.105: 错误/AndroidRuntime(12214): ... 11 更多

我的代码是:

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 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;
}
}

编辑:拉维·巴特

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();

}

}

【问题讨论】:

  • 每当应用程序“强制关闭”时,它通常会在 logcat 中提供一些错误信息。请在您的帖子中包含该信息,否则,任何人都可以猜测问题所在。

标签: android class google-maps android-activity


【解决方案1】:

最适合您需求的是 AsyncTask。 使用此链接http://developer.android.com/reference/android/os/AsyncTask.html

您可以在 doInBackground() 方法中传递参数。 params 可以是经纬度列表。

-- 进行地理定位

-- 创建覆盖项

--将其添加到逐项叠加中

onPostExectute() 方法执行以下操作。

-- 将其添加到 mapoverlay 中,即覆盖列表。 -- 之后可以使用 refreshdrawablestate() 方法。

为了从非活动类中放置该叠加层,您可以使用 mapactivity 的引用或上下文并将其用于添加叠加层。

编辑:

例如,考虑链接http://developer.android.com/resources/tutorials/views/hello-mapview.html中的示例地图视图

当使用 AsncTask 时,因为你有坐标数组,所以在 AsyncTask 中将这个数组作为参数传递给 AsyncTask。

然后 doInBackGround() 方法使用 doInBackGroud 因为你有字符串数组。将 for 循环逻辑放在 doInBackGround 方法中推导出坐标和 Geopoint。

--添加您从 itemizedOverlay 中的坐标获得的每个覆盖项(根据 hello mapview 的链接)。

--在onPostExecute() 方法中,在地图列表中添加逐项叠加,并使用mapview.refreshdrawablestate()。您可以将 onPostExecute 与 onPostExecute(Void result)

之类的声明一起使用

在理解的情况下执行上述步骤并完成! :)

【讨论】:

  • 这对我来说很有意义!但是,我对一些事情有点困惑。您能否看一下我在问题底部发布的新代码部分,并告诉我我可能做错了什么/应该做什么?
  • 在 doInBackground() 方法的参数中为该 String[][] 数组提供任何名称,您以后可以使用它来获取地理点或坐标。
  • 在 doInBackground() 方法的参数中为该 String[][] 数组提供任何名称,您以后可以使用它来获取地理点或坐标。并在此方法的 return 语句中返回类似 return "done.." 或任何东西......它不重要
  • 我现在知道了,它可以工作了!我可以看到地图并滚动浏览它,直到程序完成并在地图上绘制 GeoPoints。现在我实际上有一个新问题:x。为什么我的地图在 GeoPoint 被映射后迟滞到无法忍受?映射完所有点后,是否有一些我需要杀死的过程或类似的东西,以便程序停止滞后?
  • 在 onPostExecution 方法中添加地图上的覆盖列表,如 listOfOverlays99.add(mapOverlay99);然后根据需要使用 refreshdrawablestate。
【解决方案2】:

您看到一股力量接近的原因可能有很多。您是否尝试过进入 main 方法并查看它在哪里崩溃?当您传递 null 时,您可能正在将该参数用于导致崩溃的某些东西。即您是否传递文件名以在您的独立应用程序中使用?

这种类型的操作通常不会在 Activity 内完成,因为它会使您的应用程序的 UI 卡顿。我会调查 IntentService 并从中调用您的代码。然后,您可以随时从您的 UI 调用 IntentService。

【讨论】:

    【解决方案3】:

    您是从 Source 还是 Jar 文件中使用它?如果您将它用作 Jar 文件,它可能会死掉,因为您的程序使用了 Android 不可用的 API。另一种选择可能是它触及参数。我会尝试通过 ReadCSV.main(new String[] {})。

    我看到一个 java.lang.NullPointerException,但是由于格式化,很难通过 logcat 查看。但是 ReadCSV 里面的东西正在抛出一个 NPE。我建议使用调试器逐步完成 ReadCSV,或者找到抛出该 NPE 的行的行号。居然找到了:

    net.learn2develop.GoogleMaps.MapsActivity.onCreate(MapsActivity.java:81)

    所以 MapsActivity 的第 81 行是问题所在。看起来尚未到达 ReadCSV.main()。

    我也会遵循在 AsyncTask 中执行此操作的建议。即使我会考虑将所有代码分解为一个适当的方法,您可以直接调用并直接返回数组,因为 ReadCSV.main() 是一个 void 返回类型。所以它产生的必须是一个文件或其他东西,这样你就可以得到那个数据。而不是让它返回一个普通数组。比如:

    public List<Row> readCSV( File f ) {
    }
    

    这就是你可以做的让自己更轻松的事情。

    【讨论】:

    • 我确实把它改成了一个类,现在返回一个数组。但是,我仍然遇到同样的错误。给我一分钟时间来发布我的新代码。
    • 我认为问题不是您在 ReadCSV 中的代码。从它的外观 MapsActivity.onCreate() 方法第 81 行是问题所在。 MapsActivity 在您的 ReadCSV 类之外,因此不涉及,除非它返回 null。
    • 这是第 81 行:listOfOverlays2.add(mapOverlay2);在我尝试在中实现 ReadCSV 类之前它就起作用了。所以我仍然怀疑这就是问题所在,除非你认为它会导致问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多