Monitoring a folder for new files Eclipse - java

I'm making an app that can take photos. If the taken photo is added into my "Camera" folder I want a toaster message to appear.
However with my current code when I click the camera button, the toaster just comes up without waiting for the photo to be taken.
Below is the source code to take the photo:
static final int REQUEST_IMAGE_CAPTURE = 1;
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 0;
public void onClickbtnCamera(View v){
Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
Uri uriSavedImage=Uri.fromFile(
new File("/storage/emulated/0/DCIM/Camera","QR_"+timeStamp+ ".png"));
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(imageIntent, 1);
}
The toaster I want to show:
Toast toast= Toast.makeText(getApplicationContext(),
"Picture was taking", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP|Gravity.CENTER_HORIZONTAL, 100, 0);
toast.show();
Can you tell me why my code is failing to do the intended job?

Only the part of monitoring a a folder:
for (;;) {
// wait for key to be signaled
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException x) {
return;
}
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
// This key is registered only
// for ENTRY_CREATE events,
// but an OVERFLOW event can
// occur regardless if events
// are lost or discarded.
if (kind == OVERFLOW) {
continue;
}
// The filename is the
// context of the event.
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path filename = ev.context();
// Verify that the new
// file is a text file or a directory using the path filename from above.
}
// Reset the key -- this step is critical if you want to
// receive further watch events. If the key is no longer valid,
// the directory is inaccessible so exit the loop.
boolean valid = key.reset();
if (!valid) {
break;
}
}

Related

Vaadin addSucceededListener

I have an upload button in Vaadin 8 with an addSucceededListener listener on it- about which i don't know many things..and i couldn't find too much info for this type of listener.
When i click that button i want to fire up a confirmation window - which I instantiate with ConfirmButton cd = new ConfirmButton("Confirmare"); and i open the modal pop-up with cd.openInModalPopup();.
My issue here is that the pop-up -> cd.openInModalPopup(); shows up only after the "Choose a file" window is open and i must select a file.
My question is how can I show the confirmation first, and only if the uer confirms, open the "Choose a file" window.
Adding the code below:
<vaadin-upload button-caption="Incarc INDICATORI " _id="cmdIncarcRaportInd" :right></vaadin-upload>
public Upload getCmdIncarcRaportInd() {
return cmdIncarcRaportInd;
}
getCmdIncarcRaportInd().addSucceededListener(event -> {
int NR_Raport=0;
String WBL ="";
WBL = getCheBL().getValue()?"B":"I";
if(raport!=null) NR_Raport=Numeric.getValInt(raport.get("Nr. Raport"));
if (NR_Raport==0) {
Notification notif = new Notification("Atentie",
"NR Raport incorect",
Notification.Type.ERROR_MESSAGE);
notif.setDelayMsec(-1);
notif.show(Page.getCurrent());
return;
}
int NR_RaportW = NR_Raport;
if(WBL.equals("B")) {
NR_RaportW=99;
ConfirmButton cd = new ConfirmButton("Confirmare");
cd.misWinTitle = "Atentie MIS";
cd.misWinText = "Incarcati valori Base Line ? Daca exista deja, cele vechi se vor rescrie cu valorile noi. CONFIRMATI BASE LINE (DA / NU) ?";
cd.misButOK = "DA";
cd.misButCancel = "NU";
cd.setOkAction(()->{
String raspuns="ok";
if(!receiver.getFile().getName().split("_")[0].equals(proiect.get("Prj cod"))) {
Notification notif = new Notification("Atentie", "Cod Proiect Incorect",
Notification.Type.ERROR_MESSAGE);
notif.setDelayMsec(-1);
notif.show(Page.getCurrent());
return;
}
try {
raspuns = Utility.getSomeData(receiver.getFile(), proiect, 99, themeDisplay);
} catch (IOException | SQLException e) {
raspuns=e.getMessage();
}
Notification notificare = new Notification("Atentie - Incarcare Base Line Indicatori",
raspuns,
Notification.Type.ERROR_MESSAGE);
notificare.setDelayMsec(-1);
notificare.show(Page.getCurrent());
incarcGrdIndicatori(prj_cod);
receiver.uploadFinished(event);
});
cd.setCancelAction(()->{
});
cd.openInModalPopup();
} else {
String raspuns="ok";
if(!receiver.getFile().getName().split("_")[0].equals(proiect.get("Prj cod"))) {
Notification notif = new Notification("Atentie", "Cod Proiect Incorect",
Notification.Type.ERROR_MESSAGE);
notif.setDelayMsec(-1);
notif.show(Page.getCurrent());
return;
}
try {
raspuns = Utility.DoSomeStuff(receiver.getFile(), proiect, NR_RaportW, themeDisplay);
} catch (IOException | SQLException e) {
raspuns=e.getMessage();
}
Notification notificare = new Notification("Atentie - Incarcare Rap Indicatori",
raspuns,
Notification.Type.ERROR_MESSAGE);
notificare.setDelayMsec(-1);
notificare.show(Page.getCurrent());
incarcGrdIndicatori(prj_cod);
receiver.uploadFinished(event);
}
});
//);
}
Add a normal Button which the users clicks, and then show the Upload Button only when your conditions are meet?

