FileObserver in Android 8 does not fire the CREATE event - android

In Android I use the FileObserver to observe a folder and do something when a new file is created.
I noticed that the CREATE event is generated on Android 5 and Android 7 but it is NOT generated on Android 8. Any idea why?
This is the pseudocode.
public class FolderObserver extends FileObserver {
String path;
static final int mask = (FileObserver.CREATE);
public FolderObserver(String path) {
super(path,mask);
this.path = path;
}
void doSomeAction(string file){}
#Override
public void onEvent(int i, #Nullable String s) {
switch (i) {
case FileObserver.CREATE:
// this event is generated on Android 5 and 7
// but is NOT generated on Android 8
doSomeAction(s);
break;
default:
break;
}
}
}
....
/*
in my client
*/
FolderObserver observer = new FolderObserver(myPath);
observer.startWatching();

Finally I found a workaround.
Copying a new file into the observed folder generates the CREATE event on Android 5 and 7 while it generates the MOVE_TO event on Android 8, strange but ok.
So I simply listen for both events like that
static final int mask = (FileObserver.CREATE | FileObserver.MOVED_TO);
....
public void onEvent(int i, #Nullable String s) {
switch (i) {
case FileObserver.CREATE:
case FileObserver.MOVED_TO:
doSomeAction(s);
break;
default:
break;
}
}

Related

cloud.speech.v1.StreamingRecognizeResponse - error: an enum switch case label must be the unqualified name of an enumeration constant

