2

Android上にGoogleマップベースのアプリケーションがあります。
簡単に言うと、アプリケーションは次のように動作します: 最初にいくつかのサンプル データ (緯度/経度のペアを含む) をデータベースに入力し、それらを読み取り、最後にマップ オーバーレイにプロットします。

このアプリは、Android 2.3.3 (Gingerbread) エミュレーターと HTC Desire S で実行すると正常に動作します。ただし、同じアプリケーションを Android 4.0.3 (ICS) エミュレーターで実行すると (マニフェスト ファイルに変更を加えた後) SDK バージョンの場合)Cursor Finalized without Prior Close()アクティビティを実行しようとするとエラーが発生します。NullPointer 例外が発生し、アプリがクラッシュします。

StackTrace ペーストビンはこちら
更新されたメソッド

public int getAllEntries() {
        //int entryCount;
        Cursor cursorE = db.rawQuery("SELECT COUNT(LATS) FROM myPROmapData",
                null);
try {
            if (cursorE.moveToFirst()) {
                return cursorE.getInt(0);
            }   
            return cursorE.getInt(0);
            } finally {
              cursorE.close();
            }
    }

--
public Double[] PopulateLats() {

        //id = getAllEntries();

        int LatcolumnIndex = 0;

        Cursor cursor = db.rawQuery("SELECT LATS FROM myPROmapData", null);
        try {
            Double myLats[] = new Double[cursor.getCount()];;
            if (cursor.moveToFirst()) {

                for (int i = 0; i < cursor.getCount(); i++)
                    {
                        myLats[i] = cursor.getDouble(LatcolumnIndex);
                        cursor.moveToNext();
                        //cursor.close();
                    }  

            }   
            return myLats;
            } finally {
              cursor.close();
            }
}

--

public Double[] PopulateLons(){
        int LoncolumnIndex = 0;
        Cursor cursor2 = db.rawQuery("SELECT LONS FROM myPROmapData", null);
        try {
            Double myLons[] = new Double[cursor2.getCount()];;
            if (cursor2.moveToFirst()) {

                for (int i = 0; i < cursor2.getCount(); i++)
                    {
                        myLons[i] = cursor2.getDouble(LoncolumnIndex);
                        cursor2.moveToNext();
                        //cursor.close();
                    }  

            }   
            return myLons;
            } finally {
              cursor2.close();
            }
}


これが私のアクティビティコードです:

public class MapMaster extends MapActivity {
    /** Called when the activity is first created. */
    private List mapOverlays;
    private Projection projection;
    private MapController mc;
    private MapView mapView;
    private GeoPoint gP;
    // private GeoPoint gP2;
    private MyOverlay myoverlay;
    //Author: Kanishk

    DBAdapter db = new DBAdapter(this);
    public Double GetStartLat4gp()
    {   
        Double Lat1 = null;
        db.open();

        //db.insertQuote(); //INSERTING SAMPLE DATA INTO TABLE

        Double[] dtaStartLat = null;
        dtaStartLat = db.PopulateLats();

        for(int z=0;z<(dtaStartLat.length);z++)
        {
            //System.out.println("START_LAT:");
            //System.out.println(dtaStartLat[z]);
            Lat1 = dtaStartLat[z];
            break;
        }
        db.close();
        return Lat1;
    }
    public Double GetStartLon4gp()
    {   
        Double Lon1 = null;
        db.open();

        //db.insertQuote(); //INSERTING SAMPLE DATA INTO TABLE

        Double[] dtaStartLon = null;
        dtaStartLon = db.PopulateLons();

        for(int z=0;z<(dtaStartLon.length);z++)
        {
            //System.out.println("START_LAT:");
            //System.out.println(dtaStartLon[z]);
            Lon1 = dtaStartLon[z];
            break;
        }
        db.close();
        return Lon1;
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map_master);
        //Double myStartLat = null;
        //Double myStartLon = null;

        mapView = (MapView) findViewById(R.id.mapview1);// Creating an instance
                                                        // of MapView
        mapView.setBuiltInZoomControls(true);// Enabling the built-in Zoom
                                                // Controls

        //mapView.setTraffic(true);
        //mapView.setStreetView(true);

