Android Provider Testing - android

I am trying to test android content providers. I am writing code similar to given here, inserting into a db and then querying the db,
but sometimes and not always, the returned cursor has 0 rows. What may be the problem?
public class MyProviderTestCase extends ProviderTestCase2<MyProvider> {
private MockContentResolver mMockResolver;
....
public MyProviderTestCase() {
super(MyProvider.class, "com.example.MyProvider");
}
protected void setUp() throws Exception {
super.setUp();
mMockResolver = getMockContentResolver();
}
protected void tearDown() throws Exception {
super.tearDown();
}
#SmallTest
public void testInsertAndUpdate() {
...
SomeObject someObject = ...;
Uri insertedUri = mMockResolver.insert(MyrProvider.URI, someObject.createContentValues());
assertNotNull(insertedUri);
Log.d("test insert and update and delete:inserteduri", insertedUri+"");
Cursor c = mMockResolver.query(MyProvider.URI, null, null, null, null);
assertNotNull(c);
assertTrue(c.moveToFirst());// This assertion fails sometimes
}
}

Related

Unit testing: NoSuchMethodError at mock retrofit get request

When I run only method testInsert() test completes with no problem, but when I run a whole class I've got an error:
java.lang.NoSuchMethodError: com.dataart.kvarivoda.myapplication.api.PlacesApi.getNearbyPlaces(Ljava/lang/String;Ljava/lang/String;I)Lretrofit2/Call;
at GetPlacesTest.testLogin(GetPlacesTest.java:61)
....
Retrofit #GET interface is:
public interface PlacesApi {
#GET("/maps/api/place/nearbysearch/json")
PlacesResults getNearbyPlaces(#Query("key") String key, #Query("location") String location, #Query("radius") int radius);
}
My test class is:
public class GetPlacesTest extends ProviderTestCase2 {
PlacesApi mockApi;
EventBus mockEventBus;
PlacesApi api;
Cursor cursor;
String webApiKey;
public GetPlacesTest() {
super(PlacesContentProvider.class, "com.example.myName.myapplication.database.PROVE");
}
public void setUp() throws Exception {
super.setUp();
setContext(InstrumentationRegistry.getTargetContext());
//MockitoAnnotations.initMocks(this);
mockApi = Mockito.mock(PlacesApi.class);
mockEventBus = Mockito.mock(EventBus.class);
webApiKey = getContext().getResources().getString(R.string.webApiKey);
api = ((PlacesApp) getApplication()).getApi();
}
#Override
protected void tearDown() throws Exception {
super.tearDown();
if (cursor != null) {
cursor.close();
}
}
#Test
public void testInsert() throws Exception {
PlacesResults results1 = loadResults("getplaces.json");
Mockito.when(mockApi.getNearbyPlaces(eq("testkey"), Matchers.anyString(), Matchers.anyInt())).thenReturn(results1);
GetPlacesAction action = new GetPlacesAction(getContext().getContentResolver(), mockEventBus, mockApi, "testkey");
action.downloadPlaces();
//check
cursor = getContext().getContentResolver().query(PlacesContentProvider.getUri(DB.PlaceTable.DB_TABLE), null, null, null, null);
assertEquals(2, cursor.getCount());
cursor.moveToPosition(0);
assertEquals("461d123aeb1c1648abdd5e535989d2bc518cf28e", getColumn(DB.PlaceTable.COLUMN_ID));
assertEquals("Astral Tower & Residences", getColumn(DB.PlaceTable.COLUMN_TITLE));
assertEquals(getImageUrl("CoQBcwAAAMUTbLLt7doNLiVSnpGryeIJLVdrDnMPcqs3uV84zfvDklrBr1uYxitVMEZWzTD40xkM923ak8HfRtoGiNdi32mqzP6sKB3lOYNbbOQeaHZ3bStClwhWO3507ryh4bODvEfXc-l42r7rFXFAg9GLSd7N2tqoOgLwzTLray0d1sixEhAZaZ2_ajvBieZvUuPA72d7GhQTtFtpqT8j7UBYSHvq9AuRsoRSig"), getColumn(DB.PlaceTable.COLUMN_IMAGE));
assertEquals(locationToString(-33.868111), getColumn(DB.PlaceTable.COLUMN_LOCATION_LAT));
assertEquals(locationToString(151.195219), getColumn(DB.PlaceTable.COLUMN_LOCATION_LNG));
}
private PlacesResults loadResults(String file) throws IOException {
InputStream is = InstrumentationRegistry.getContext().getAssets().open(file);
return new GsonBuilder().create().fromJson(new InputStreamReader(is), PlacesResults.class);
}
private String getImageUrl(String photoReference) {
return new GoogleImagesUtil("testkey").getImageUrl(photoReference);
}
private String locationToString(double location) {
return String.valueOf(LocationsUtil.locationToInteger(location));
}
private String getColumn(String column) {
return cursor.getString(cursor.getColumnIndex(column));
}
private int getColumnInt(String column) {
return cursor.getInt(cursor.getColumnIndex(column));
}
}
After some trying I couldn't even compile and started to get “No tests found” error. Later I've found that there was some run configuration on the class, although I didn't add anything. I deleted run configuration following this answer:
https://stackoverflow.com/a/38190125/2574228
All the errors gone after that.

Android NPE running JUnit test

I'm trying to implement some tests in my application. One thing that I want to test is writing a java object to my db, then retrieving it and asserting the the object that comes out of the db matches the object that went in.
Here's my MySQLiteHelper application code:
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.concurrent.atomic.AtomicInteger;
class MySQLiteHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "unittesttester.db";
private static final int DATABASE_VERSION = 8;
private static final String LOG_TAG = MySQLiteHelper.class.getSimpleName();
private static final int WEATHER_STALENESS_PERIOD_MS = 60 * 5 * 1000; //5 minutes
private AtomicInteger mOpenCounter = new AtomicInteger();
private static MySQLiteHelper mInstance = null;
private SQLiteDatabase db;
private Context mContext;
public static MySQLiteHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySQLiteHelper(context.getApplicationContext());
}
return mInstance;
}
private MySQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(WeatherTable.CREATE_TABLE_WEATHER);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion <= DATABASE_VERSION) {
onCreate(db);
}
}
private synchronized SQLiteDatabase openDatabase() {
final int i = mOpenCounter.incrementAndGet();
if (i == 1) {
db = getWritableDatabase();
}
return db;
}
private synchronized void closeDatabase() {
final int i = mOpenCounter.decrementAndGet();
if (i == 0) {
db.close();
}
}
private void truncateWeatherTable() {
db = openDatabase();
db.delete(WeatherTable.TABLE_WEATHER, null, null);
closeDatabase();
}
public void deleteAndInsertWeather(Weather weather) {
db = openDatabase();
db.beginTransaction();
try {
truncateWeatherTable();
insertWeather(weather);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
closeDatabase();
}
}
private void insertWeather(Weather weather) {
db = openDatabase();
db.insert(WeatherTable.TABLE_WEATHER, null, makeWeatherCv(weather));
closeDatabase();
}
public Weather getWeather() {
db = openDatabase();
String sql = "SELECT * FROM " + WeatherTable.TABLE_WEATHER;
Cursor c = null;
Weather weather = null;
try {
c = db.rawQuery(sql, null);
if (c.moveToFirst()) {
weather = makeWeather(c);
//If sample too old return null
if (System.currentTimeMillis() - weather.getTimestamp() > WEATHER_STALENESS_PERIOD_MS) {
weather = null;
truncateWeatherTable();
}
}
} finally {
if (c != null) {
c.close();
}
closeDatabase();
}
return weather;
}
private Weather makeWeather(Cursor c) {
Weather weather = new Weather();
weather.setTimestamp(c.getLong(c.getColumnIndex(WeatherTable.COLUMN_TIMESTAMP)));
weather.setElevation(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_ELEVATION)));
weather.setTemperature(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_TEMPERATURE)));
weather.setDusk(c.getInt(c.getColumnIndex(WeatherTable.COLUMN_DUSK)));
weather.setNighttime(c.getInt(c.getColumnIndex(WeatherTable.COLUMN_NIGHTTIME)));
weather.setGravity(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_GRAVITY)));
weather.setDaytime(c.getInt(c.getColumnIndex(WeatherTable.COLUMN_DAYTIME)));
weather.setHumidity(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_HUMIDITY)));
weather.setPressure(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_PRESSURE)));
weather.setOkta(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_OKTA)));
weather.setDawn(c.getInt(c.getColumnIndex(WeatherTable.COLUMN_DAWN)));
return weather;
}
private ContentValues makeWeatherCv(Weather weather) {
ContentValues contentValues = new ContentValues();
contentValues.put(WeatherTable.COLUMN_TIMESTAMP, weather.getTimestamp());
contentValues.put(WeatherTable.COLUMN_TEMPERATURE, weather.getElevation());
contentValues.put(WeatherTable.COLUMN_TEMPERATURE, weather.getTemperature());
contentValues.put(WeatherTable.COLUMN_DUSK, weather.getDusk());
contentValues.put(WeatherTable.COLUMN_NIGHTTIME, weather.getNighttime());
contentValues.put(WeatherTable.COLUMN_GRAVITY, weather.getGravity());
contentValues.put(WeatherTable.COLUMN_DAYTIME, weather.getDaytime());
contentValues.put(WeatherTable.COLUMN_HUMIDITY, weather.getHumidity());
contentValues.put(WeatherTable.COLUMN_PRESSURE, weather.getPressure());
contentValues.put(WeatherTable.COLUMN_OKTA, weather.getOkta());
contentValues.put(WeatherTable.COLUMN_DAWN, weather.getDawn());
return contentValues;
}
}
Here's my test class for the class above:
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
import org.junit.Test;
import static org.mockito.Mockito.*;
public class MySQLiteHelperTest extends AndroidTestCase {
private MySQLiteHelper db;
private Weather mockedWeather = mock(Weather.class);
#Override
public void setUp() throws Exception {
super.setUp();
context = new MockContext();
setContext(context);
assertNotNull(context);
RenamingDelegatingContext renamingContext = new RenamingDelegatingContext(getContext(), "test_");
db = MySQLiteHelper.getInstance(renamingContext);
assertNotNull(db);
when(mockedWeather.getDawn()).thenReturn(0);
when(mockedWeather.getDaytime()).thenReturn(1);
when(mockedWeather.getDusk()).thenReturn(2);
when(mockedWeather.getElevation()).thenReturn(3.0);
when(mockedWeather.getGravity()).thenReturn(4.0);
when(mockedWeather.getHumidity()).thenReturn(5.0);
when(mockedWeather.getNighttime()).thenReturn(6);
when(mockedWeather.getOkta()).thenReturn(7.0);
when(mockedWeather.getPressure()).thenReturn(8.0);
when(mockedWeather.getTemperature()).thenReturn(9.0);
when(mockedWeather.getTimestamp()).thenReturn(10L);
}
#Override
public void tearDown() throws Exception {
super.tearDown();
}
public void testGetInstance() throws Exception {
}
public void testOnCreate() throws Exception {
}
public void testOnUpgrade() throws Exception {
}
#Test
public void testDeleteAndInsertWeather() throws Exception {
db.deleteAndInsertWeather(mockedWeather);
Weather actualWeather = db.getWeather();
assertEquals(mockedWeather.getDawn(), actualWeather.getDawn());
assertEquals(mockedWeather.getDaytime(), actualWeather.getDaytime());
assertEquals(mockedWeather.getDusk(), actualWeather.getDusk());
assertEquals(mockedWeather.getElevation(), actualWeather.getElevation());
assertEquals(mockedWeather.getGravity(), actualWeather.getGravity());
assertEquals(mockedWeather.getHumidity(), actualWeather.getHumidity());
assertEquals(mockedWeather.getNighttime(), actualWeather.getNighttime());
assertEquals(mockedWeather.getOkta(), actualWeather.getOkta());
assertEquals(mockedWeather.getPressure(), actualWeather.getPressure());
assertEquals(mockedWeather.getTemperature(), actualWeather.getTemperature());
assertEquals(mockedWeather.getTimestamp(), actualWeather.getTimestamp());
}
public void testDeleteWeather() throws Exception {
}
public void testInsertWeather() throws Exception {
}
public void testGetWeather() throws Exception {
}
public void testWeatherMakeCv() throws Exception {
}
}
When I run the test I am getting a NPE during my test. It seems to occur when the MySQLiteHelper class has its db = getWritableDatabase() line. getWriteableDatabase() is a public method from the base class.
I don't think I understand why this test results in an NPE. In my test I call the static method, MySQLiteHelper.getInstance(Context context) which should initialize the class. It is my assumption that calling getInstance will provide me with a fully initialized instance of MySQLiteHelper. Why does this not seem to be happening?
EDIT:
The problem I have now is that when getWritableDatabase() is called it returns null instead of an instance of SQLiteDatabase.
I ended completing my goals of unit testing my sqlite database. The problem seemed to be that I needed to use the build artifact called Android Instrumentation Test instead of the Unit Test build artifact.
I setup a test class in my app/src/androidTest/java directory. The test class extended InstrumentationTestCase.
When I setup my database I use the context provided by getInstrumentation().getTargetContext(). This was important because originally I tried to use getInstrumentation().getContext() and I found that that would always result in a SQLiteCantOpenDatabaseException.
So it seemed my problems occurred because:
1) I wasn't using the correct test artifact
2) I wasn't using the correct test base class
3) I wasn't getting the context correctly
AndroidTestCase#getContext() returns whatever Context you've set with setContext() and you haven't set anything, so a null is returned`.
Using a null context with SQLiteOpenHelper will NPE when the database is being opened e.g. with getWritableDatabase().
See Getting context in AndroidTestCase or InstrumentationTestCase in Android Studio's Unit Test feature for more details on how to set up a Contex in test cases.

