I have a service which will update the Sqllite database with data at each 10 minute with the help of service.I have Opened a database connetion and closed the connection when data got updated.
In my application I have differnt pages where database updation took place.I have also Opened a database connetion and closed the connection each and every pages for data updation.
The Problem is that While the service is running I am not Able to Update the data to sqlite throught my application when conncetion opened in the service.
Is there any way to run data base updation simuntanously using service and application.
Will any one help with samples.
I am calling a function in my sevice as given below (code)
public class service_helper extends Service {
public static final String TAG = "Service";
private NotificationManager mNM;
private DatabaseAdapter dbAdapter;
private service_updator serviceUpdator;
private int NOTIFICATION = 1;
private Timer timer = new Timer();
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
serviceUpdator = new service_updator(this);
dbAdapter = new DatabaseAdapter(this);
dbAdapter.open();
Toast.makeText(this, "Service created ...", Toast.LENGTH_LONG).show();
startService() ;
}
#Override
public void onStart(Intent intent, int startid) {
}
#Override
public void onDestroy() {
timer.cancel();
super.onDestroy();
Toast.makeText(this, "Service destroyed ...", Toast.LENGTH_LONG).show();
}
private void startService()
{
timer.scheduleAtFixedRate(new mainTask(), 0, 250000);
}
private class mainTask extends TimerTask
{
public void run()
{
try {
serviceUpdator.UploadData();
Log.d(TAG, "Service");
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private Runnable threadBody = new Runnable() {
public void run() {
try {
serviceUpdator.UploadData();
Log.d(TAG, "Service");
} catch (ParserConfigurationException e) {
}
}
};
}
UploadData() Function Code
dbAdapter = new DatabaseAdapter(this.context);
dbAdapter.open();
Long transactionType = null;
String transactionData = null;
String sql = "Select * from tblTransaction where PKTransaction >?";
Cursor cursorTransaction = dbAdapter.ExecuteRawQuery(sql, "-1");
cursorTransaction.moveToFirst();
dbAdapter.close();
for (int i = 0; i < cursorTransaction.getCount(); i++) {
}
dbAdapter.close();
Application Code
private void SaveSortOrder() throws Exception {
try {
String server1IPAddress = "";
String server2IPAddress = "";
String deviceId = "";
Cursor cursorTransaction;
Cursor cursorAdmin;
DatabaseAdapter dbAdapter;
DataXmlExporter dataXmlExporter;
admin_helper adminhelper;
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
String RevisedEstimatedDate = sdf.format(date);
adminhelper = new admin_helper(this);
cursorAdmin = adminhelper.GetAdminDetails();
if (cursorAdmin.moveToFirst())
server1IPAddress = cursorAdmin.getString(cursorAdmin
.getColumnIndex("RemoteServer1IPAddress"));
server2IPAddress = cursorAdmin.getString(cursorAdmin
.getColumnIndex("RemoteServer2IPAddress"));
deviceId = cursorAdmin.getString(cursorAdmin
.getColumnIndex("DeviceID"));
cursorAdmin.close();
ContentValues initialSortOrder = new ContentValues();
ContentValues initialTransaction = new ContentValues();
for (int i = 0; i < ListSortOrder.getAdapter().getCount(); i++) {
HashMap result = (HashMap) ListSortOrder.getItemAtPosition(i);
View vListSortOrder;
vListSortOrder = ListSortOrder.getChildAt(i);
TextView Sort_DeliveryOrder = (TextView) vListSortOrder
.findViewById(R.id.et_Sort_Order);
initialSortOrder.put("DeliveryOrder", Sort_DeliveryOrder
.getText().toString());
dbAdapter = new DatabaseAdapter(this);
dbAdapter.open();
dbAdapter.BeginTransaction();
dbAdapter.UpdateRecord("tblDelivery", initialSortOrder,
"PKDelivery" + "="
+ result.get("Sort_PKDelivery").toString(),
null);
dataXmlExporter = new DataXmlExporter(this);
dataXmlExporter.StartDataSet();
String sqlTransaction = "Select 5 as TransactionType,'Update Delivery Order' as Description,'"
+ result.get("Sort_PKDelivery").toString()
+ "' as FKDelivery, "
+ " deviceId as DeviceID ,'"
+ Sort_DeliveryOrder.getText().toString()
+ "' as DeliveryOrder ,date() as TransactionUploadDate,time() as TransactionUploadTime from tblAdmin where PKAdmin > ?";
cursorTransaction = dbAdapter.ExecuteRawQuery(sqlTransaction,
"-1");
dataXmlExporter.AddRowandColumns(cursorTransaction,
"Transaction");
String XMLTransactionData = dataXmlExporter.EndDataSet();
try {
if ((server1IPAddress != "") && (server2IPAddress != "")) {
try {
if (server1IPAddress != "") {
InsertUploadedTrancasctionDetails(
server1IPAddress, deviceId,
XMLTransactionData);
}
} catch (Exception exception) {
if ((server1IPAddress != server2IPAddress)
&& (server2IPAddress != "")) {
InsertUploadedTrancasctionDetails(
server2IPAddress, deviceId,
XMLTransactionData);
}
}
}
} catch (Exception exception) {
initialTransaction
.put("ReceivedDate", RevisedEstimatedDate);
initialTransaction.put("TransactionData",
XMLTransactionData);
dbAdapter.InsertRecord("tblTransaction", "",
initialTransaction);
}
dbAdapter.SetSucessfulTransaction();
dbAdapter.EndTransaction();
dbAdapter.close();
}
} catch (Exception exception) {
throw exception;
}
}
I had a similar problem when moving to Honeycomb it started throwing SQLiteDatabaseLockedException I sorted it by putting a content provider over my database and then Android handles all the threading issues. You can try find the threading problem if you want of course but that would definitely fix it :)
Related
i have created an Application for Nougat device where my application is detecting all the images taking by camera and i am sending this images in the server. My application is successfully sending the first photo taken by the camera but the receiver neither detecting the second image i am taking nor sending it to the server. I have a ConfigurationBuilder class which will trigger each and every 30 minutes to detect the new pictures by the camera and a cameraReceiver and a service class where i have registered the receiver.
ConfigurationBuilder.java
public class ConfigurationBuilder extends JobService {
JobParameters mRunningParams;
static final int PROJECTION_ID = 0;
static final int PROJECTION_DATA = 1;
static final String DCIM_DIR = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM).getPath();
static final String[] PROJECTION = new String[] {
MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA
};
static final List<String> EXTERNAL_PATH_SEGMENTS
= MediaStore.Images.Media.EXTERNAL_CONTENT_URI.getPathSegments();
String TAG = "JobService";
private Context mContext;
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public boolean onStartJob(JobParameters jobParameters) {
mContext = getApplicationContext();
getSettingResponse(true);
jobFinished(jobParameters, false);
Log.d(TAG, "onStartJob: ");
return true;
}
private void getSettingResponse(boolean fromJobScheduler) {
try {
if (fromJobScheduler)
new DataClear();
OkHttpClient client = new SSLManager().getClientKeyNonDeprecated(mContext);
// code request code here
HttpUrl.Builder urlBuilder =
HttpUrl.parse(mContext.getSharedPreferences(NetworkAPI.PREFNAME,Context.MODE_PRIVATE ).getString("configuration_url", "")).newBuilder();
//urlBuilder.addQueryParameter("device", CommonMethods.getBluetoothName());
urlBuilder.addQueryParameter("device", "FranksS7");
urlBuilder.addQueryParameter("membership", "Phone Network");
urlBuilder.addQueryParameter("membershipType", "Domain");
Request request = new Request.Builder().addHeader("Accept", "application/json")
.url(urlBuilder.build()).get()
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
getConfigure(null);
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (!response.isSuccessful()) {
Log.d(TAG, "onResponse:Unexpected code" + response.body().string());
} else {
getConfigure(response.body().string());
}
}
});
} catch (Exception e) {
Log.d(TAG, "getSettingResponse: " + e.getMessage());
}
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
return false;
}
private void getConfigure(String response) {
try {
if (response != null) {
JSONArray policies = new JSONObject(response).getJSONArray("Policies");
for (int i = 0; i < policies.length(); i++) {
JSONObject obj = policies.getJSONObject(i);
Iterator iterator = obj.keys();
String key = (String) iterator.next();
JSONObject issue = obj.getJSONObject(key);
String value = issue.optString("Value");
RecorderPolicies policiesField = new Select()
.from(RecorderPolicies.class)
.where("Policy = ?", key).executeSingle();
if (policiesField != null) {
policiesField.Value = value;
long res = policiesField.save();
// new Update(RecorderPolicies.class).set("Value = ?",value).where("Policy = ?", key).execute();
} else {
RecorderPolicies recorderPolicies = new RecorderPolicies();
recorderPolicies.Policy = key;
recorderPolicies.Value = value;
long res = recorderPolicies.save();
}
}
}
if (isMyServiceRunning(ApplicationService.class)) {
// stopService(new Intent(mContext, ApplicationService.class));
Log.d(TAG, "Service Terminated");
}
if (new RecorderPolicies().getActivateCode("CanRecordDetailedData"))
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
mContext.startService(new Intent(mContext, ApplicationService.class));
Log.d(TAG, "Service Restarted");
}
}, 10000);
else
Log.d(TAG, "----------------------problem starting service---------------------");
} catch (Exception e) {
Log.d(TAG, "getConfigure: " + e.getMessage());
}
}
#RequiresApi(api = Build.VERSION_CODES.N)
public void startConfigurationScheduler(int JobID, Context activityContext) {
mContext = activityContext;
ComponentName jobService =
new ComponentName(activityContext, ConfigurationBuilder.class.getName());
JobInfo jobInfo =
new JobInfo.Builder(JobID, jobService)
.setPersisted(true).setRequiresDeviceIdle(true)
//updated code for nougat...............................................................on 12/11/2017
//.setPeriodic(32*60000, (long) (1.6*60000)).build();
.setPeriodic(32 * 60000).build();
JobScheduler jobScheduler = (JobScheduler) activityContext.getSystemService(JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);
getSettingResponse(false);
}
public void stopConfigurationScheduler(int JobID, Context activityContext) {
JobScheduler jobScheduler = (JobScheduler) activityContext.getSystemService(JOB_SCHEDULER_SERVICE);
jobScheduler.cancel(JobID);
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Process.killProcess(service.pid); // kill service
return true;
}
}
return false;
}
}
CameraReceiver .java
public class CameraReceiver extends BroadcastReceiver {
private String pathSplit;
private String type;
Context mContext;
#Override
public void onReceive(Context context, Intent intent) {
mContext=context;
Cursor cursor = context.getContentResolver().query(intent.getData(),
null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
String image_path = cursor.getString(cursor.getColumnIndex("_data"));
String MediaType = intent.getAction().equals("android.hardware.action.NEW_VIDEO") ? "VIDEO" : "IMAGE";
FilesObservers.postDataCreateEvent("CREATE", image_path, true,MediaType);
cursor.close();
}
}
public IntentFilter getVideoFilters() {
IntentFilter lsIntentFilter = new IntentFilter();
try {
lsIntentFilter.addDataType("video/*");
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
}
lsIntentFilter.addAction("android.hardware.action.NEW_VIDEO");
lsIntentFilter.addCategory("android.intent.category.DEFAULT");
return lsIntentFilter;
}
public IntentFilter getCameraFilters() {
IntentFilter lsIntentFilter = new IntentFilter();
try {
lsIntentFilter.addDataType("image/*");
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
} //lsIntentFilter.addAction("JobInfo.Builder.addTriggerContentUri(JobInfo.TriggerContentUri)");
lsIntentFilter.addAction("android.provider.MediaStore.ACTION_IMAGE_CAPTURE)");
lsIntentFilter.addCategory("android.intent.category.DEFAULT");
return lsIntentFilter;
}
}
In Nougat ACTION_NEW_VIDEO and ACTION_NEW_PICTURE broadcasts were removed.
Instead this they recommend to use JobInfo.Builder.JobInfo.Builder.addTriggerContentUri(JobInfo.TriggerContentUri)
It is funny because In Android O this broadcast has been brought back - for registered receivers only.
i'm developing my first Android app and i created a class (not Activity) that downloads a JSON file and writes content to SQLite database at every start-up of the application.
I then use an instance of this class in the main activity class.
If the download takes few seconds the home page of my app hangs on a blank screen.
Do you think i should use service instead of a class to handle download and writing of the db?
Could it be a good idea? If it could, what are the advantages?
If you are writing to a database I would recommend using an IntentService
The intent service runs in it's own thread.
When the download is complete you can use LocalBroadcastManager to notify the activity.
It could also work with ContentProvider and Loaders.
I also wanted to download the list of images in background so I used Services with SharedPreferences and I also Used AQuery With the Service.Here the ConnectionDetector is my Java class which checks the Internet Connection is available or not. It works for me. I hope it will give u some help.
public class MyService extends Service {
String f;
String path;
File file;
Bitmap bm;
String url1;
ArrayList<String> url_img;
AQuery aq;
int count = 1;
String val;
ArrayList<String> completed_url_list;
ArrayList<Integer> _index;
FileOutputStream out;
static ArrayList<String> list;
private Thread updateTask = new Thread(new Runnable() {
#Override
public void run() {
while (count < url_img.size()) {
try {
Log.e("Counter", "" + count);
val = url_img.get(count).toString();
final AjaxCallback<Bitmap> cb = new AjaxCallback<Bitmap>() {
#Override
public void callback(String url, Bitmap bm,
AjaxStatus status) {
try {
System.out.println("url is" + url);
String urll = url.substring(url
.lastIndexOf("/") + 1);
Log.e("Image name", "" + urll);
System.out.println("url111" + urll);
File f = new File(path + urll);
f.createNewFile();
System.out.println(f.getAbsolutePath());
try {
out = new FileOutputStream(f);
bm.compress(Bitmap.CompressFormat.JPEG, 40,
out);
if (out != null) {
out.flush();
out.close();
Log.e("download", "Complete");
completed_url_list.add(url);
System.out
.println("Completed Dowmload Image"
+ completed_url_list);
}
} catch (Exception e) {
boolean del_file = f.delete();
if (del_file == true){
Log.e("File", "deleted");
System.out.println("exception");
}
else{
System.out.println("file not deleted");
}
} finally {
out.close();
if (bm != null) {
bm.recycle();
bm = null;
}
System.gc();
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
} catch (Exception e) {
}
}
};
final AQuery aq = new AQuery(getApplicationContext());
aq.ajax(val, Bitmap.class, 0, cb);
} catch (Exception e) {
}
count++;
}
}
});
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
url_img = getArrayList();
completed_url_list = new ArrayList<String>();
_index = new ArrayList<Integer>();
aq = new AQuery(MyService.this);
System.out.println("I am in super");
if (url_img.size() > 0) {
updateTask.start();
}
} catch (Exception e) {
e.printStackTrace();
}
return START_STICKY;
}
#Override
public void onCreate() {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
super.onCreate();
try {
System.out.println("Service Creating");
f = Environment.getExternalStorageDirectory().getAbsolutePath();
path = f + "/HRI3mages/";
file = new File(path);
if (!file.exists()) {
file.mkdir();
}
} catch (Exception e) {
}
}
#Override
public void onDestroy() {
try {
for (int index = 0; index < completed_url_list.size(); index++) {
for (int index1 = 0; index1 < url_img.size(); index1++) {
if (completed_url_list.get(index).equals(
url_img.get(index1))) {
_index.add(index1);
}
}
}
Collections.sort(_index, new MyIntComparable());
System.out.println("next_download" + _index);
for(int index=0;index<_index.size();index++){
url_img.remove(index);
}
System.out.println("After_Deletion_of_Image"+url_img);
_addArray(url_img);
updateTask.interrupt();
} catch (Exception e) {
}
System.out.println("Service destroy");
super.onDestroy();
}
public class MyIntComparable implements Comparator<Integer>{
#Override
public int compare(Integer o1, Integer o2) {
return (o1>o2 ? -1 : (o1==o2 ? 0 : 1));
}
}
public ArrayList<String> getArrayList() {
ArrayList<String> list_url = new ArrayList<String>();
SharedPreferences SharedPref = getSharedPreferences("SSO", MODE_PRIVATE);
int size = SharedPref.getInt("list_size", 0);
for (int i = 0; i < size; i++) {
list_url.add(SharedPref.getString("list_" + i, ""));
}
System.out.println(list_url);
return list_url;
}
public void _addArray(ArrayList<String> list) {
SharedPreferences SharedPref = getSharedPreferences("SSO", 0);
SharedPreferences.Editor editor = SharedPref.edit();
int size = list.size();
editor.putInt("list_size", size);
for (int i = 0; i < size; i++) {
editor.putString("list_" + i, list.get(i));
}
editor.commit();
}
}
You might want to use an AsyncTask.
This will do the work in a background thread, so if it takes long your screen won't hang.
While the work is in progress, you can show a ProgressDialog (optional) to inform the user. You can also add a button to that ProgressDialog to cancel the task if needed.
See this: http://developer.android.com/intl/es/reference/android/os/AsyncTask.html
In this case I prefer an AsyncTask and not a Service so it seems easier and simpler to do what you want.
Good luck =)
I have trouble using thread.join in my code below. It should wait for the thread to finish before executing the codes after it, right? It was behaving differently on different occasions.
I have three cases to check if my code goes well
App is used for the first time - works as expected but the loading page don't appear while downloading
App is used the second time (db is up to date) - works okay
App is used the third time (db is outdated, must update) - won't update, screen blacks out, then crashes
I think I have problems with this code on onCreate method:
dropOldSchedule();
dropThread.join();
triggerDownload();
Based on the logs, the code works until before this part... What can be the problem?
MainActivity.java
public class MainActivity extends Activity {
final static int INDEX_ACCTTYPE = 0;
final static int INDEX_ECN = 1;
final static int INDEX_TLN = 2;
final static int INDEX_SIN = 3;
final static int INDEX_MOBILE = 4;
final static int INDEX_CITY = 5;
final static int INDEX_START_DATE = 6;
final static int INDEX_START_TIME = 7;
final static int INDEX_END_DATE = 8;
final static int INDEX_END_TIME = 9;
final static int INDEX_REASON = 10;
final static int INDEX_DETAILS = 11;
DatabaseHandler db;
String str;
ProgressDialog pd;
TextView homeText1, homeText2, homeText3, homeText4;
final private String csvFile = "http://www.meralco.com.ph/pdf/pms/pms_test.csv";
final private String uploadDateFile = "http://www.meralco.com.ph/pdf/pms/UploadDate_test.txt";
Thread dropThread = new Thread(new Runnable() {
public void run() {
db = new DatabaseHandler(MainActivity.this);
db.dropOldSchedule();
runOnUiThread(new Runnable() {
public void run() {
while (!pd.isShowing());
db.close();
pd.dismiss();
}
});
}
});
Thread getUploadDateThread = new Thread(new Runnable() {
public void run() {
try {
URL myURL = new URL(uploadDateFile);
BufferedReader so = new BufferedReader(new InputStreamReader(myURL.openStream()));
while (true) {
String output = so.readLine();
if (output != null) {
str = output;
}
else {
break;
}
}
so.close();
}
catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
while (!pd.isShowing());
pd.dismiss();
}
});
}
});
Thread downloadThread = new Thread(new Runnable() {
public void run() {
db = new DatabaseHandler(MainActivity.this);
db.beginTransaction();
try {
URL url = new URL(csvFile);
Log.i("dl", "start");
InputStream input = url.openStream();
CSVReader reader = new CSVReader(new InputStreamReader(input));
Log.i("dl", "after reading");
String [] sched;
while ((sched = reader.readNext()) != null) {
if(sched[INDEX_CITY].equals("")) sched[INDEX_CITY]="OTHERS";
try {
db.addRow(sched[INDEX_SIN], sched[INDEX_CITY],
sched[INDEX_START_DATE], sched[INDEX_START_TIME],
sched[INDEX_END_DATE], sched[INDEX_END_TIME],
sched[INDEX_DETAILS], sched[INDEX_REASON]);
} catch (IndexOutOfBoundsException e) {
db.addRow(sched[INDEX_SIN], sched[INDEX_CITY],
sched[INDEX_START_DATE], sched[INDEX_START_TIME],
sched[INDEX_END_DATE], sched[INDEX_END_TIME],
"", sched[INDEX_REASON]);
//e.printStackTrace();
}
}
input.close();
Log.i("dl", "finished");
} catch (MalformedURLException e) {
e.printStackTrace();
db.endTransaction();
} catch (IOException e) {
e.printStackTrace();
db.endTransaction();
}
Log.d("Count", ""+db.count());
db.setTransactionSuccessful();
db.endTransaction();
writeUploadDateInTextFile();
}
});
#SuppressWarnings("unqualified-field-access")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pms_main);
Button home = (Button) findViewById(R.id.home);
home.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MeralcoSuite_TabletActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
homeText1 = (TextView) findViewById(R.id.home_text1);
homeText2 = (TextView) findViewById(R.id.home_text2);
homeText3 = (TextView) findViewById(R.id.home_text3);
homeText4 = (TextView) findViewById(R.id.home_text4);
homeText1.setVisibility(View.INVISIBLE);
homeText2.setVisibility(View.INVISIBLE);
homeText3.setVisibility(View.INVISIBLE);
homeText4.setVisibility(View.INVISIBLE);
getUploadDate();
try {
getUploadDateThread.join(); //wait for upload date
Log.d("getUploadDate","thread died, upload date=" + str);
if(dbExists()){
db = new DatabaseHandler(MainActivity.this);
Log.d("Count", "" + db.count());
db.close();
if(!uploadDateEqualsDateInFile()){
dropOldSchedule();
dropThread.join();
triggerDownload();
}
showDisclaimer();
Log.i("oncreate", "finished!");
return;
}
triggerDownload();
showDisclaimer();
Log.i("oncreate", "finished!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void dropOldSchedule(){
if(pd!=null && pd.isShowing())
pd.setTitle("Getting upload date...");
else
pd = ProgressDialog.show(this, "Getting upload date",
"This may take a few minutes...", true, false);
dropThread.start();
}
public void triggerDownload() {
if (!checkInternet()) {
showAlert("An internet connection is required to perform an update, please check that you are connected to the internet");
return;
}
if(pd!=null && pd.isShowing())
pd.setTitle("Getting upload date...");
else
pd = ProgressDialog.show(this, "Getting upload date",
"This may take a few minutes...", true, false);
downloadThread.start();
}
public void getUploadDate() {
Log.d("getUploadDate", "getting upload date of schedule");
if(pd!=null && pd.isShowing())
pd.setTitle("Getting upload date...");
else
pd = ProgressDialog.show(this, "Getting upload date",
"This may take a few minutes...", true, false);
getUploadDateThread.start();
}
public void writeUploadDateInTextFile() {
Log.d("writeUploadDateTextFile", "writing:"+str);
try {
OutputStreamWriter out = new OutputStreamWriter(openFileOutput(
"update.txt", 0));
out.write(str);
out.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
public void showDisclaimer() {
Log.d("ShowDisclaimer", "showing disclaimer");
homeText3
.setText("..." + str
+ "...");
homeText1.setVisibility(View.VISIBLE);
homeText2.setVisibility(View.VISIBLE);
homeText3.setVisibility(View.VISIBLE);
homeText4.setVisibility(View.VISIBLE);
Log.d("showDisclaimer", "finished showing disclaimer");
}
public boolean uploadDateEqualsDateInFile() {
Log.d("uploadDateEqualsDateInFile","comparing schedule upload dates");
try {
String recordedDate = "";
InputStream instream = openFileInput("update.txt");
if (instream != null) { // if file the available for reading
Log.d("uploadDateEqualsDateInFile","update.txt found!");
InputStreamReader inputreader = new InputStreamReader(instream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line = null;
while ((line = buffreader.readLine()) != null) {
recordedDate = line;
Log.d("uploadDateEqualsDateInFile","recorded:"+recordedDate);
}
Log.d("uploadDateEqualsDateInFile","last upload date: " + str + ", recorded:" +recordedDate);
if(str.equals(recordedDate)) return true;
return false;
}
Log.d("uploadDateEqualsDateInFile","update.txt is null!");
return false;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public boolean checkInternet() {
ConnectivityManager cm = (ConnectivityManager) this
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo infos[] = cm.getAllNetworkInfo();
for (NetworkInfo info : infos)
if (info.getState() == NetworkInfo.State.CONNECTED
|| info.getState() == NetworkInfo.State.CONNECTING) {
return true;
}
return false;
}
public boolean dbExists() {
File database=getApplicationContext().getDatabasePath(DatabaseHandler.DATABASE_NAME);
if (!database.exists()) {
Log.i("Database", "Not Found");
return false;
}
Log.i("Database", "Found");
return true;
}
#Override
protected void onDestroy() {
super.onDestroy();
if (db != null) {
db.close();
}
}
#Override
protected void onPause() {
super.onPause();
if (db != null) {
db.close();
}
}
}
Sorry but I couldn't find mistakes or problems in your code. But I would strongly recommend you to use AsyncTask for doing something in different thread. AsyncTask is very easy to use and I would say that it is one of the biggest advantages of java. I really miss it in obj-c.
http://labs.makemachine.net/2010/05/android-asynctask-example/
http://marakana.com/s/video_tutorial_android_application_development_asynctask_preferences_and_options_menu,257/index.html
check those links hope that will help you.
It was already mentioned that AsyncTask is the better alternative. However, it may be the case, that your call to join will throw InterruptedException. Try to use it like this:
while(getUploadDateThread.isRunning()){
try{
getUploadDateThread.join();
} catch (InterruptedException ie){}
}
// code after join
I think the problem that your facing is that you are blocking the UI thread when you call join in the onCreate() method. You should move this code into another thread which should execute in the background and once its done you can update the UI.
Here is a sample code:
final Thread t1 = new Thread();
final Thread t2 = new Thread();
t1.start();
t2.start();
new Thread(new Runnable() {
#Override
public void run() {
// Perform all your thread joins here.
try {
t1.join();
t2.join();
} catch (Exception e) {
// TODO: handle exception
}
// This thread wont move forward unless all your threads
// mentioned above are executed or timed out.
// ------ Update UI using this method
runOnUiThread(new Runnable() {
#Override
public void run() {
// Update UI code goes here
}
});
}
}).start();
Using Sqlite db, I am populating my list. That List is refreshed every minute(using Timer). Also I am updating/inserting Sqlite db(using Service), checking for new data.
This is also happening every minute. This is working but sometimes "Database is getting locked". How can I manage this and not get that error. Appreciate your input.
public class Services extends Service {
Context context;
int NOTIFICATION_ID = 1;
NotificationManager notificationManager, chatNotificationManager;
boolean connected = false;
boolean notconnected = false;
int numChat = 0;
int numTask = 0;
List<String> list = new ArrayList();
String android_id, syncDecision;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
android_id = Secure.getString(this.getContentResolver(), Secure.ANDROID_ID);
context = getBaseContext();
/*
* THIS TIMER CONTAINS ANY SERVICE THAT ACCESSES THE SQLite database
*/
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Log.d(TAG, "starting to do work in timer1");
synchronizeSQLiteDatabases();
}
}, 0, 60000);
private void synchronizeSQLiteDatabases() {
try {
if (Functions.isOnline(context) )
{
// ---------------------------------- COMMENT UPLOAD ----------------------------
if (!((GlobalMobileVianet) this.getApplication()).getUserid().equals("000000")) {
try
{
Log.i(TAG, "uploading comment data");
DataUploader_Comment commentupdater = new DataUploader_Comment(((GlobalMobileVianet) this.getApplication()).getUserid(),
((GlobalMobileVianet) this.getApplication()).getPassword(), context);
commentupdater.run();
}
catch(Exception e)
{
Log.i(TAG, " CATCH uploading comment data" + e.toString());
}
}
else
{
//Functions.logout(getApplicationContext());
Log.i(TAG, " NOT uploading comment data");
}
//--------------------------------------- TASK UPLOAD --------------------------------
if ( !((GlobalMobileVianet) this.getApplication()).getUserid().equals("000000")) {
try{
Log.i(TAG, "uploading task data");
DataUploader_Task taskuploader = new DataUploader_Task(((GlobalMobileVianet) this.getApplication()).getUserid(),
((GlobalMobileVianet) this.getApplication()).getPassword(), context);
taskuploader.run();
}
catch(Exception e)
{
Log.i(TAG, " CATCH uploading task data" + e);
}
}
else
{
//Functions.logout(getApplicationContext());
Log.i(TAG, " NOT uploading task data");
}
// ------------------------------------------AC DOWNLOAD ---------------------------------
if (!((GlobalMobileVianet) this.getApplication()).getUserid().equals("000000")) {
try{
Log.i(TAG, "running aircraft data download");
DataLoader_Aircraft acloader = new DataLoader_Aircraft(((GlobalMobileVianet) this.getApplication()).getUserid(),
((GlobalMobileVianet) this.getApplication()).getPassword(), context, "N");
acloader.run();
}
catch(Exception e)
{
Log.i(TAG, " CATCH running aircraft data download" + e.toString());
}
}
else
{
//Functions.logout(getApplicationContext());
Log.i(TAG, " NOT running aircraft data download");
}
// ------------------------------------ TASK DOWNLOAD ------------------------------------
if ( !((GlobalMobileVianet) this.getApplication()).getUserid().equals("000000")) {
try{
Log.i(TAG, "running task data download");
DataLoader_Task tasksloader = new DataLoader_Task(((GlobalMobileVianet) this.getApplication()).getUserid(),
((GlobalMobileVianet) this.getApplication()).getPassword(), context, "N");
tasksloader.run();
}
catch(Exception e)
{
Log.i(TAG, " CATCH running task data download" + e.toString());
}
}
else
{
//Functions.logout(getApplicationContext());
Log.i(TAG, " NOT running task data download");
}
// -------------------------------- EMPLOYEE DOWNLOAD -----------------------------------
if (!((GlobalMobileVianet) this.getApplication()).getUserid().equals("000000")) {
try
{
Log.i(TAG, "running employee data download");
DataLoader_Employee employeeloader = new DataLoader_Employee(((GlobalMobileVianet) this.getApplication()).getUserid(),
((GlobalMobileVianet) this.getApplication()).getPassword(), context, "N");
employeeloader.run();
}
catch(Exception e)
{
Log.i(TAG, " CATCH running employee data download " + e.toString());
}
}
else
{
//Functions.logout(getApplicationContext());
Log.i(TAG, " NOT running employee data download");
}
// ------------------------------------COMMENT DOWNLOAD -----------------------------------------
if (!((GlobalMobileVianet) this.getApplication()).getUserid().equals("000000")) {
try{
Log.i(TAG, "running comment data update");
DataLoader_Comment commentloader = new DataLoader_Comment(((GlobalMobileVianet) this.getApplication()).getUserid(),
((GlobalMobileVianet) this.getApplication()).getPassword(), context, "N");
commentloader.run();
}
catch(Exception e)
{
Log.i(TAG, " CATCH running comment data update" + e.toString());
}
}
else
{
//Functions.logout(getApplicationContext());
Log.i(TAG, " NOT running comment data download");
}
}
} catch (Exception e) {
Log.e(TAG,
"synchronizeSQLiteDatabases exception: " + e.toString());
}
}
and this is activity which refreshes the list
public class TestExList extends ExpandableListActivity{
String empid, ctext, fleet_name, rString;
private DbAdapter_Assignment assignment;
private DbAdapter_Task task;
private DbAdapter_Comment comment;
private DbAdapter_Aircraft aircraft;
private Cursor accursor, taskcursor;
private ExpandableListView expListView;
private Timer taskTimer;
private ListView lv;
private Camera cam;
private boolean onoff;
private boolean testValue;
private SimpleCursorTreeAdapter cursorTreeAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
empid = getIntent().getExtras().getString("EmpID");
Log.d("testValue","from onCreate, onoff is " + onoff);
setHeader();
if(empid.equals(Functions.getLoginEmpID(this))){
getData(empid);
}
taskTimer = new Timer();
taskTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, 60000);
expListView.invalidateViews();
}
private void TimerMethod()
{
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
if(Functions.getServiceStatus(getBaseContext()) != "No service")
{
if(empid.equals(Functions.getLoginEmpID(getBaseContext())))
{
getData(empid);
}
}
}
};
#Override
public void onDestroy()
{
super.onDestroy();
try
{
accursor.close();
taskcursor.close();
task.close();
comment.close();
aircraft.close();
assignment.close();
}
catch(Exception e)
{
Log.e("ViaNetError", "Unable to close cursors.");
}
if(cam != null)
{
cam.release();
cam = null;
}
}
public void getData(final String empid)
{
Log.e("Testing", "Getting data for emp: " + empid);
assignment = new DbAdapter_Assignment(getBaseContext());
assignment.open();
task = new DbAdapter_Task (getBaseContext());
task.open();
comment = new DbAdapter_Comment (getBaseContext());
comment.open();
}
}
I fought with this exact same problem for ages, randomly with using my app an opening of the db would get a "db is locked" with no rime or reason. After struggling for several months this was my solution.
1) Create you dbopenhelper in class with all of its methods like normal.
2) Create an instance of that class in your APPLICATION class.
3) Open the DB in the onCreate of the Application class, and never close it ever.
4) Run all queries through the Application class owned copy of the dbhelper.
I was worried about never closing the DB, but my research showed many instances of Android developers (IE Googles folks) suggesting just that.
Hope it works as well for you as it has for me.
SQLite is telling you the database is already opened in an other thread. You have to use SQLite in a thread-safe way.
Could you add your code in your question where you open your database and the timer ?
I'm making an app that sends a notification to the status bar, it sends the notification when stepping through the code in the debugger, however it never sends the notification when run in realtime.
Here is my runnable that generates the notification, again when stepping through this code in the debugger the notification runs however in realtime nothing happens.
public class NewsEvents_Service extends Service {
private static final String NEWSEVENTS = "newsevents";
private static final String KEYWORDS = "keywords";
private NotificationManager mNM;
private ArrayList<NewsEvent> neList;
private int count;
#Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
neList = new ArrayList<NewsEvent>();
getKeywords();
//getNewsEvents();
Thread thr = new Thread(null, mTask, "NewsEvents_Service");
thr.start();
Log.d("Thread", "IT STARTED!!!!!!????!!!!!!!!!!!!!!!?!!?");
}
#Override
public void onDestroy() {
// Cancel the notification -- we use the same ID that we had used to start it
mNM.cancel(R.string.ECS);
// Tell the user we stopped.
Toast.makeText(this, "Service Done", Toast.LENGTH_SHORT).show();
}
/**
* The function that runs in our worker thread
*/
Runnable mTask = new Runnable() {
public void run() {
getNewsEventsFromWeb();
for(NewsEvent ne : neList){
Log.d("Thread Running", "Service Code running!!!!!!!!!!!!!!!");
String body = ne.getBody().replaceAll("\\<.*?>", "");
String title = ne.getTitle();
for(String s : keyWordList){
if(body.contains(s) || body.contains(s.toLowerCase()) ||
title.contains(s) || title.contains(s.toLowerCase())){
ne.setInterested(true);
}
}
if(ne.isInterested() == true ){
Notification note = new Notification(R.drawable.icon,
"New ECS News Event", System.currentTimeMillis());
Intent i = new Intent(NewsEvents_Service.this, FullNewsEvent.class);
i.putExtra("ne", ne);
PendingIntent pi = PendingIntent.getActivity(NewsEvents_Service.this, 0,
i, 0);
note.setLatestEventInfo(NewsEvents_Service.this, "New Event", ne.getTitle(), pi);
note.flags = Notification.FLAG_AUTO_CANCEL;
mNM.notify(R.string.ECS, note);
}
}
}
};
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Show a notification while this service is running.
*/
private void getNewsEventsFromWeb() {
HttpClient client = new DefaultHttpClient();
HttpGet get;
try {
get = new HttpGet(getString(R.string.jsonnewsevents));
ResponseHandler<String> response = new BasicResponseHandler();
String responseBody = client.execute(get, response);
String page = responseBody;
Bundle data = new Bundle();
data.putString("page",page);
Message msg = new Message();
msg.setData(data);
handler.sendMessage(msg);
}
catch (Throwable t) {
Log.d("UpdateNews", "PROBLEMS");
}
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
String page = msg.getData().getString("page");
try {
JSONArray parseArray = new JSONArray(page);
for (int i = 0; i < parseArray.length(); i++) {
JSONObject jo = parseArray.getJSONObject(i);
String title = jo.getString("title");
String body =jo.getString("body");
String pd = jo.getString("postDate");
String id = jo.getString("id");
NewsEvent ne = new NewsEvent(title, pd , body, id);
boolean unique = true;
for(NewsEvent ne0 : neList){
if(ne.getId().equals(ne0.getId())){
unique = false;
}else{
unique = true;
}
}
if(unique == true){
neList.add(ne);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
private ArrayList<String> keyWordList;
public void getNewsEvents(){
try {
InputStream fi = openFileInput(NEWSEVENTS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
neList = (ArrayList<NewsEvent>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(neList == null){
neList = new ArrayList<NewsEvent>();
}
}
public ArrayList<String> getKeywords(){
try {
InputStream fi = openFileInput(KEYWORDS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
keyWordList = (ArrayList<String>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(keyWordList == null){
keyWordList = new ArrayList<String>();
return keyWordList;
}
return keyWordList;
}
/**
* This is the object that receives interactions from clients. See RemoteService
* for a more complete example.
*/
private final IBinder mBinder = new Binder() {
#Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
return super.onTransact(code, data, reply, flags);
}
};
}
Here is my activity that schedules the service to run
public class NewsEvents extends ListActivity{
private URL JSONNewsEvents;
private ArrayList<NewsEvent> neList;
private ArrayList<String> keyWordList;
private Worker worker;
private NewsEvents ne;
public static final String KEYWORDS = "keywords";
private static final String NEWSEVENTS = "newsevents";
public static final int ONE_ID = Menu.FIRST+1;
private PendingIntent newsAlarm;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.newsevents);
ne = this;
neList = new ArrayList<NewsEvent>();
try {
JSONNewsEvents = new URL(getString(R.string.jsonnewsevents));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
worker = new Worker(handler, this);
setListAdapter(new IconicAdapter());
getKeywords();
worker.execute(JSONNewsEvents);
}
#Override
protected void onStop() {
super.onStop();
writeNewsEvents() ;
}
#Override
protected void onPause(){
super.onPause();
writeNewsEvents();
}
private void writeNewsEvents() {
try {
OutputStream fi = openFileOutput(NEWSEVENTS, 0);
if (fi!=null) {
ObjectOutputStream out = new ObjectOutputStream(fi);
out.writeObject(neList);
out.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
}
/**
* #return
*/
public ArrayList<String> getKeywords(){
try {
InputStream fi = openFileInput(KEYWORDS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
keyWordList = (ArrayList<String>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(keyWordList == null){
keyWordList = new ArrayList<String>();
return keyWordList;
}
return keyWordList;
}
public void onListItemClick(ListView parent, View v,
int position, long id) {
startFullNewsEvent(neList.get(position));
}
/**
* #param newsEvent
*/
public void startFullNewsEvent(NewsEvent ne) {
Intent intent = new Intent(this, FullNewsEvent.class);
intent.putExtra("ne", ne);
this.startActivity(intent);
finish();
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
String page = msg.getData().getString("page");
try {
JSONArray parseArray = new JSONArray(page);
for (int i = 0; i < parseArray.length(); i++) {
JSONObject jo = parseArray.getJSONObject(i);
String title = jo.getString("title");
String body =jo.getString("body");
String pd = jo.getString("postDate");
String id = jo.getString("id");
NewsEvent ne = new NewsEvent(title, pd , body, id);
boolean unique = true;
for(NewsEvent ne0 : neList){
if(ne.getId().equals(ne0.getId())){
unique = false;
}else{
unique = true;
}
}
if(unique == true){
neList.add(ne);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ne.setListAdapter(new IconicAdapter());
}
};
public class IconicAdapter extends ArrayAdapter<NewsEvent> {
IconicAdapter() {
super(NewsEvents.this, R.layout.rownews, neList);
}
public View getView(int position, View convertView,ViewGroup parent) {
LayoutInflater inflater=getLayoutInflater();
View row=inflater.inflate(R.layout.rownews, parent, false);
TextView label=(TextView)row.findViewById(R.id.label);
ImageView image= (ImageView)row.findViewById(R.id.icon);
String body = neList.get(position).getBody();
body.replaceAll("\\<.*?>", "");
String title = neList.get(position).getTitle();
for(String s : keyWordList){
if(body.contains(s) || body.contains(s.toLowerCase()) ||
title.contains(s) || title.contains(s.toLowerCase())){
neList.get(position).setInterested(true);
}
}
if(neList.get(position).isInterested() == true){
image.setImageResource(R.drawable.star);
}
label.setText(neList.get(position).getTitle());
return(row);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
populateMenu(menu);
return(super.onCreateOptionsMenu(menu));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return(applyMenuChoice(item) || super.onOptionsItemSelected(item));
}
//Creates our activity to menus
private void populateMenu(Menu menu) {
menu.add(Menu.NONE, ONE_ID, Menu.NONE, "Home");
}
private boolean applyMenuChoice(MenuItem item) {
switch (item.getItemId()) {
case ONE_ID: startHome(); return(true);
}
return(false);
}
public void startHome() {
Intent intent = new Intent(this, ECS.class);
this.startActivity(intent);
finish();
}
}
Race conditions, I'm making an HTTP Request and then handing it off to a handler, immediately following that I iterator through the array list, which at full speed is empty because the HTTP hasn't completed. In debugging it all slows down so the HTTP is complete and all works well.
Threads and Network Connections, a deadly combination.