        GeoPoint gP = new GeoPoint((int)(GetStartLat4gp() * 1E6), (int)(GetStartLon4gp() * 1E6));
        //gP = new GeoPoint(28570000, 77320000);// Creating a GeoPoint

        System.out.println("v START CORDS v");
        System.out.println(GetStartLat4gp());
        System.out.println(GetStartLon4gp());
        System.out.println("^ START CORDS ^");

        mc = mapView.getController();
        mc.setCenter(gP);

        mc.setZoom(15);// Initializing the MapController and setting the map to
                        // center at the
        // defined GeoPoint

        mapOverlays = mapView.getOverlays();
        projection = mapView.getProjection();

        myoverlay = new MyOverlay();
        mapOverlays.add(myoverlay);

        db.open();

        //db.CreateSampleData();  //create sample data
        //db.SyncNclean();      //SYNC - CLEAN

        if(db.doesDatabaseExist(this, "PROdb")){
            Toast.makeText(this, "EXISTS", Toast.LENGTH_SHORT).show();
            db.SyncNclean();
            Toast.makeText(this, "CLEANING..CREATING SAMPLE DATA..", Toast.LENGTH_SHORT).show();
            db.CreateSampleData();
            Toast.makeText(this, "Sample Data Created", Toast.LENGTH_SHORT).show();

        }
        else{
            Toast.makeText(this, "DOES NOT EXISTS", Toast.LENGTH_SHORT).show();
            db.SyncNclean();
            Toast.makeText(this, "CLEANING..CREATING SAMPLE DATA..", Toast.LENGTH_SHORT).show();
            db.CreateSampleData();
            Toast.makeText(this, "Sample Data Created", Toast.LENGTH_SHORT).show();

        }


        long id = 0;
        id = db.getAllEntries();
        CharSequence text = "The data was added successfully!\nData Totals = " + id + "Records";
        System.out.println(text);
        db.close();
    }
    public Double[] GetLats()
    {   
        db.open();

        //db.insertQuote(); //INSERTING SAMPLE DATA INTO TABLE

        Double[] dtaMyLats = null;
        dtaMyLats = db.PopulateLats();
        for(int z=0;z<(dtaMyLats.length);z++)
        {
            System.out.println("LATS:");
            System.out.println(dtaMyLats[z]);
        }
        db.close();
        return dtaMyLats;
    }
    public Double[] GetLons()
    {
        db.open();
        Double[] dtaMyLons = null;
        dtaMyLons = db.PopulateLons();
        for(int z=0;z<(dtaMyLons.length);z++)
        {
            System.out.println("LONS:");
            System.out.println(dtaMyLons[z]);
        }
        db.close();
        return dtaMyLons;
    }
    @Override
    protected boolean isRouteDisplayed() {
        // TODO Auto-generated method stub
        return false;
    }

    class MyOverlay extends Overlay {

        public MyOverlay() {

        }
        //Author: Kanishk



        public void draw(Canvas canvas, MapView mapv, boolean shadow) {
            super.draw(canvas, mapv, shadow);
            // Configuring the paint brush
            Paint mPaint = new Paint();
            mPaint.setDither(true);
            mPaint.setColor(Color.RED);
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mPaint.setStrokeJoin(Paint.Join.ROUND);
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            mPaint.setStrokeWidth(4);


            Double[] LatArr = GetLats();
            Double[] LonArr = GetLons();


        //generate geopoints dynamically based on coordinates from index @ array
            //author: Kanishk

            int count = LatArr.length;
            //System.out.println(count);

            for(int i=0;i<count-1;i++)
            {

                    Double lat1;
                    Double lon1;
                    Double lat2;
                    Double lon2;
                    lat1 = LatArr[i];
                    lon1 = LonArr[i];
                    //System.out.println(LatLon[i][j]);
                    /*System.out.println("<< BREAK >>");
                    System.out.println(lat1);
                    System.out.println(lon1);
                    */
                    lat2=LatArr[i+1];
                    //lat1 = null;
                    lon2=LonArr[i+1];
                    //lon1 = null;
                    //i++;

                    if(lat2!=null){
                    GeoPoint gp1 = new GeoPoint((int)(lat1 * 1E6), (int)(lon1 * 1E6)); //
                    GeoPoint gp2 = new GeoPoint((int)(lat2 * 1E6), (int)(lon2 * 1E6)); //
                    System.out.println("<< coord1 >>");
                    System.out.println(lat1);
                    System.out.println(lon1);
                    System.out.println("<< coord2 >>");
                    System.out.println(lat2);
                    System.out.println(lon2);

                    Point p11 = new Point();
                    Point p22 = new Point();

                    Path mypath = new Path();
                    projection.toPixels(gp1, p11);
                    projection.toPixels(gp2, p22);
                    mypath.moveTo(p22.x, p22.y);// *
                    mypath.lineTo(p11.x, p11.y);// *

                    canvas.drawPath(mypath, mPaint);
                    }


            }
        // logic end

        }

    }
}

