views:

995

answers:

1

Hi, im triying to do an app using the notepad tutorial of Android as a guide. I can insert new elements on the table without problems, but if i want to update the fields of one of this elements an error is prompted. I revisited the tutorial lots of times but i cant find the solution.

Thank you!

Here is the menu (to insert, delete and update)

package citic.android.remoteir;

import android.app.ListActivity; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.widget.SimpleCursorAdapter; import android.widget.AdapterView.AdapterContextMenuInfo;

public class ServerCp extends ListActivity{

private RemoteIrDbAdapter mDbHelper; 

private static final int ACTIVITY_CREATE=0;
private static final int ACTIVITY_EDIT=1;

private static final int  INSERT_ID = Menu.FIRST;
private static final int  EDIT_ID = Menu.FIRST + 1;
private static final int  DELETE_ID = Menu.FIRST + 2;

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.contentlist);

    mDbHelper = new RemoteIrDbAdapter(this);
    mDbHelper.open();

    fillDataServer();
    registerForContextMenu(getListView());

}

private void fillDataServer() {

    Cursor c = mDbHelper.fetchAllQueryDataAutoCompleteServerName();
    startManagingCursor(c);

    String[] from;

    from = new String[] { RemoteIrDbAdapter.KEY_NAMESERVER}; 

    int[] to = new int[] { R.id.row1 };

    SimpleCursorAdapter data =
        new SimpleCursorAdapter(this, R.layout.listrow, c, from, to);

    setListAdapter(data);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    menu.add(0, INSERT_ID, 0, R.string.menu_insert_server);
    return true;
}

@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
    switch(item.getItemId()) {
    case INSERT_ID:
        createServer();
        return true;
    }

    return super.onMenuItemSelected(featureId, item);
}


public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    menu.add(0, EDIT_ID, 0, R.string.menu_edit_server);
    menu.add(0, DELETE_ID, 0, R.string.menu_delete_server);

}

@Override
public boolean onContextItemSelected(MenuItem item) {
    switch(item.getItemId()) {
    case EDIT_ID:
        AdapterContextMenuInfo infoEdit = (AdapterContextMenuInfo) item.getMenuInfo();
        Intent i = new Intent(this, ServerEdit.class);
        i.putExtra(RemoteIrDbAdapter.KEY_ROWIDSERVER, infoEdit.id);
        startActivityForResult(i, ACTIVITY_EDIT);

    case DELETE_ID:
        AdapterContextMenuInfo infoDelete = (AdapterContextMenuInfo) item.getMenuInfo();
        mDbHelper.deleteQueryDataServer(infoDelete.id);
        fillDataServer();
        return true;
    }
    return super.onContextItemSelected(item);
}

private void createServer() {
    Intent i = new Intent(this, ServerEdit.class);
    startActivityForResult(i, ACTIVITY_CREATE);
}

/*@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    Intent i = new Intent(this, ProfileEdit.class);
    i.putExtra(RemoteIrDbAdapter.KEY_ROWID, id);
    startActivityForResult(i, ACTIVITY_EDIT);
}


*/
    @Override
    protected void onActivityResult(int requestCode, int resultCode, 
                                    Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        fillDataServer();
    }


}

Here is the edit and create class:

package citic.android.remoteir;

import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText;

public class ServerEdit extends Activity{

private EditText mNameText;
private EditText mIpText;
private EditText mPortText;
private Long mRowId;
private RemoteIrDbAdapter mDbHelper;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mDbHelper = new RemoteIrDbAdapter(this);
    mDbHelper.open();
    setContentView(R.layout.editserver);


    mNameText = (EditText) findViewById(R.id.name);
    mIpText = (EditText) findViewById(R.id.ip);
    mPortText = (EditText) findViewById(R.id.port);

    Button confirmButton = (Button) findViewById(R.id.confirm);

    mRowId = savedInstanceState != null ? savedInstanceState.getLong(RemoteIrDbAdapter.KEY_ROWIDSERVER) 
                                        : null;
    if (mRowId == null) {
        Bundle extras = getIntent().getExtras();            
        mRowId = extras != null ? extras.getLong(RemoteIrDbAdapter.KEY_ROWIDSERVER) 
                                : null;
    }