Sending intents from a worker to an activity in a separate app

I have an app that writes to its local storage depending on user actions; said contents need to
be forwarded to another app.
My approach:
create a worker thread with a file observer pointed to local storage
start worker from the apps main activity
worker thread creates and sends intents with updated contents to separate app
I'm not sure (maybe need to open a separate question), but everything created in an activity gets destroyed when the activity is stopped, right? meaning that adding workers, file observers have the same life span as the activity they're defined in, right?
Code:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final String FILE_OBSERVER_WORK_NAME = "file_observer_work";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "Creating file observer worker");
WorkManager workManager = WorkManager.getInstance(getApplication());
WorkContinuation continuation = workManager
.beginUniqueWork(FILE_OBSERVER_WORK_NAME,
ExistingWorkPolicy.REPLACE,
OneTimeWorkRequest.from(APIWorker.class));
Log.i(TAG, "Starting worker");
continuation.enqueue();
final Button button = findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.i(TAG, "Button clicked!");
String stuffToWriteToFile = getStuff();
String cwd = getApplicationInfo().dataDir;
String stuffFilePath= cwd + File.separator + "stuff.json";
PrintWriter stuffFile= null;
try {
stuffFile = new PrintWriter(stuffFilePath, "UTF-8");
stuffFile.println(stuffToWriteToFile);
stuffFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
});
}
#Override
public void onResume(){
super.onResume();
// start worker here?
}
#Override
public void onStart() {
super.onStart();
// start worker here?
}
}
APIWorker.java:
public class APIWorker extends Worker {
public APIWorker(#NonNull Context context, #NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
private static final String TAG = APIWorker.class.getSimpleName();
#NonNull
#Override
public Result doWork() {
Context applicationContext = getApplicationContext();
Log.d(TAG, "Observing stuff file");
FileObserver fileObserver = new FileObserver(cwd) {
#Override
public void onEvent(int event, #Nullable String path) {
if(event == FileObserver.CREATE ||
event == FileObserver.MODIFY) {
String cwd = applicationContext.getApplicationInfo().dataDir;
String stuffFilePath = cwd + File.separator + "stuff.json";
String fileContents;
File observedFile = new File(stuffFilePath);
long length = observedFile.length();
if (length < 1 || length > Integer.MAX_VALUE) {
fileContents = "";
Log.w(TAG, "Empty file: " + observedFile);
} else {
try (FileReader in = new FileReader(observedFile)) {
char[] content = new char[(int)length];
int numRead = in.read(content);
if (numRead != length) {
Log.e(TAG, "Incomplete read of " + observedFile +
". Read chars " + numRead + " of " + length);
}
fileContents = new String(content, 0, numRead);
Log.d(TAG, "Sending intent ");
String packageName = "com.cam.differentapp";
Intent sendIntent = applicationContext.getPackageManager().
getLaunchIntentForPackage(packageName);
if (sendIntent == null) {
// Bring user to the market or let them choose an app?
sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.setData(Uri.parse("market://details?id=" + packageName));
}
// sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, fileContents);
sendIntent.setType("application/json");
applicationContext.startActivity(sendIntent);
Log.d(TAG, "Intent sent ");
}
catch (Exception ex) {
Log.e(TAG, "Failed to read file " + path, ex);
fileContents = "";
}
}
}
}
};
fileObserver.startWatching();
return null;
}
}
Looking at the docs:
https://developer.android.com/guide/components/activities/background-starts
there are restrictions as to when activities can be started from the background but also exceptions, namely:
The app has a visible window, such as an activity in the foreground.
meaning (I think?) that as long as the user interacts with the app (MainActivity) the background worker should run, correct? It's stopped if the activity is paused/destroyed, right?
Usually you would use a Service if you have background processing to do that doesn't need user interaction (display or user input). If your app is in the foreground then your Service can launch other activities using startActivity().
Your architecture seems very strange to me. You are using a Worker, which has a maximum 10 minute lifetime. You are starting the Worker which then creates a FileObserver to detect creation/modification of files. It then reads the file and starts another Activity. This is a very complicated and roundabout way of doing things. I have doubts that you can get this working reliably.
Your Activity is writing the data to the file system. It could just call a method (on a background thread) after it has written the file that then forwards the data to another Activity. This would be much more straightforward and has a lot less moving parts.
I don't know exactly how the lifecycle of the Activity effects the Workers. I would assume that they are not directly linked to the Activity and therefore would not stop when the Activity is paused or destroyed.
I also notice that you are writing to a file on the main (UI) thread (in your OnClickListener). This is not OK and you should do file I/O in a background thread, because file I/O can block and you don't want to block the main (UI) thread.

Cannot save a file to devices Download folder using getExternalFilesDir()

I spent hours trying to solve this problem and got nowhere!
I am trying to save magnetometer data to csv file.
I am using FastCSV library.
Initially I used getExternalStoragePublicDirectory to save the file to the Downloads directory in my phone.
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "magnetic" + value + ".csv");
But since its been depreciated I used
File file = new File(context.getExternalFilesDir(DIRECTORY_DOWNLOADS), "magnetic" + value + ".csv");
I get a toast message saying that my file is saved in the memory but I cannot find them when I look for them in my phone's Download location. Instead they are stored in my phone's Android directory.
Here's the code:
private int REQUEST_CODE = 1;
private View.OnClickListener listenerStopButton = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(recording == true)
{
recording = false;
counter = 0;
String value = fileIDEdit.getText().toString();
stateText.setText("Recording Stopped");
stateText.setTextColor(Color.parseColor("#0000FF"));
if (storagePermitted((Activity) context)){
csvWriter = new CsvWriter();
File file = new File(context.getExternalFilesDir(DIRECTORY_DOWNLOADS), "magnetic" + value + ".csv");
//File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "magnetic" + value + ".csv");
try {
csvWriter.write(file, StandardCharsets.UTF_8, magneticData);
Toast.makeText(MainActivity.this, "File is recorded in memory.", Toast.LENGTH_LONG).show();
} catch (IOException io) {
Log.d("Error", io.getLocalizedMessage());
}
}
}
else{
Toast.makeText(MainActivity.this, "Nothing to save. Recording was not started.", Toast.LENGTH_LONG).show();
}
}
};
#Override
protected void onResume(){
super.onResume();
sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_FASTEST);
}
This code checks for permission:
private static boolean storagePermitted(Activity activity){
// Check read write permission
Boolean readPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
Boolean writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
if (readPermission && writePermission){
return true;
}
ActivityCompat.requestPermissions(activity, new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUESTCODE_STORAGE_PERMISSION);
return false;
}
Please let me know how can I use getExternalFilesDir() to save the file to Downloads directory!