Android: Database INSERT triggers exception "getWritableDatabase called recursively"

Whenever the asynchonous task tries to insert data into the SQLite database I run into the following exception.
java.lang.IllegalStateException: getWritableDatabase called recursively
The data is produced by a service that runs separate asynchonous tasks to download, convert and finally to insert the data. I am not sure if the context objects I am passing are correct. Please note the comments I added to the source code. In the following I added the relevant classes and functions. Please leave a comment if you need futher information.
public class CustomServiceHelper {
// This method gets called by the activities.
public static void loadData(Context context) {
Intent intent = new Intent(context, CustomService.class);
context.startService(intent);
}
}
...
public class CustomService extends Service {
private void startStoringTask(Users users) {
// Passing the context of the service.
mStoringTask = new StoringTask(this);
Object[] params = { users };
mStoringTask.execute(params);
}
}
...
public class UsersProvider extends ContentProvider {
#Override
public boolean onCreate() {
// Not sure if getContext() is correct.
mDatabase = new CustomDatabase(getContext());
return true;
}
#Override
public Uri insert(Uri uri, ContentValues values) {
switch (URI_MATCHER.match(uri)) {
case URI_CODE_USERS:
long id = mDatabase.insertUsers(values);
// TODO: Not sure about the return value.
return ContentUris.withAppendedId(uri, id);
}
return null;
}
}
...
public class CustomDatabase {
public class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
CustomSQLiteOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(TABLE_USERS_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
throw new UnsupportedOperationException();
}
}
private CustomSQLiteOpenHelper mDatabaseHelper = null;
public CustomDatabase(Context context) {
// The context is passed in by the UsersProvider.
mDatabaseHelper = new CustomSQLiteOpenHelper(context);
}
public long insertUsers(ContentValues contentValues) {
return mDatabaseHelper.getWritableDatabase().insert(
CustomSQLiteOpenHelper.TABLE_USERS, null, contentValues);
}
}
...
public class StoringTask extends AsyncTask<Object, Void, Boolean> {
private Context mContext = null;
public StoringTask(Context context) {
mContext = context;
}
#Override
protected Boolean doInBackground(Object... params) {
Users users = (Users)params[0];
return storeUser(users);
}
private boolean storeUsers(Users users) {
if (users == null) return false;
// Not sure if calling getContentResolver on this context is correct.
ContentResolver contentResolver = mContext.getContentResolver();
Iterator<User> iterator = users.iterator();
do {
User user = iterator.next();
storeUser(contentResolver, user);
}
while (iterator.hasNext());
return true;
}
private void storeUser(ContentResolver contentResolver, User user) {
ContentValues cv = new ContentValues(1);
cv.put(CustomDatabase.Contract.COLUMN_NAME, user.name);
contentResolver.insert(UsersProvider.Contract.URI_USERS, cv);
}
}
When I run the application in Debug mode I end up in the framework class ThreadPoolExecutor in the finally block of the runWorker() method.
Edit:
Here is the full exception stack trace.
java.lang.RuntimeException: An error occured while executing doInBackground()
android.os.AsyncTask$3.done(AsyncTask.java:200)
java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
java.util.concurrent.FutureTask.setException(FutureTask.java:124)
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
java.util.concurrent.FutureTask.run(FutureTask.java:137)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
java.lang.Thread.run(Thread.java:1096)
Caused by: java.lang.IllegalStateException: getWritableDatabase called recursively
android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:81)
com.test.users.database.CustomDatabase.insertUsers(CustomDatabase.java:125)
com.test.users.database.CustomDatabase$CustomSQLiteOpenHelper.insertTestData(CustomDatabase.java:85)
com.test.users.database.CustomDatabase$CustomSQLiteOpenHelper.onCreate(CustomDatabase.java:60)
android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:106)
com.test.users.database.CustomDatabase.insertUsers(CustomDatabase.java:125)
com.test.users.contentprovider.UsersProvider.insert(UsersProvider.java:51)
android.content.ContentProvider$Transport.insert(ContentProvider.java:174)
android.content.ContentResolver.insert(ContentResolver.java:587)
com.test.users.tasks.StoringTask.storeFeature(StoringTask.java:82)
com.test.users.tasks.StoringTask.storeResponse(StoringTask.java:58)
com.test.users.tasks.StoringTask.doInBackground(StoringTask.java:32)
com.test.users.tasks.StoringTask.doInBackground(StoringTask.java:1)
android.os.AsyncTask$2.call(AsyncTask.java:185)
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
I did not mention the method CustomSQLiteOpenHelper.insertTestData() which invokes getWritableDatabase(). I call the method insertTestData() in CustomSQLiteOpenHelper.onCreate(). The crash happens everytime whenever the application has not created a database yet. To summarize, hawaii.five-0 was totally right!
java.lang.IllegalStateException: getWritableDatabase called recursively
So this kind of Exception is usually thown when you use getWritableDatabase() or getReadableDatabase() in onCreate or onUpgrade methods of SQLiteOpenHelper.