DBAdapter クラス:

public class DBAdapter {
    int id = 0;
    //public static final String KEY_ROWID = "_id";
    public static final String KEY_PHID = "phID";
    public String KEY_LAT = "LATS";
    public String KEY_LON = "LONS";
    private static final String TAG = "DBAdapter";

    private static final String DATABASE_NAME = "PROdb";
    private static final String DATABASE_TABLE = "myPROmapData";
    private static final int DATABASE_VERSION = 9;

    //private static final String DATABASE_CREATE = "create table myPROmapData (_id integer primary key autoincrement, phID integer, LATS real not null, LONS real not null);";
    private static final String DATABASE_CREATE = "create table myPROmapData (phID integer, LATS real not null, LONS real not null);";

    private final Context context;

    private DatabaseHelper DBHelper;
    private SQLiteDatabase db;


    public DBAdapter(Context ctx) {
        this.context = ctx;
        DBHelper = new DatabaseHelper(context);
    }

    private static class DatabaseHelper extends SQLiteOpenHelper {
        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            try {
            db.execSQL(DATABASE_CREATE);
            }
            catch (Exception e){
                Log.e(TAG,"Error: onCreate db");
            }
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            try {
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS myPROmapData");
            onCreate(db);
            }
            catch (Exception e){
                Log.e(TAG,"Error: onUpgrade db");
            }
        }
    }

    // ---opens the database---
    public DBAdapter open() throws SQLException {
        db = DBHelper.getWritableDatabase();
        return this;
    }

    // ---closes the database---
    public void close() {
        DBHelper.close();
    }

    // ---insert sample data into the database---
    public long CreateSampleData() {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_PHID, 100);

        initialValues.put(KEY_LAT, 28.4588);
        initialValues.put(KEY_LON, 77.0725);
        db.insert(DATABASE_TABLE, null, initialValues);

        initialValues.put(KEY_LAT, 28.4719);
        initialValues.put(KEY_LON, 77.0722);
        db.insert(DATABASE_TABLE, null, initialValues);


        /*initialValues.put(KEY_LAT, 28.5700);
        initialValues.put(KEY_LON, 77.3200);*/
        initialValues.put(KEY_LAT, 28.4795);
        initialValues.put(KEY_LON, 77.0800);
         db.insert(DATABASE_TABLE, null, initialValues);

        /*initialValues.put(KEY_LAT, 28.4700);
        initialValues.put(KEY_LON, 77.0300);*/
        initialValues.put(KEY_LAT, 28.4813);
        initialValues.put(KEY_LON, 77.0931);
         db.insert(DATABASE_TABLE, null, initialValues);

        /*initialValues.put(KEY_LAT, 27.1833);
        initialValues.put(KEY_LON, 78.0167);*/
        initialValues.put(KEY_LAT, 28.4820);
        initialValues.put(KEY_LON, 77.1023);
         db.insert(DATABASE_TABLE, null, initialValues);

        /*initialValues.put(KEY_LAT, 26.4583);
        initialValues.put(KEY_LON, 80.3173);*/
        initialValues.put(KEY_LAT, 28.4804);
        initialValues.put(KEY_LON, 77.1251);

        return db.insert(DATABASE_TABLE, null, initialValues);
    }

    public int getAllEntries() {
        //int entryCount;
        Cursor cursorE = db.rawQuery("SELECT COUNT(LATS) FROM myPROmapData",
                null);
        if (cursorE.moveToFirst()) {
            //entryCount = cursorE.getInt(0);
            return cursorE.getInt(0);
            //return entryCount;
        }
                        //  CLOSING CURSOR
        cursorE.close(); 
        return cursorE.getInt(0);

        //return entryCount;
    }

    public boolean doesDatabaseExist(ContextWrapper context, String dbName) {
        File dbFile = context.getDatabasePath(dbName);

        return dbFile.exists();
    }

    public void SyncNclean(){

        Log.w(TAG, "Sync'ing with Master Server..");

        //sync master server here

        Log.w(TAG, "Sync Complete..");
        //Log.w(TAG, "Cleaning old data..");

        db.execSQL("DROP TABLE IF EXISTS myPROmapData");
        DBHelper.onCreate(db);

        Log.w(TAG, "Cleaning completed..");
    }

    public Double[] PopulateLats() {

        //id = getAllEntries();

        int LatcolumnIndex = 0;

        Cursor cursor = db.rawQuery("SELECT LATS FROM myPROmapData", null);
        Double myLats[] = new Double[cursor.getCount()];;
        if (cursor.moveToFirst())
        {                       
            for (int i = 0; i < cursor.getCount(); i++)
            {
                myLats[i] = cursor.getDouble(LatcolumnIndex);
                cursor.moveToNext();
                cursor.close();
            }  

        }
        // Original location for cursor.close()

        return myLats;

    }

    public Double[] PopulateLons(){
        int LoncolumnIndex = 0;
        Cursor cursor2 = db.rawQuery("SELECT LONS FROM myPROmapData", null);
        Double myLons[] = new Double[cursor2.getCount()];;
        if (cursor2.moveToFirst())
        {                       
            for (int i = 0; i < cursor2.getCount(); i++)
            {
                myLons[i] = cursor2.getDouble(LoncolumnIndex);
                cursor2.moveToNext();
                cursor2.close(); //third try
            }
            // second tried here: cursor2.close();
        }
        // Original location for cursor.close()
        //db.close();

        return myLons;
    }

}