    System.out.println("el rowid es" + mRowId);
    populateFields();

    confirmButton.setOnClickListener(new View.OnClickListener() {

        public void onClick(View view) {
            setResult(RESULT_OK);
            finish();
        }

    });
}

private void populateFields() {  // <- This is where the error refers
    if (mRowId != null) {
        Cursor server = mDbHelper.fetchServer(mRowId);
        startManagingCursor(server);
        mIpText.setText(server.getString(
                server.getColumnIndexOrThrow(RemoteIrDbAdapter.KEY_IP)));
        mPortText.setText(server.getString(
                server.getColumnIndexOrThrow(RemoteIrDbAdapter.KEY_PORT)));
        mNameText.setText(server.getString(
                server.getColumnIndexOrThrow(RemoteIrDbAdapter.KEY_NAMESERVER)));    
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putLong(RemoteIrDbAdapter.KEY_ROWIDSERVER, mRowId);
}

@Override
protected void onPause() {
    super.onPause();
    saveState();
}

@Override
protected void onResume() {
    super.onResume();
    populateFields();
}

private void saveState() {
    String name = mNameText.getText().toString();
    String ip = mIpText.getText().toString();
    String port = mPortText.getText().toString();

    if (mRowId == null) {
        long id = mDbHelper.createQueryDataServer(ip, port, name);
        if (id > 0) {
            mRowId = id;
        }
    } else {
        mDbHelper.updateServerData(mRowId, ip, port, name);
    }
}

}

And here the database management:

package citic.android.remoteir;

import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log;

public class RemoteIrDbAdapter{

    public static final boolean DISTINCT = true;

    public static final String KEY_ROWIDSERVER= "_id"; //ANTES _IDS
    public static final String KEY_PORT = "port";
    public static final String KEY_IP = "ip";
    public static final String KEY_NAMESERVER = "server";

    public static final String KEY_ROWIDPROFILE= "_id"; //ANTES _id
    public static final String KEY_NAMEPROFILE= "profile";

    //public static final String KEY_ROWID = "_id";

    private static final String TAG = "RemoteIrDbAdapterBak";
    private DatabaseHelper mDbHelper;
    private SQLiteDatabase mDb;


    private static final String DATABASE_CREATE_SERVER = "create table server (_id integer primary key autoincrement,ip string not null, port string not null, server string not null);";
            /*"create table server (_id integer primary key autoincrement, " 
                    + "ip string not null, port string not null, server string not null);";*/

    private static final String DATABASE_CREATE_PROFILE = "create table profile (_id integer primary key autoincrement, profile string not null);";

            /*"create table profile (_id integer primary key autoincrement, "
                    + "profile string not null);";*/

    private static final String DATABASE_CREATE_SERPRO = "create table serpro (_ids integer not null, _idp integer not null, PRIMARY KEY (_ids, _idp), CONSTRAINT fk_idsps FOREIGN KEY (_ids) REFERENCES server(_id) ON DELETE CASCADE, CONSTRAINT fk_idspp FOREIGN KEY (_ids) REFERENCES server(_id) ON DELETE CASCADE);";

            /*"create table serpro (_ids integer not null, _idp integer not null, PRIMARY KEY (_ids, _idp), " 
                    + " CONSTRAINT fk_idsps REFERENCES server(_id) ON DELETE CASCADE "
                    + " CONSTRAINT fk_idspp REFERENCES profile(_id) ON DELETE CASCADE);";*/

private static final String DATABASE_TABLE_SERVER = "server";

    private static final String DATABASE_TABLE_PROFILE = "profile";

    private static final String DATABASE_TABLE_SERPRO = "serpro";

