I have a huge MS Access database file (aprrox. 1gb) and about 5 different GUI (FXML). Each fxml contains data from different tables. I am using ucanaccess to connect with database. Now I am having problem in connecting with database. I never get connection. It works fine with smaller database file. I am using service and task for background thread. Could someone tell me what can be the best approach to overcome this problem.
private Service backgroundService;
private Connection ucaConn;
#FXML
private void handleButtonAction(ActionEvent event) {
backgroundService = new Service() {
#Override
protected Task createTask() {
return new Task() {
#Override
protected Object call() throws Exception {
try {
ucaConn = getUcanaccessConnection(DataCarrier.getInstance().getDatabaseLocation());
} catch (SQLException | IOException ex) {
Logger.getLogger(HomeController.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
};
}
};
backgroundService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
System.out.println("Done");
errorMessage.textProperty().unbind();
String timeStamp = new SimpleDateFormat("mm:ss").format(Calendar.getInstance().getTime());
System.out.println("End time: " + timeStamp);
}
});
errorMessage.textProperty().bind(backgroundService.messageProperty());
backgroundService.restart();
}
}
}
private static Connection getUcanaccessConnection(String pathNewDB) throws SQLException,
IOException {
String url = UcanaccessDriver.URL_PREFIX + pathNewDB + ";newDatabaseVersion=V2003";
return DriverManager.getConnection(url, "sa", "");
}
Related
I have a function which is supposed to return a list from the result of a Task API.
#Override
public List performQuery(boolean isPaginationQuery, boolean isSortingQuery {
try {
TaskImpl taskImpl = new TaskImpl(isPaginationQuery,
isSortingQuery);
queryExecutor.submit(taskImpl).get();
return taskImpl.get();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Inner class which performs the updates
private class TaskImpl extends Task<List> {
private boolean isPaginationQuery, isSortingQuery;
public TaskImpl(boolean isPaginationQuery, boolean isSortingQuery) {
this.isPaginationQuery = isPaginationQuery;
this.isSortingQuery = isSortingQuery;
}
#Override
protected List call() throws Exception {
Platform.runLater(() -> {
loaderContainer.setVisible(true);
loaderContainer.toFront();
});
HSession hSession = new HSession();
TaskInfoDao taskInfoDao = new TaskInfoDaoImpl(hSession.getSession(), currentConnection.getConnectionId());
if (!isPaginationQuery && !isSortingQuery) {
paginator.setTotal(taskInfoDao.getTaskInfoWithFiltersCount(paginator.getFilterMap(), false));
}
Stream<TaskInfo> resultStream = taskInfoDao.getTaskInfoWithFilters(paginator.getFilterMap(), false,
paginator.getStartIndex() * paginator.getPageSize(),
paginator.getPageSize() * paginator.getPageGap());
List<TaskInfoTableView> data = createData(resultStream);
hSession.close();
return data;
}
#Override
protected void succeeded() {
super.succeeded();
try {
//set the pagination if the task is complete
//and it is not a pagination query
if (!isPaginationQuery) {
((TaskInfoViewController) uiController).setPagination(
FXCollections.observableArrayList(get()));
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
#Override
protected void cancelled() {
super.cancelled();
updateMessage("Cancelled!");
}
#Override
protected void failed() {
super.failed();
updateMessage("Failed!");
}
}
performQuery function calls the thread and waits for its result.
The loader is being displayed from inside the TaskImpl class using Platform.runLater.
But the loader does not appear until the task has finished i.e. loader appears after the completion of call() function's execution.
When i remove the taskImpl.get() the loader works fine.
Any help is appreciated.
P.S. : Under any case, I need the result of the Task API outside the Inner class( outside TaskImpl )
First of all, it seems like you are not very familiar with asynchronous programming. Having performQuery() to return a List shows that you are expecting to run this synchronously - there is no way for you to return results before you get the results. This is exactly why you are freezing your UI.
The important thing to understand about asynchronous programming is, you would start doing something (i.e. a task) in another thread, and return immediately. When there is result returned from the task, you switch back to the UI (JavaFX Application) thread to update it. You can see this as event-driven approach.
Therefore, for your case, you should directly update the list (the list which you are returning in performQuery()) in the succeeded() method that you have overridden in TaskImpl class.
If the list that you should be updating is not in the scope of TaskImpl, then you can the functional interfaces in java.util.function package to do it for you. This means that you would create that functional interface object at the right scope, and pass in into TaskImpl during object construction, and call that interface in succeeded().
Update
If I assume this is what calls performQuery():
public class MyController {
#FXML
TableView<Foo> tableView;
public void initialize() {
List result = queryController.performQuery(true, true);
tableView.getItems().addAll(result);
}
}
Then, I would probably do something like this:
public class MyController {
#FXML
TableView<Foo> tableView;
public void initialize() {
List result = queryController.performQuery(true, true, list -> tableView.getItems.addAll(list));
}
}
public class QueryController {
#Override
public void performQuery(boolean isPaginationQuery, boolean isSortingQuery, java.util.function.Consumer<List> onQuerySucceeded) {
try {
TaskImpl taskImpl = new TaskImpl(isPaginationQuery,
isSortingQuery, onQuerySucceeded);
queryExecutor.submit(taskImpl);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
private class TaskImpl extends Task<List> {
private final java.util.function.Consumer<List> onQuerySucceeded;
public TaskImpl(boolean isPaginationQuery, boolean isSortingQuery, java.util.function.Consumer<List> onQuerySucceeded) {
this.isPaginationQuery = isPaginationQuery;
this.isSortingQuery = isSortingQuery;
this.onQuerySucceeded = onQuerySucceeded;
}
#Override
protected void succeeded() {
super.succeeded();
// Not sure what the original codes are doing.
try {
//set the pagination if the task is complete
//and it is not a pagination query
if (!isPaginationQuery) {
((TaskInfoViewController) uiController).setPagination(
FXCollections.observableArrayList(get()));
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// This is what is being added in
onQuerySucceeded.accept(this.getValue());
}
}
I'm wreting a SpringBoot web service use websocket to send message to client and using JPA to save data.
in project I use a thread to create a data ,and then use JPA to save it ,use Websocket to show data. But it doesn't work with a NullPointExecption.
this is my code:
#RestController
#ServerEndpoint("/websocket")
public class CrawlingController {
private final Logger logger = LoggerFactory.getLogger(CrawlingController.class);
#Autowired
private SimulateDataRepository simulateDataRepository;
private static GlobalStatus globalStatus = GlobalStatus.getInstance();
private Session session;
private static CopyOnWriteArraySet<CrawlingController> crawlingControllers =
new CopyOnWriteArraySet<>();
#OnOpen
public void onOpen(Session session) throws Exception {
this.session = session;
crawlingControllers.add(this);
String message = dataCrawling();
}
#OnMessage
public void onMessage(String message, Session session) throws IOException {
for (CrawlingController controller : crawlingControllers)
sendMessage(message);
}
#OnClose
public void onClose() {
crawlingControllers.remove(this);
if (crawlingControllers.size() == 0)
end();
session=null;
end();
}
private void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
public void onError(Session session, Throwable error) {
logger.error(error.getMessage());
System.out.println("websocket found something error!");
}
#RequestMapping("/start")
public String dataCrawling() throws Exception {
if (!globalStatus.isDataCrawling) {
Process process = null;
synchronized (globalStatus) {
process = Utils.crawling();
globalStatus.crawlingProcss = process;
globalStatus.isDataCrawling = true;
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
new Thread(() -> {
try {
stuffSimulate(bufferedReader);
} catch (IOException | ParseException e) {
logger.error(e.getMessage());
}
}).start();
return "start Finish!";
} else return "faild";
}
public void stuffSimulate(BufferedReader reader) throws IOException, ParseException {
line = reader.readLine();
while (globalStatus.isDataCrawling) {
SimulateData simulateData = new SimulateData();
.... ...
simulateData.setData(data.toString());
this.saveAndShow(simulateData);
}
}
}
}
private void saveAndShow(SimulateData simulateData) throws IOException {
simulateData = simulateDataRepository.saveAndFlush(simulateData);
SummaryData summaryData = SimulateService.obtainSummary(simulateData);
onMessage(summaryData.printSummary(),this.session);
summaryData.sout();
}
}
simulateDataRepository can be work when i use http://localhost:8080/start.
the mysql can get data.
But it cna't be work when i use websocket!!!
The error meaasge said that:
Exception in thread "Thread-5" java.lang.NullPointerException
at cn.linhos.controller.CrawlingController.saveAndShow(CrawlingController.java:293)
at cn.linhos.controller.CrawlingController.stuffSimulate(CrawlingController.java:172)
at cn.linhos.controller.CrawlingController.lambda$dataCrawling$0(CrawlingController.java:104)
at java.lang.Thread.run(Thread.java:748)
why simulateDataRepository can't saveAndFlush when websocket but can do it when i use "/start"?
how should i do to make websocket work ?
UPDATE:
I have learned what I am looking to do is to use the Async within Retrofit with multiple queries too. I have updated my code, but I cannot get the async with the queries.
I am using Retrofit to make my data calls to a movie database and need to change the sort order depending on user settings. I am not clear how I could add this functionality to my interface.
sort_by=highest_rating.desc
or
sort_by=popularity.desc
Interface:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<MovieDbModel> response);
}
UPDATED API INTERFACE:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie?sort_by=popularity.desc&api_key=xxxxxxx")
void getMoviesByPopularityDesc(Callback<MovieDbModel> response);
#GET("/3/discover/movie?sort_by=vote_average_desc&api_key=xxxxxxxx")
void getMoviesByVotingDesc(Callback<MovieDbModel> response);
}
UPDATED DATA CALL THAT WORKS:
private void makeDataCall(String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
if (sortPreference.equals(this.getString(R.string.sort_order_popularity)) ){
apiLocation.getMoviesByPopularityDesc (new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
} else {
apiLocation.getMoviesByVotingDesc( new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
My call for the data:
private void makeDataCall (String apiKey, String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
apiLocation.getData(apiKey, sortPreference, new Callback<MovieDbModel>){
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
I found a way to do Synchronously, but not asynchronously.
From your question and comment, IHMO, you should import retrofit.Callback; instead of import com.squareup.okhttp.Callback;
My code as the following has no compile error:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// creating a RestAdapter using the custom client
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL_BASE)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient(mOkHttpClient))
.build();
WebService webService = restAdapter.create(WebService.class);
retrofit.Callback<GetRoleData> callback = new Callback<GetRoleData>() {
#Override
public void success(GetRoleData getRoleData, retrofit.client.Response response) {
}
#Override
public void failure(RetrofitError error) {
}
};
webService.getData("api_key", "sort_by", callback);
}
Interface:
public interface WebService {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<GetRoleData> response);
}
So, please check your code again
After unsuccessful attempts to find what is the problem with my IntentService, (reading and googling) I decide to ask at stakeoverflow. I couldn't figure our what is wrong with this code. I actually want to start a service after receiving result from another activity. I do get result from that activity then comes to the method from where i want to start this service.
Service Starter Code
Intent templateCreationIntent = new Intent(getApplicationContext(), TemplateCreationService.class);
templateCreationIntent.putExtra(TemplateCreationService.PARAM_IN_MSG,userName);
startService(templateCreationIntent);
Service Code
public class TemplateCreationService extends IntentService{
private static final String TAG = "TemplateCreationService";
public static final int STATUS_RUNNING = 0;
public static final int STATUS_FINISHED = 1;
public static final int STATUS_ERROR = 2;
static final String TEST_RAW_DATA_PATH = Environment.getExternalStorageDirectory() +"/gaitDataRecording"+ "/rawTestingData" + "/acc/";
public static String userName;
public static String cycleLength;
public static final String PARAM_OUT_MSG = "omsg";
public static final String PARAM_IN_MSG = "imsg";
public TemplateCreationService() {
super(TemplateCreationService.class.getName());
// TODO Auto-generated constructor stub
}
#Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG,"Template Creation Service Started");
userName = intent.getStringExtra(PARAM_IN_MSG);
try {
Boolean b = DataProcessingStepsV2.gaitDataLoading(TRAIN_RAW_DATA_PATH, userName);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
double []gaitCycleLengths = DataProcessingStepsV2.getCycleLengths();
cycleLength = gaitCycleLengths.toString();
// processing done hereā¦.
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ResponseReceiver.ACTION_RESP);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(PARAM_OUT_MSG,cycleLength);
sendBroadcast(broadcastIntent);
}
}
Manifest
<service android:name=".gait_authentication_segmentation.TemplateCreationService"
android:exported = "false"/>
Main Activity Registering Receiver
IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new ResponseReceiver();
registerReceiver(receiver, filter);
Broadcast Receiver
public class ResponseReceiver extends BroadcastReceiver {
public static final String ACTION_RESP =
"at.usmile.gait_authentication.intent.action.MESSAGE_PROCESSED";
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(getApplicationContext(), intent.getStringExtra(TemplateCreationService.PARAM_OUT_MSG),Toast.LENGTH_LONG).show();
//String text = intent.getStringExtra(SimpleIntentService.PARAM_OUT_MSG);
//result.setText(text);
}
}
I think the name of Service in the AndroidManifest.xml is not correct. It can be:
It is not the fully qualified name.
There is some spelling mistake.
Try giving full package name with the service name and give it a try.
I've looked through this question as well : problem about sqlite database, no such table:
but have had no success in fixing the problem.
As the title mentions, the exact same code was able to run on the emulator fine(displays the table) but runs into the exception with "no such table" found on the device. Using an HTC Desire Z Android version 2.2.1
I was basically following this tutorial: http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/
The idea being to copy a preloaded database to the directory which the android app will use to make changes to, then copy out to the sd card upon a save being called. However, although the copy from the assets folder to the app database directory works fine, and the copy to the SD card works fine (tested by opening the db file copied out to the sd card using an sqlite browser), trying to display the database on the device gives me a problem whereas i've run into no problems at all with the emulator.
here is the code for the database helper:
public class DatabaseHelper extends SQLiteOpenHelper{
private static String DB_PATH = "/data/data/com.mko.preloaddb/databases/";
private static String DB_NAME = "preloaddb";
private SQLiteDatabase myDB;
private final Context myContext;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
/**
* Creates DB by copying over DB from assets if it doesn't exist yet
* #throws IOException
*/
public void createDatabase() throws IOException{
boolean dbExist = checkDatabase();
if(dbExist){
Log.e("DatabaseHelper","database exists");
}else{
this.getReadableDatabase().close();
try{
//copy preloaded db from assets if it doesn't exist yet
copyDatabase();
}catch(IOException e){
throw new Error("Error copying database");
}
}
}
public void openDatabase() throws SQLException{
//open the database
String myPath = DB_PATH + DB_NAME;
myDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
/***
* Copies preloaded db from assets
* #throws IOException
*/
private void copyDatabase() throws IOException{
//Open local db as input steam
InputStream myInput = myContext.getAssets().open(DB_NAME);
//Path to just created empty db
String outFileName = DB_PATH + DB_NAME;
//open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while((length = myInput.read(buffer))>0){
myOutput.write(buffer,0,length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
private boolean checkDatabase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database doesn't exist yet, so checkDB will be null
}
if(checkDB !=null){
checkDB.close();
}
return checkDB !=null ? true : false;
}
}
And here is the code for the activity that calls it:
public class PreloadDBTestActivity extends Activity {
/** Called when the activity is first created. */
Application myApp;
DatabaseHelper myDbHelper;
SQLiteDatabase myDb;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myApp = this.getApplication();
myDbHelper = new DatabaseHelper(this);
setContentView(R.layout.main);
}
public void refreshViewTable(View v){
TableLayout tl = (TableLayout)findViewById(R.id.tbl_dbview);
if(myDb==null || !myDb.isOpen()){
openDB(null);
}
String[] result_columns = new String[]{"_id","baseclassname","basehealth"};
Cursor allRows = myDb.query(true, "baseclasses", result_columns, null, null, null, null, null, null);
if(allRows.moveToFirst()){
do{
String classname = allRows.getString(1);
TableRow curr = new TableRow(this);
TextView text = new TextView(this);
text.setText(classname);
curr.addView(text);
tl.addView(curr);
}while(allRows.moveToNext());
}
}
public void openDB(View v){
TextView tv = (TextView)findViewById(R.id.lbl_debug);
try{
myDbHelper.createDatabase();
}catch (IOException ioe){
throw new Error("Unable to create database");
}
try{
myDb = myDbHelper.getWritableDatabase();
}catch(SQLiteException e){
tv.setText("Unable to open writable database");
}
Toast.makeText(this, "Successful open, copy should work", Toast.LENGTH_LONG).show();
}
public boolean copyDbToSd(View v){
File dbfile = new File(Environment.getDataDirectory()+"/data/com.mko.preloaddb/databases/preloaddb");
File exportDir = new File(Environment.getExternalStorageDirectory(),"/exampledata/example");
TextView tv = (TextView)findViewById(R.id.lbl_debug);
if(myDb.isOpen()){
myDb.close();
}
if(!exportDir.exists()){
boolean success = exportDir.mkdirs();
tv.setText("Making dir");
if(success){
Toast.makeText(this, "Success expor dir !"+exportDir.getAbsolutePath(), Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, "No success expor dir =("+exportDir.getAbsolutePath(), Toast.LENGTH_LONG).show();
}
}
if(!dbfile.exists()){
tv.setText("Database file does not exist or wrong directory "+dbfile.getAbsolutePath());
}else{
tv.setText("Database file found! " +dbfile.getAbsolutePath());
}
File file = new File(exportDir,dbfile.getName());
try{
file.createNewFile();
if(!file.exists()){
Toast.makeText(this, "DestinationFile does not exist!", Toast.LENGTH_LONG).show();
}
this.copyfile(dbfile, file);
return true;
}catch (IOException e){
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
Log.e("Preload", e.getMessage(), e);
return false;
}
}
private void copyfile(File src, File dst) throws IOException{
FileChannel inChannel = new FileInputStream(src).getChannel();
FileChannel outChannel = new FileOutputStream(dst).getChannel();
try{
inChannel.transferTo(0, inChannel.size(), outChannel);
}finally{
if(inChannel!=null){
inChannel.close();
}
if(outChannel!=null){
outChannel.close();
}
}
}
private boolean isExternalStorageAvail(){
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
Just in case it's confusing, i've bound the methods "openDB","copyDbToSd" and "refreshViewTable" to buttons on the gui, and I hit the buttons in the order of "openDB", "refreshViewTable" and "copyDBToSd"
I've already had the same problem with the method
SQLiteDatabase.openDatabase
the method getWritebleDatabase() calls the onCreate() method of the DBHandler (if DB file doesn't exists, then onOpen() ).
So, maybe you can take a look at the code below:
public class SqlDBAdapter {
private static final String DB_NAME = "projHours.sqlite";
private static final int DB_VERSION = 1;
private static Context c;
private SQLiteDatabase db;
private SQLiteOpenHelper sqlDBHelp;
/**
* Constructor for the SQL DB Adapter, copy DB from assets if not exists in /data/data/<package-name>/databases
*
* #param c
*/
public SqlDBAdapter(Context c) {
super();
SqlDBAdapter.c = c;
sqlDBHelp = new SqlDBHelper();
}
/**
* Open the SQL DB as Writable
*/
public void openDB() {
try {
db = sqlDBHelp.getWritableDatabase();
} catch (SQLiteException ex) {
Toast.makeText(c, "DB with filename " + DB_NAME + "coudn't be opend!", Toast.LENGTH_SHORT);
}
}
/**
* Close the SQL DB
*/
public void closeDB() {
db.close();
}
/**
* Helper class for the SQL DB Adapter
*/
static class SqlDBHelper extends SQLiteOpenHelper {
private static final String DB_PATH = "/data/data/" + c.getPackageName() + "/databases/" + DB_NAME;
public SqlDBHelper() {
super(c, DB_NAME, null, DB_VERSION);
createDB();
}
private void createDB() {
SharedPreferences prefs = c.getSharedPreferences("sharedPrefs", 0);
boolean dbExists = prefs.getBoolean("dbExists", false);
Log.d("PM.ADA.SDA", "DB Exists : " + dbExists);
if (!dbExists) {
this.getReadableDatabase();
copyDB();
prefs.edit().putBoolean("dbExists", true).commit();
}
}
#Override
public void onCreate(SQLiteDatabase db) {}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
public void copyDB() {
try {
InputStream is = c.getAssets().open(DB_NAME);
BufferedInputStream bis = new BufferedInputStream(is);
OutputStream os = new FileOutputStream(DB_PATH);
BufferedOutputStream bos = new BufferedOutputStream(os);
byte[] buffer = new byte[64];
int length;
while ((length = bis.read(buffer)) > 0) {
bos.write(buffer, 0, length);
}
bos.flush();
bos.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I use an inner class for my DB Helper that extends the SQLiteOpenHelper. the methods onCreate() and onUpgrade() are here required.
I use a SharedPreferences file to safe a boolean value to check, if the database exists in /data/data/
Hope this will help you!
Have nice coding!