Cursor fetching performance in non UI thread

I've got a performance problem while fetching data from a cursor in AsyncTaskLoader. Testing in android API level 10. For example 2 classes with cursor - TestFragmentUI fetching data in UI thread and TestFragment fetching data in none UI thread.
public class TestFragment extends Fragment implements LoaderManager.LoaderCallbacks<Object> {
...
#Override
public void onActivityCreated(Bundle savedInstanceState) {
...
getLoaderManager().initLoader(0, null, this);
...
}
public android.support.v4.content.Loader<Object> onCreateLoader(
int id, Bundle args) {
return new Loader(getActivity());
}
class Loader extends AsyncTaskLoader<Object> {
public Loader(Context context) {
super(context);
}
public Object loadInBackground() {
...
DataBaseHelper helper = new DataBaseHelper(getContext());
SQLiteDatabase database = helper.getReadableDatabase();
long start = System.currentTimeMillis();
Cursor data = database.rawQuery(String.format(SQL_LOAD, parametr), null);
while (data.moveToNext()) {
String number = data.getString(data.getColumnIndex("number"));
}
data.close();
Log.i(TAG, "load: " + (System.currentTimeMillis() - start));
...
}
}
...
}
and
public class TestFragmentUI extends Fragment {
...
#Override
public void onActivityCreated(Bundle savedInstanceState) {
...
DataBaseHelper helper = new DataBaseHelper(getActivity());
SQLiteDatabase database = helper.getReadableDatabase();
...
long start = System.currentTimeMillis();
Cursor data = database.rawQuery(String.format(SQL_LOAD, parametr), null);
while (data.moveToNext()) {
String number = data.getString(data.getColumnIndex("number"));
}
data.close();
Log.i(TAG, "load: " + (System.currentTimeMillis() - start));
...
}
...
}
In emulator TestFragment class output time that is 10 times slower than output TestFragmentUI and visually it is very noticeable.
Any ideas?
use it on a real device (your phone) to test since emulators are slow
The answer was to change background process priority (Process.setThreadPriority) coz by default AsyncTask runs at background priority.