    private static final String TRIGGER_SERPRO_IP = "create trigger serpro_pi before insert on serpro for each row when ((select _id from profile where _id = new._id) is null) begin select raise(abort, 'insert on table \"serpro\" violates foreign key constraint \"fk_idspp\"'); end;";
    /*"CREATE TRIGGER SERPRO_PI BEFORE INSERT ON serpro FOR EACH ROW BEGIN SELECT CASE WHEN ((SELECT _id FROM profile WHERE _id = NEW._id) IS NULL ) THEN RAISE (ABORT, ‘insert on table serpro violates foreign key constraint fk_idspp’) END; END;";*/

    private static final String TRIGGER_SERPRO_UP = "create trigger serpro_up before update on serpro for each row when ((select _id from profile where _id = new._id) is null) begin select raise(abort, 'update on table \"serpro\" violates foreign key constraint \"fk_idspp\"'); end;"; 
    /*"CREATE TRIGGER SERPRO_UP BEFORE UPDATE ON serpro FOR EACH ROW BEGIN SELECT CASE WHEN ((SELECT _id FROM profile WHERE _id = NEW._id) IS NULL ) THEN RAISE (ABORT, ‘update on table serpro violates foreign key constraint fk_idspp’) END; END;";*/

    private static final String TRIGGER_SERPRO_DP = "create trigger serpro_dp before delete on profile for each row begin select raise(abort, 'delete on table \"profile\" violates foreign key constraint \"fk_idspp\" on \"serpro\"') where (select _idp from serpro where _idp = old._id) is not null; end;";
    /*"CREATE TRIGGER SERPRO_DP BEFORE DELETE ON profile FOR EACH ROW BEGIN SELECT CASE WHEN ((SELECT _id FROM serpro WHERE _id = OLD._id) IS NULL ) THEN RAISE (ABORT, ‘delete on table profile violates foreign key constraint fk_idspp’) END; END;";*/


    private static final String TRIGGER_SERPRO_IS = "create trigger serpro_is before insert on serpro for each row when ((select _id from server where _id = new._id) is null) begin select raise(abort, 'insert on table \"serpro\" violates foreign key constraint \"fk_idsps\"'); end;";
    /*"CREATE TRIGGER SERPRO_IS BEFORE INSERT ON serpro FOR EACH ROW BEGIN SELECT CASE WHEN ((SELECT _id FROM server WHERE _id = NEW._id) IS NULL ) THEN RAISE (ABORT, ‘insert on table serpro violates foreign key constraint fk_idsps’) END; END;";*/

    private static final String TRIGGER_SERPRO_US = "create trigger serpro_us before update on serpro for each row when ((select _id from server where _id = new._id) is null) begin select raise(abort, 'update on table \"serpro\" violates foreign key constraint \"fk_idsps\"'); end;";
    /*"CREATE TRIGGER SERPRO_US BEFORE UPDATE ON serpro FOR EACH ROW BEGIN SELECT CASE WHEN ((SELECT _id FROM server WHERE _id = NEW._id) IS NULL ) THEN RAISE (ABORT, ‘update on table serpro violates foreign key constraint fk_idsps’) END; END;";*/

    private static final String TRIGGER_SERPRO_DS = "create trigger serpro_ds before delete on server for each row when ((select _ids from serpro where _ids = old._id) is not null) begin select raise(abort, 'delete on table \"server\" violates foreign key constraint \"fk_idsps\" on \"server\"'); end;";
    /*"CREATE TRIGGER PROFILE_DS BEFORE DELETE ON server FOR EACH ROW BEGIN SELECT CASE WHEN ((SELECT _id FROM serpro WHERE _id = OLD._id) IS NULL ) THEN RAISE (ABORT, ‘delete on table server violates foreign key constraint fk_idsps’) END; END;";*/


    /*private static final String DATABASE_CREATE =
            "create table userdata (_id integer primary key autoincrement, "
                    + "ip string not null, port string not null, query string not null, calendar string not null);";*/

    private static final String DATABASE_NAME = "data";
    //private static final String DATABASE_TABLE = "remoteirdata";
    private static final int DATABASE_VERSION = 2;

    private final Context mCtx;

    private static class DatabaseHelper extends SQLiteOpenHelper {