I made a project in Android Studio with Google Cloud Platform Java sample project from github a year ago. It was working correctly by then but a month ago when I opened the project, I faced the following error:
error: an enum switch case label must be the unqualified name of an enumeration constant
I have checked other solutions on SO,Ex, but on the StreamingRecognizeResponse class I saw the code is written as the solution suggests. Ex:
protected final Object dynamicMethod(
com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,
Object arg0, Object arg1) {
switch (method) {
case NEW_MUTABLE_INSTANCE: {
return new com.google.cloud.speech.v1.StreamingRecognizeResponse();
}
case IS_INITIALIZED: { //**clicking on first error takes to this line.** but it is as solution suggests.
return DEFAULT_INSTANCE;
}
case MAKE_IMMUTABLE: {
results_.makeImmutable();
return null;
}
case NEW_BUILDER: {
return new Builder();
}
case VISIT: {...
...................
I can't compile my project anymore and I need to fix this error.
Any suggestion to solve this problem would help.
It is unclear which Java sample you are referring to, but com.google.protobuf enumeration GeneratedMessageLite.MethodToInvoke generally has these constants:
Object dynamicMethod(MethodToInvoke method, Object arg0, Object arg1) {
switch (method) {
case GET_DEFAULT_INSTANCE: {
return DEFAULT_INSTANCE;
}
case GET_PARSER: {
break;
}
case IS_INITIALIZED: {
break;
}
case MAKE_IMMUTABLE: {
results_.makeImmutable();
return null;
}
case MERGE_FROM: {
break;
}
case NEW_BUILDER: {
return new Builder();
}
case NEW_INSTANCE: {
return new com.google.cloud.speech.v1.StreamingRecognizeResponse();
}
case PARSE_PARTIAL_FROM: {
break;
}
}
}
There is no NEW_MUTABLE_INSTANCE and there is no VISIT. One can also list them:
for (GeneratedMessageLite.MethodToInvoke c : GeneratedMessageLite.MethodToInvoke.values()) {
System.out.println(c);
}
Also see StreamingRecognizeResponse.

How to restrict bound service to be called by particular packages

I have written a bound service and I would like this service to be only called from particular app. I do not want other apps to be able to make calls to this service.
The options I know so far are:
Use a permission. There seems to be 3 secured permission, dangerous, signature and signatureOrSystem. Unfortunately, none of these permissions will work for me as I don't want users to accept this permission also both app does not have same signature and these are not system app.
Get app name on service bind or when making a call to service. I looked up a way to do this on stackoverflow here. This unfortunately does not works for me as it always returns the app ID in which the service resides.
Is there any other option for me or I can use the above mentioned options with some change to achieve the desired requirement.
Bound Service Code
public class SampleCommsService extends Service {
private static Messenger messanger;
#Override
public IBinder onBind(Intent intent) {
Log.e("TEST", "package intent: " + intent.getPackage());
String callingApp = MyApplication.getAppContext().getPackageManager().getNameForUid(Binder.getCallingUid());
Log.e("TEST", "onBind - package name: " + callingApp);
return getMyBinder();
}
private synchronized IBinder getMyBinder() {
if (messanger == null) {
messanger = new Messenger(new SettingsProcessor());
}
return messanger.getBinder();
}
class SettingsProcessor extends Handler {
private static final int GET_SETTINGS_REQUEST = 1;
private static final int UPDATE_SETTINGS_RESPONSE = 2;
private static final String SETTINGS = "settings";
#Override
public void handleMessage(Message msg) {
String callingApp = MyApplication.getAppContext().getPackageManager().getNameForUid(Binder.getCallingUid());
Log.e("TEST", "handle message - package name: " + callingApp);
switch (msg.what) {
case GET_SETTINGS_REQUEST:
sendSettingsValue(msg);
break;
default:
super.handleMessage(msg);
}
}
private void sendSettingsValue(Message msg) {
try {
Message resp = Message.obtain(null, UPDATE_SETTINGS_RESPONSE);
Bundle bundle = new Bundle();
bundle.putBoolean(SETTINGS, MyApplication.isSettingsEnabled());
resp.setData(bundle);
msg.replyTo.send(resp);
} catch (RemoteException e) {
// ignore
}
}
}
}
Output on calling api:
02-01 15:21:03.138 7704-7704/my.service.package E/TEST: package intent: null
02-01 15:21:03.139 7704-7704/my.service.package E/TEST: onBind - package name: my.service.package
02-01 15:21:12.429 7704-7704/my.service.package E/TEST: handle message - package name: my.service.package
OK, I was able to solve this problem based on a given answer here. The answer given in the link obviously does not works, but you can get the app ID from the Handler used for the bound service.
class SettingsProcessor extends Handler {
#Override
public void handleMessage(Message msg) {
String callingApp = MyApplication.getAppContext().getPackageManager().getNameForUid(msg.sendingUid);
Log.e("TEST", "handle message - package name: " + callingApp);
}
}
Instead of Binder.getCallingUid(), I am using msg.sendingUid and it works fine for me.

TransferUtility Does not trigger onProgresschanged

I am working on a project where I want to upload files after developer authentication is complete. I am using AWS Cognito for authentication. Problem here is sometimes TransferUtility does not trigger onProgresschanged. Although it does not trigger onprogresschanged but the file is getting uploaded. I want to show a progressbar on the UI for every upload.It is working sometimes and sometimes it is not working.
Here is how I am uploading files.
public void upload() {
ClientConfiguration configuration = new ClientConfiguration();
configuration.setProtocol(Protocol.HTTP);
configuration.setSocketTimeout(5 * 10000);
configuration.setConnectionTimeout(5 * 10000);
configuration.setMaxErrorRetry(3);
if(sS3Client==null) {
sS3Client = new AmazonS3Client(credentials,configuration);
}
sTransferUtility = new TransferUtility(sS3Client,
this.ctx);
observer = sTransferUtility.upload("bucketer", "Filename", "file");
observer.setTransferListener(new UploadListener(progress));
}
private class UploadListener implements TransferListener {
ProgressBar progressBar;
public UploadListener(ProgressBar progress){
this.progressBar = progress;
}
#Override
public void onStateChanged(int i, TransferState transferState) {
Log.d("STATUS CHANGED:".concat(String.valueOf(i)),transferState.toString());
switch (transferState.toString())
{
case "IN_PROGRESS":
{
Log.d("IN_PROGRESS", "IN_PROGRESS");
}
break;
case "COMPLETED":
{
Log.d("COMPLETED COMPLETED", "COMPLETED");
}
break;
}
}
#Override
public void onProgressChanged(int i, long l, long l1) {
updator();
this.progressBar.setProgress(transferprogres);
}
#Override
public void onError(int i, Exception e) {
Log.d("UPOLADING ERROR:",String.valueOf(e));
}
}
public void updator(){
transferprogres = (int) ((double) observer.getBytesTransferred() * 100 / observer.getBytesTotal());
}
The code above is a part of total project. For more details comment.
Why is it showing weird performance?
See Aws S3 TransferService Upload failing without errors and https://github.com/aws/aws-sdk-android/issues/101. In short, v2.2.12 requires user to manage the life cycle of transfer listeners as transfer utility keeps only weak references of them. You can make the listener or the observer as class variable to prevent it from garbage collected. Anyway, we are tweaking the listeners in future releases. Sorry for the trouble and please stay tuned.

Check Directory for new files in android

I need to read all files in a directory every say 5 minutes and check if any new files have been created.
What would be the best way to do this?
I thought of using a DB to store all file names and then compare one by one but it seems like it would take too long.
I also thought of writing the file names to a text file and the looking if the file name is on the list or not.
Is there a better way?
Why don't you try with FileObservers
private final class DirectoryObserver extends FileObserver {
private DirectoryObserver(String path, int mask) {
super(path, mask);
}
#Override
public void onEvent(int event, String pathString) {
event &= FileObserver.ALL_EVENTS;
switch (event) {
case FileObserver.DELETE_SELF:
//do stuff
break;
case FileObserver.CREATE:
case FileObserver.DELETE:
//do stuff
break;
}
}
}
Ref:FileObserver CREATE or DELETE received only for files

How to detect a newly created file in android?

Is there any way to detect when a file is created or modified or downloaded in the android phone? I checked the available intents, but none of them are related to files. I am working on the broadcast receiver and couldnt figure out a way to detect a new file creation. Can someone please help?
use FileObserver...
public class MyFileObserver extends FileObserver {
public MyFileObserver(String path) {
super(path);
}
#Override
public void onEvent(int event, String path) {
switch (event) {
case DELETE:
// file deleted
break;
case ACCESS:
// file accessed;
break;
case MODIFY:
// file modified;
break;
case OPEN:
// file opened
break;
// see documentation for available events
default:
break;
}
}
}
sample usage:
MyFileObserver fileObserver = new MyFileObserver(Environment.getExternalStorageDirectory().getPath());
fileObserver.startWatching();

Categories

Resources