SQLite database leak found

I'm creating an application. I'm getting this error:
11-08 13:46:24.665: ERROR/Database(443):
java.lang.IllegalStateException:
/data/data/com.testproj/databases/Testdb SQLiteDatabase created and
never closed
I can't seem to find the reason for this, as it somethimes shows me the error, sometimes not. Here is my code:
public class SQLiteAssistant extends SQLiteOpenHelper {
public SQLiteAssistant(Context context){
super(context, DB_NAME, null, DB_VERSION_NUMBER);
this.myContext = context;
}
public void openDataBase() throws SQLException{
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
public void closeDataBase() {
if(this.myDataBase != null) {
if(this.myDataBase.isOpen())
this.myDataBase.close();
}
}
}
}
In another class, I have these queries:
public class Db{
private static SQLiteAssistant sqlite;
public static String getSomeString(Context ctx) {
sqlite = new SQLiteAssistant(ctx);
sqlite.openDataBase();
Cursor cursor = sqlite.myDataBase.rawQuery("SELECT someColumn from SomeTable",null);
if (cursor != null) {
if (cursor.getCount()==1) {
if(cursor.moveToFirst()) {
String testString = cursor.getString(cursor.getColumnIndex("someColumn"));
cursor.close();
sqlite.closeDataBase();
sqlite.close();
return testString
}
}
}
sqlite.closeDataBase();
sqlite.close();
return null;
}
}
My problem is when I start a new activity in which I get an AsyncTask. This task gets data from a web service and accesses the database for the String. Here is the AsyncTask:
protected class BackTask extends AsyncTask<Context, String, String> {
#Override
protected String doInBackground(Context... params) {
try{
//get requeste data from the database
//access the web service
return result;
} catch (Exception e) {
return null;
}
return null;
}
}
If I let the activity take its course, everything goes fine. If I don't and quickly press the back button, I get the error. Any suggestion on how to solve this problem?
Am not sure you're using SQLiteOpenHelper properly... you don't need that myDataBase field, the idea is that it manages your database connection for you. Don't subclass in that way... unless you're doing things in onCreate() etc that aren't posted here it looks like you can just use SQLiteOpenHelper directly, i.e.:
SQLiteOpenHelper sqlite = new SQLiteOpenHelper(ctx, DB_PATH+DB_NAME, null,
DB_VERSION_NUMBER);
Assuming that ending the activity should also stop your background task, I'd recommend calling AsyncTask.cancel(true) from your Activity.onPause(). Ensure the database is cleaned up from onCancelled().
And if your background task is the only thing reading the database then make it own the SQLiteOpenHelper instance. It's easy to get into trouble with static data, so it's best avoided IMHO. I'd do something like this:
protected class BackTask extends AsyncTask<String, Integer, String>
{
private SQLiteOpenHelper sqlite;
public void BackTask(Context ctx) {
sqlite = new SQLiteOpenHelper(ctx, DB_PATH+DB_NAME, null,
DB_VERSION_NUMBER);
}
#Override
protected String doInBackground(String... params)
{
try {
//get requeste data from the database
//access the web service
return result;
} catch (Exception e) {
}
return null;
}
#Override
protected void onCancelled() {
sqlite.close();
}
#Override
protected void onPostExecute(String result)
sqlite.close();
// Update UI here
}
}
I think this part :
cursor.close();
sqlite.closeDataBase();
sqlite.close();
must be in a finally close like
Try{
//Do something
}
catch(){
//Catch exception
}
finally{
//Close cursor or/and eventually close database if you don't need it in the future
}
Also don't forget to close database in onDestroy method .
onCreate(Bundle b){
//create database instance
}
onDestroy{
//close db
}

Categories

Resources