        DatabaseHelper(Context context) {

            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DATABASE_CREATE_SERVER);
            db.execSQL(DATABASE_CREATE_PROFILE);
            db.execSQL(DATABASE_CREATE_SERPRO);
            db.execSQL(TRIGGER_SERPRO_IP);
            db.execSQL(TRIGGER_SERPRO_UP);
            db.execSQL(TRIGGER_SERPRO_DP);
            db.execSQL(TRIGGER_SERPRO_IS);
            db.execSQL(TRIGGER_SERPRO_US);
            db.execSQL(TRIGGER_SERPRO_DS);  
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS server");
            db.execSQL("DROP TABLE IF EXISTS profile");
            db.execSQL("DROP TABLE IF EXISTS serpro");
            onCreate(db);
        }
    }

    public RemoteIrDbAdapter(Context ctx) {
        this.mCtx = ctx;
    }

    public RemoteIrDbAdapter open() throws SQLException {
        mDbHelper = new DatabaseHelper(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        mDbHelper.close();
    }


    public long createQueryDataServer(String ip, String port, String server) {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_IP, ip);
        initialValues.put(KEY_PORT, port);
        initialValues.put(KEY_NAMESERVER, server);

        return mDb.insert(DATABASE_TABLE_SERVER, null, initialValues);
    }

    public long createQueryDataProfile(String profile) {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_NAMEPROFILE, profile);

        return mDb.insert(DATABASE_TABLE_PROFILE, null, initialValues);
    }

    public long createQueryDataSerpro(Integer _id, Integer _idp) {
        ContentValues initialValues = new ContentValues();
        initialValues.put(KEY_ROWIDSERVER, _id);
        initialValues.put(KEY_ROWIDPROFILE, _idp);

        return mDb.insert(DATABASE_TABLE_SERPRO, null, initialValues);
    }

    public boolean deleteQueryDataServer(long rowId) {

        return mDb.delete(DATABASE_TABLE_SERVER, KEY_ROWIDSERVER + "=" + rowId, null) > 0;
    }

    public boolean deleteQueryDataProfile(long rowId) {

        return mDb.delete(DATABASE_TABLE_PROFILE, KEY_ROWIDPROFILE + "=" + rowId, null) > 0;
    }


    public Cursor fetchServer(long rowId) throws SQLException {

        Cursor mCursor =

                mDb.query(true, DATABASE_TABLE_SERVER, new String[] {KEY_ROWIDSERVER,
                        KEY_IP, KEY_PORT, KEY_NAMESERVER}, KEY_ROWIDSERVER + "=" + rowId, null,
                        null, null, null, null);
        if (mCursor != null) {
            mCursor.moveToFirst();
        }
        return mCursor;

    }

    public Cursor fetchAllQueryDataServer() {
        return mDb.query(DISTINCT, DATABASE_TABLE_SERVER, new String[] {KEY_ROWIDSERVER,KEY_IP, KEY_PORT, KEY_NAMESERVER}, null, null, null, null, null, null);   
    }

    public Cursor fetchAllQueryDataProfile() {
        return mDb.query(DISTINCT, DATABASE_TABLE_PROFILE, new String[] {KEY_ROWIDPROFILE,KEY_NAMEPROFILE}, null, null, null, null, null, null);   
    }

    public Cursor fetchAllQueryDataAutoCompleteIp(){

        return mDb.query(DISTINCT, DATABASE_TABLE_SERVER, new String[] {KEY_ROWIDSERVER, KEY_IP}, null, null, KEY_IP, null, null, null);    
    }

    public Cursor fetchAllQueryDataAutoCompletePort(){

        return mDb.query(DISTINCT, DATABASE_TABLE_SERVER, new String[] {KEY_ROWIDSERVER, KEY_PORT}, null, null, KEY_PORT, null, null, null);    
    }

    public Cursor fetchAllQueryDataAutoCompleteServerName(){

        //return mDb.query(DISTINCT, DATABASE_TABLE_SERVER, new String[] {KEY_ROWIDSERVER, KEY_NAMESERVER}, null, null, KEY_NAMESERVER, null, null, null);  

        return mDb.rawQuery("SELECT DISTINCT server, _id as _id from server order by _id", null);   
    }

    public Cursor fetchAllQueryDataAutoCompleteProfileName(){

    //      return mDb.query(DISTINCT, DATABASE_TABLE_PROFILE, new String[] {KEY_ROWIDPROFILE, KEY_NAMEPROFILE}, null, null, KEY_NAMEPROFILE, null, null, null);    
            //"SELECT DISTINCT (ip, _id) FROM userdata ORDER BY ip";

        return mDb.rawQuery("SELECT DISTINCT profile, _id from profile order by _id", null);    

        //return mDb.rawQuery("SELECT DISTINCT profile, _id as _id from profile order by _id", null);   
    } 



    public Cursor fetchAllQueryData() {

        return mDb.query(DISTINCT, DATABASE_TABLE_SERVER, new String[] {KEY_ROWIDSERVER,KEY_IP, KEY_PORT, KEY_NAMESERVER}, null, null, null, null, null, null);           
    }

    public Cursor fetchAllServersNotOnProfileData(long idProfile ){

        String sqlstart = "SELECT server.server FROM server INNER JOIN ( serpro INNER JOIN profile ON serpro._id = profile._id WHERE profile._id NOT LIKE '"; 
        String sqlend = "')ON server._id = serpro._id;";
        String sql = sqlstart + idProfile + sqlend;     

        return mDb.rawQuery(sql, null);

    }

 public Cursor fetchAllServersOnProfileData(long idProfile ){

        String sqlstart = "SELECT server.server FROM server INNER JOIN ( serpro INNER JOIN profile ON serpro._id = profile._id WHERE profile._id LIKE '"; 
        String sqlend = "')ON server._id = serpro._id;";
        String sql = sqlstart + idProfile + sqlend;     

        return mDb.rawQuery(sql, null);

    }

    public boolean updateServerData(long rowId, String ip, String port, String server) {
        ContentValues args = new ContentValues();
        args.put(KEY_IP, ip);
        args.put(KEY_PORT, port);
        args.put(KEY_NAMESERVER, server);

        return mDb.update(DATABASE_TABLE_SERVER, args, KEY_ROWIDSERVER + "=" + rowId, null) > 0;
    }

    public boolean updateProfileData(long rowId, String profile) {
        ContentValues args = new ContentValues();
        args.put(KEY_NAMEPROFILE, profile);

        return mDb.update(DATABASE_TABLE_PROFILE, args, KEY_ROWIDPROFILE + "=" + rowId, null) > 0;
    }


}