how can i run a code just on first launch?

I want to send SMS just when the app launch for first time and for that I want to make a file in first launch and send SMS and in the next launch ask for existing that file if exist do not send SMS
here is my code
public static String file_name = "save_setting";
public static String text_file = "1";
public void writefile(){
try {
FileOutputStream fos_setting = openFileOutput(file_name , MODE_PRIVATE);
fos_setting.write(text_file.getBytes());
fos_setting.close();
}catch (Exception e) {
e.printStackTrace();
}
}
public void sendSMS(){
String phoneNumber = "000000000";
String message = "text";
PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,new Intent("SENT_SMS"), 0);
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, sentPI, null);
}
public void readfile() {
File directory = Environment.getDataDirectory();
File file = new File(directory + "/save_setting");
if (!file.exists()) {
writefile();
sendSMS();
} else {
}
}
On Android, consider using SharedPreferences instead. It allows you to store simple informations that will be persisted to a file managed by the system.
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean isFirstLaunch = prefs.getBoolean("first_launch", true);
if (isFirstLaunch) {
// Do your stuff here...
sendSMS();
// Remember that you already have sent the SMS
prefs.edit().putBoolean("first_launch", false).apply();
}
myFile.exsist() should work, what kind of error do you have?
Another way, if you want create this file just for check if you have to send or not the sms, is use the application SharedPreferences.
https://developer.android.com/reference/android/content/SharedPreferences.html

Download Manager Unable to Resume Download in case of Internet Disconnection and System Reboot

