Everyone.
I'm developing the android app that send the data what was stored in sqlite database to server now.
For storing the data to sqlite, I used the insertOrThrow().
What I wanna know is, if it happen the occur to fail to send the data, I'm afraid of the data is not exist. After sending the data, the android app shows the message "OK". In other words, there are no the record at server database.
I'll share my code.
public long insertSubmitRecord(int type, String data, String picPath, String vdoPath, String devicesId, String bugDesc) {
try {
ContentValues values = new ContentValues();
values.put(SQLHelper.DATA, data);
values.put(SQLHelper.TYPE, type);
values.put(SQLHelper.PIC_PATH, picPath);
values.put(SQLHelper.VDO_PATH, vdoPath);
values.put(SQLHelper.DEVICES_ID, devicesId);
values.put(SQLHelper.BUG_DESC, bugDesc);
values.put(SQLHelper.UPLOADERROR, 200);
values.put(SQLHelper.UPLOADERRORINFO, "");
return db.insertOrThrow(SQLHelper.TABLE_SUBMIT_RECORD, null, values);
} catch (SQLException e) {
e.printStackTrace();
Log.e("ERROR", "Failed to insert row into database");
return -1;
}
}
How come that is not stored? Attention: insertOrThrow().
Please help me.
Related
I'm hoping that somebody may be able to help me with something that I'm stuck on. I've searched StackOverflow looking at some other solutions and nothing is working so far.
I'm using a ContentProvider, CursorLoader, and SQLiteOpenHelper to get data out of a SQLite database into some ListViews. This has been working fine for a long time. I'm able to make updates, deletions, etc. to the data and the changes are reflected in the ListViews thanks to some use of setNotificationUri on the cursors and ContentResolver's notifyChange function.
Recently, I've implemented a cloud backup feature for my app, where the database file is backed up to cloud storage for later retrieval. At this point, I run into problems.
I have no trouble bringing the database back down from the cloud and replacing the local database file with the inbound version. However, after doing this, my Cursors and Loaders continue to return data as it existed before the database file is replaced. If I exit the application and wait for its processes to end, then restart it, the new data then appears.
I know that Cursors and Loaders store data across the Activity lifecycle, so I believe this to be the source of my trouble, but any attempts I've made at invalidating this caching behaviour has failed.
What I've checked so far:
Verified that onCreateLoader is in fact getting called after the database swap and the CursorLoader is getting recreated. It is.
Verified that the new Cursor is getting swapped into my CursorAdapter via swapCursor. It is.
Double-checked that I was using the correct URI values when I tried using notifyChange. URI values matched what I use when I update the data for a particular Listview for normal CRUD operations.
The only thing that has worked is to recreate my SQLiteOpenHelper object before every query, rather than relying on the instance created in my ContentProvider onCreate function. I assume though that this is bad practice and would create a scenario where too many connections are opened as I understand that every SQLiteOpenHelper instance manages its own connection.
Any help appreciated. Some relevant code snippets...
DBHelper.java
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
...
public void ReplaceDatabase(Context c) throws IOException
{
// First, let's make sure the database is closed...
this.close();
File inboundFile = new File(c.getFilesDir(), this.INCOMING_DATABASE_NAME);
if(!inboundFile.exists()) {
throw new IOException("Incoming Database doesn't exist.");
}
File currentFile = c.getDatabasePath(this.DATABASE_NAME);
if(!currentFile.exists()) {
throw new IOException("Database doesn't exist.");
}
boolean deletionResult = c.deleteFile(this.BACKUP_DATABASE_NAME);
try {
InputStream input = new FileInputStream(currentFile);
File backupFile = new File(c.getFilesDir(),this.BACKUP_DATABASE_NAME);
OutputStream output = new FileOutputStream(backupFile);
byte[] buffer = new byte[1024];
int length;
while ((length = input.read(buffer))>0)
{
output.write(buffer, 0, length);
}
output.flush();
output.close();
input.close();
} catch (FileNotFoundException e) {
throw e;
}
try {
InputStream input = new FileInputStream(inboundFile);
currentFile.delete();
File databaseFile = c.getDatabasePath(this.DATABASE_NAME);
OutputStream output = new FileOutputStream(databaseFile);
byte[] buffer = new byte[1024];
int length;
while ((length = input.read(buffer))>0)
{
output.write(buffer, 0, length);
}
output.flush();
output.close();
input.close();
} catch (FileNotFoundException e) {
throw e;
}
c.getContentResolver().notifyChange(Asset.AssetTable.CONTENT_DETAIL_URI, null);
}
}
CoreProvider.java
public class CoreProvider extends ContentProvider {
private DBHelper dbHelper;
#Override
public boolean onCreate() {
dbHelper = new DBHelper(getContext());
return true;
}
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){
// Here I build the query. Then....
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor c = qb.query(
db, // The database to query
projection, // The columns to return from the query
selection, // The columns for the where clause
selectionArgs, // The values for the where clause
null, // don't group the rows
null, // don't filter by row groups
orderBy // The sort order
);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
}
I'm currently developing an android app that requires data to be inserted into an azure Mobile Service DB. An id string and a first login integer, to be exact. However the following error is being thrown up.
"IllegalArgumentException: The class representing the MobileServiceTable must have a single id property defined"
The id value that I need to insert into the database is being passed back from a fragment interface using passId(). Inside the override of this is where I am attempting to insert the values into azure as shown below.
#Override
public void passId(String id) {
userInstance user = new userInstance();
user.user_id = id;
user.first_login = 0;
mClient.getTable(userInstance.class).insert(user, new TableOperationCallback<userInstance>() {
public void onCompleted(userInstance entity, Exception exception, ServiceFilterResponse response) {
if (exception == null) {
// Insert succeeded
} else {
// Insert failed
}
}
});
The mClient var represents the MobileServicesClient as shown below
try {
mClient = new MobileServiceClient(
"https://xxxx.azure-mobile.net/",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
this);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
The table name that I am trying to insert the data into is "user_table" if that helps at all.
I hope you're able to help, and thanks in advance for any help you guys give me.
SOLUTION:
Because the Azure Table that I was attempting to add data to auto created an "id" column, the user object that I was using to construct user info to insert into the database had to define an "id" String. As shown below:
public class userInstance {
#com.google.gson.annotations.SerializedName("id")
public String mId;
#com.google.gson.annotations.SerializedName("user_id")
public String mUserId;
#com.google.gson.annotations.SerializedName("first_login")
public int mLogin;
}
I am new to Android and Window Azure.I have created a database in Azure and some Tables.now I successfully inserted data to the table but now I want to delete a row from that table.I have tried the following code but its not working and the amulater gets hing .Please help me to solve this problem
//code use for delete.
del.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final MobileServiceTable<Test> mtest;
mtest=mClient.getTable(Test.class);
try {
final MobileServiceList<Test>res=mtest.where().field("fullname").eq("hanan").execute().get();
mtest.delete("res");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
});
In the above code I just tried to delete the row whose fullname field =="hanan"
If you are using Moblie Service with SQL database as a backend server, there are 2 ways to delete an item form table referred on official guide
A, mTable.delete(item)
B, mTable.delete(IDString)
However, in your code:
mtest.delete("res");
you used a string in delete function, Azure will delete the row with id field equl “res”.
I am including a database in my Android application. I am following the guide here:
http://developer.android.com/training/basics/data-storage/databases.html
I have a "DatabaseHelper" class that extends SQLiteOpenHelper as suggested, and I have a Contract that holds the information about the table and implements 'BaseColumns'. Therein, I have a function for inserting a new row into the database:
public static void addUploadInfo(SQLiteOpenHelper dbHelper, UploadInfo info) {
// Gets the data repository in write mode
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = info.getContentValues();
// Insert the new row, returning the primary key value of the new row
long newRowId;
newRowId = db.insert(
UploadInfoTable.TABLE_NAME,
null,
values);
db.close(); // Closing database connection
info.setDatabaseId(newRowId);
}
I am using the database to store app related meta data about a file. When I create a new file, I run the above function, and a row is successfully added to the database (and the database is created successfully if needed). I can see it using:
public static List<UploadInfo> getUploadInfoList(SQLiteOpenHelper dbHelper) {
List<UploadInfo> infoList = new ArrayList<>();
SQLiteDatabase db = dbHelper.getReadableDatabase();
String allQuery = "SELECT * FROM " + UploadInfoTable.TABLE_NAME;
Cursor cursor = db.rawQuery(allQuery, null);
if (cursor.moveToFirst()) {
do {
infoList.add(new UploadInfo(cursor));
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return infoList;
}
However, when the app first loads, I insert a few initial entries into the database using:
#Override
public void onResume() {
super.onResume();
DatabaseHelper dbHelper = new DatabaseHelper(getActivity());
for (UploadInfo info: uploadList) {
UploadInfoTable.addUploadInfo(dbHelper, info);
}
}
These entries are assigned a new row ID that appears to be the correct value (not -1 indicating an error). There are no errors in the log. However, they are not found when I next run getUploadInfoList.
I have also tried this alternate insert function:
public static void addUploadInfo(SQLiteOpenHelper dbHelper, UploadInfo info) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = info.getContentValues();
// Insert the new row, returning the primary key value of the new row
db.beginTransaction();
long newRowId = -1;
try {
newRowId = db.insertOrThrow(
UploadInfoTable.TABLE_NAME,
null,
values);
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
db.close(); // Closing database connection
info.setDatabaseId(newRowId);
}
but I see the same result. In no case is info null. I always log the contents of the ContentValues. I use final variables for column names, so don't think I have an error in column name. This would show up as a row value of -1 anyway, and it doesn't.
Why would one implementation of the code insert successfully and the other not?
I suspect your code in onResume() is not successfully detecting the upgrade. Rather put all your code having to do with the upgrade in onUpgrade() instead of trying to detect an upgrade in onResume(). That should resolve the issue.
My application has a SQLite database to contain a list of highways. It shows them all in a list. It first tries to query the database for the roads. If the query doesn't return any, it calls another method that downloads a list from a remote server, and populates the database. After that returns, it immediately queries the database again.
That's how it should work. How it actually works is, the first query always returns nothing. It goes straight to downloading a fresh list, it inserts the list into the database, and queries again. The second query always returns the correct result. The strange thing is, I can repeat the operation without even exiting the application. Using the adb shell, I can read the SQLite3 database on the emulator. The data shown in the database is exactly as expected. But the application is behaving as though the data isn't there? Is there some behaviour I'm not aware of? Here's the code.
RoadsDataSource.java
public class RoadsDataSource {
private DataStorage data;
private static Context context;
public RoadsDataSource() {
this.data = new DataStorage(RoadsDataSource.context);
}
private List<Road> getRoads(Integer state) {
List<Road> roads = loadRoadsFromDb(state);
if (roads.isEmpty()) {
Request api = new Request(RoadsDataSource.context);
Roads apiRoads = api.fetchRoads(state);
this.data.storeRoads(apiRoads);
roads = loadRoadsFromDb(state);
}
return roads;
}
private List<Road> loadRoadsFromDb(Integer state) {
SQLiteQueryBuilder query = new SQLiteQueryBuilder();
query.setTables(Queries.ROAD_STATE_MATCHES);
Cursor results = query.query(
this.data.getWritableDatabase(),
new String[] {Tables.ROADS + "." + Tables.Roads.ID, Tables.ROADS + "." + Tables.Roads.TYPE, Tables.ROADS + "." + Tables.Roads.NUMBER},
Queries.ROADS_BY_STATE,
new String[] {state.toString()}, null, null, null
);
List<Road> roads = new ArrayList<Road>();
results.moveToFirst();
while (!results.isAfterLast()) {
roads.add(new Road(results.getInt(0), results.getString(1), results.getInt(2)));
results.moveToNext();
}
results.close();
System.out.println(roads.size());
return roads;
}
}
DataStorage.java
public class DataStorage extends SQLiteOpenHelper {
public void storeRoads(Roads roads) {
SQLiteDatabase db = this.getWritableDatabase();
for (Road road : roads.getRoads()) {
ContentValues roadRow = new ContentValues();
roadRow.put(Tables.Roads.ID, road.getId());
roadRow.put(Tables.Roads.TYPE, road.getType());
roadRow.put(Tables.Roads.NUMBER, road.getNumber());
try {
db.insertOrThrow(Tables.ROADS, null, roadRow);
} catch (SQLException e) {
}
ContentValues linkRow = new ContentValues();
linkRow.put(Tables.StatesRoads.STATE_ID, roads.getState());
linkRow.put(Tables.StatesRoads.ROAD_ID, road.getId());
try {
db.insertOrThrow(Tables.STATES_ROADS, null, linkRow);
} catch (SQLException e) {
}
}
}
}
Mo Kargas is right. Your db helper should look more like this http://code.google.com/p/android-notes/source/browse/trunk/src/com/bitsetters/android/notes/DBHelper.java?r=10
This may fix your issue though Replace
SQLiteDatabase db = this.getWritableDatabase();
with this
SQLiteDatabase db;
try {
db = dbHelper.getWritableDatabase();
} catch (SQLiteException e) {
db = dbHelper.getReadableDatabase();
}
I've had huge issues in the past with not closing the database handle - generally I do all db operations inside an SQLiteOpenHelper subclass, keeping a reference to the db, opening and closing it atomically.