どんな助けでも大歓迎です。読んでくれてありがとう。

4

2 に答える 2

6

nullpointer 例外の解決策は次のとおりです。

GetStartLat4gp または GetStartLon4gp は null を返します。

それとは別に、このメソッドを次のように書き換えると、コードはより安定します。

public int getAllEntries() {
    //int entryCount;
    Cursor cursorE = db.rawQuery("SELECT COUNT(LATS) FROM myPROmapData",
            null);
    try {
      if (cursorE.moveToFirst()) {
          return cursorE.getInt(0);
      }   
      return cursorE.getInt(0);
    } finally {
      cursorE.close();
    }
}

元のドラフトでは、カーソルが早く戻ったため、カーソルを閉じませんでした。

try {} finally { close resources } を適切なスタイルとして使用し、どのような場合でも (予期しない例外であっても) すべてのリソースを確実に閉じます。

それとは別に、他のカーソルの close() をループの外に戻すと、ループ内でエラーが発生します。(最高です、try / finally there も使用してください)

于 2012-12-20T08:47:04.313 に答える
1

私はあなたが最終的な前にreturnステートメントを実行しているためだと信じています。この場合、最終的には決して実行されないため、データベースは閉じられません

カーソルから値を取得して変数に設定し、次のように関数の最後で変数を返す必要があります。

public int getAllEntries() {
    //int entryCount;
    Cursor cursorE = db.rawQuery("SELECT COUNT(LATS) FROM myPROmapData",
            null);
    int value = 0
    try {
      if (cursorE.moveToFirst()) {
          value = cursorE.getInt(0);
      }   
      value = cursorE.getInt(0);
    } finally {
      cursorE.close();
    }
    return value;
}

また、サイド ライン コメントとして、db.rawQuey も try ステートメント内にある必要があります。そうしないと、何らかの理由でクエリが失敗した場合にアプリが強制終了します。

于 2012-12-20T11:24:05.670 に答える