I have created a simple application which is supposed to download large zip files. After some R&D I came to the conclusion that I have to use Download Manager to achieve this. I want the download to resume automatically if the device is restarted or in case of unstable internet connectivity. Right now, the code is able to download large files as expected, but in case of internet connectivity fluctuations or system restart, it stops downloading.
The activity:
public class MainActivity extends ActionBarActivity {
String Download_path = "http://wickedbrains.com/map/mumbai.zip";
String Download_ID = "DOWNLOAD_ID";
SharedPreferences preferenceManager;
DownloadManager downloadManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
preferenceManager = PreferenceManager.getDefaultSharedPreferences(this);
downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
Button btnDownload = (Button)findViewById(R.id.download);
btnDownload.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View arg0) {
// Locate storage location
String filepath = "";
File folder = new File(
Environment.getExternalStorageDirectory() + "/osmdroid");
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
if (success) {
// Do something on success
filepath = Environment.getExternalStorageDirectory()
.getPath() + "/osmdroid";
// Deleting if zip file exists
File folder2 = Environment.getExternalStorageDirectory();
String fileName = folder2.getPath() + "/osmdroid/mumbai.zip";
File myFile = new File(fileName);
if(myFile.exists())
myFile.delete();
}
//Starting download manager to download file
Uri Download_Uri = Uri.parse(Download_path);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
long download_id = downloadManager.enqueue(request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle("Test")
.setDescription("Map Download")
.setDestinationInExternalPublicDir("/osmdroid","mumbai.zip"));
// long download_id = downloadManager.enqueue(request);
//Save the download id
Editor PrefEdit = preferenceManager.edit();
PrefEdit.putLong(Download_ID, download_id);
PrefEdit.commit();
}});
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
registerReceiver(downloadReceiver, intentFilter);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
unregisterReceiver(downloadReceiver);
}
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(preferenceManager.getLong(Download_ID, 0));
Cursor cursor = downloadManager.query(query);
if(cursor.moveToFirst()){
int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status = cursor.getInt(columnIndex);
int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
int reason = cursor.getInt(columnReason);
if(status == DownloadManager.STATUS_SUCCESSFUL){
//Retrieve the saved download id
long downloadID = preferenceManager.getLong(Download_ID, 0);
ParcelFileDescriptor file;
try {
file = downloadManager.openDownloadedFile(downloadID);
Toast.makeText(MainActivity.this,
"File Downloaded: " + file.toString(),
Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(MainActivity.this,
e.toString(),
Toast.LENGTH_LONG).show();
}
}else if(status == DownloadManager.STATUS_FAILED){
Toast.makeText(MainActivity.this,
"FAILED!\n" + "reason of " + reason,
Toast.LENGTH_LONG).show();
}else if(status == DownloadManager.STATUS_PAUSED){
Toast.makeText(MainActivity.this,
"PAUSED!\n" + "reason of " + reason,
Toast.LENGTH_LONG).show();
}else if(status == DownloadManager.STATUS_PENDING){
Toast.makeText(MainActivity.this,
"PENDING!",
Toast.LENGTH_LONG).show();
}else if(status == DownloadManager.STATUS_RUNNING){
Toast.makeText(MainActivity.this,
"RUNNING!",
Toast.LENGTH_LONG).show();
}
}
}
};
}
Where am I going wrong? What should I do to enable the resume capability of the download?
Quoting from docs,
The download manager will conduct the download in the background, taking care of HTTP interactions and retrying downloads after failures or across connectivity changes and system reboots.
I guess Download Manager, by default takes cares of retries.
If you are having issues you can use DownloadManager.Query class and query for COLUMN_STATUS and COLUMN_REASON to get the download status
Edit:
Starting a download
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Request request = new Request( YOUR_DOWNLOAD_URL );
long enqueue = dm.enqueue(request);
enqueue is more like a download reqeust id. You can use that enqueue to fetch the download progress/status
Querying the download Status
Query query = new Query();
query.setFilterById(enqueue);
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int downloadStatus = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (DownloadManager.STATUS_SUCCESSFUL == downloadStatus) {
// download succeded
} else if (DownloadManager.STATUS_FAILED == downloadStatus){
String failedReason = c.getString(c.getColumnIndex(DownloadManager.COLUMN_REASON));
// handle failures
}
}
Haven't tested the code myself. But it should work.
I confirm that this problem still exists in 2020, when testing in an emulator and having WiFi enabled, this error consistently appears (even with Android 10).
Switching off WiFi in the emulator seems to solve the problem.
Try to get the reason for the failed download.
e.g does it work on network switch wifi->data
(If your error reason is 1008- there seems to be a reported bug here
https://code.google.com/p/android/issues/detail?id=18462,
further:
http://papaya-backend.net/2013/04/12/why-http-etag-header-may-cause-your-downloading-apps-on-android-failed/)

Categories