And the error is this:

05-14 10:07:46.766: ERROR/AndroidRuntime(324): Uncaught handler: thread main exiting due to uncaught exception
05-14 10:07:46.776: ERROR/AndroidRuntime(324): java.lang.RuntimeException: Unable to start activity ComponentInfo{citic.android.remoteir/citic.android.remoteir.ServerEdit}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2401)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.app.ActivityThread.access$2100(ActivityThread.java:116)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.os.Looper.loop(Looper.java:123)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.app.ActivityThread.main(ActivityThread.java:4203)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at java.lang.reflect.Method.invokeNative(Native Method)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at java.lang.reflect.Method.invoke(Method.java:521)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at dalvik.system.NativeStart.main(Native Method)
05-14 10:07:46.776: ERROR/AndroidRuntime(324): Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.database.AbstractCursor.checkPosition(AbstractCursor.java:580)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:172)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:41)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at citic.android.remoteir.ServerEdit.populateFields(ServerEdit.java:57)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at citic.android.remoteir.ServerEdit.onCreate(ServerEdit.java:41)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
05-14 10:07:46.776: ERROR/AndroidRuntime(324):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)

Thank you all, im pretty desperate with this :s

+1  A: 

Your query is returning 0 rows, which is why you are getting an error attempting to use the 1st row of a 0-row Cursor.

You may wish to log what _id value you are trying to use, to see if it makes sense. You can also download the database from your emulator to your development machine to inspect its contents.

CommonsWare