1

My code listens to the DCIM folder, using a FileObserver.

All Android versions I used, except 4.1.1, sent only 1 event - when the video was finished taken. I think it's the correct behavior - write continually and close when finished.

In 4.1.1 (Galaxy Nexus and Nexus S) though, the event FileObserver.CLOSE_WRITE is sent twice - when the video starts and when it ends.

Also the same for photos - the event is sent twice - though it's not that critical.

The problem is that I can't distinguish between the start event and end event of a video.

I could try and check the size of the file, but because the event may have been delayed (slow/busy device), the size may be quite big.

Any idea why was the behavior changed? Do you know where is the camera's app source code? I can try and look at the history to understand that.

AlikElzin-kilaka
  • 34,335
  • 35
  • 194
  • 277
  • Maybe the file is now created empty (& closed) then data appended to that empty file (& closed again). Source might be [>this<](https://github.com/android/platform_packages_apps_camera/tree/jb-release/src/com/android/camera) – zapl Aug 16 '12 at 12:20
  • Have you done research into this and checked the AOSP source? The history is commonly found on github, if your observations indicate the behaviour change, then its for a reason. Having said that, the source is very different from GB to ICS, and from ICS to JB.... Maybe try the google's android newsgroups or irc? – t0mm13b Aug 16 '12 at 12:32
  • @zapl the project doesn't even have the manifest file :( I tried looking at https://android.googlesource.com/platform/packages/apps/Camera.git - No AndroidManifest.xml as well. – AlikElzin-kilaka Aug 16 '12 at 13:27
  • The key class is VideoCamera: https://github.com/android/platform_packages_apps_camera/blob/jb-release/src/com/android/camera/VideoCamera.java – AlikElzin-kilaka Aug 16 '12 at 13:48
  • It's not mVideoFileDescriptor being closed in that class. Perhaps when it's passed to mMediaRecorder or mEffectsRecorder? – AlikElzin-kilaka Aug 16 '12 at 13:50
  • On 4.1.1, a tmp video file is created along with the original file name. The original is 0KB and the video is written to the tmp file. Then the video is renamed from the tmp to the original. On a verizon's Galaxy Nexus (4.0.4), **no** tmp file is created at all and the video is written to the original. This explains the 2 events. The first CLOSE_WRITE event is for the initial empty file and the second if the rename from the tmp file. – AlikElzin-kilaka Aug 16 '12 at 14:29
  • I guess I should listen to the MediaStore... – AlikElzin-kilaka Aug 16 '12 at 14:43
  • Bad news. I changed the app to use a ContentObserver to listen to MediaStore changes, but the onChange() was invoked when the video started instead of when it was ended. **A video should not be added to the MediaStore if it's not finished!!!**. This must be a bug!!! – AlikElzin-kilaka Aug 21 '12 at 13:04
  • Opened a bug regarding the content resolving: http://code.google.com/p/android/issues/detail?id=36543 – AlikElzin-kilaka Aug 21 '12 at 14:53

2 Answers2

0

As I wrote in one of my comments, the difference between 4.1 and previous Android versions is that in 4.1.1, the file is written and closed twice. Once when an empty video file is created. Then the video is written into a tmp file. Then the rename/copy of the tmp file is the second write_close event.

In previous versions there's not tmp file - only the original - thus only one close_write event.

Please comment if you think it's a bug. I'm not sure.

Community
  • 1
  • 1
AlikElzin-kilaka
  • 34,335
  • 35
  • 194
  • 277
0

I have myself an app which monitors the DCIM/Camera directory through a FileObserver. What I noticed, and could be of help to you, is that the first operation is a CLOSE_WRITE, however the final operation is a MOVED_TO from the .tmp to the real file, which means you can recognize when the video is (really) ready.

My real code is more complex due to the requirements of my app, but the general idea is something like this:

/* My FileObserver implementation field */
private HashSet<String> jbCache = new HashSet(...)

...

protected void onEvent(int event, String path) {
   boolean isJellyBean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLYBEAN;

   if ((event & FileObserver.CLOSE_WRITE) > 0) {
      if (isJellyBean) {
         jbCache.add(path);
      } else {
         performYourWork(path);
      }
   } else if ((event & FileObserver.MOVED_TO) > 0 && isJellyBean && jbCache.contains(path)) {
      performYourWork(path);
      jbCache.remove(path);
   }
}

You have to listen to both CLOSE_WRITE and MOVED_TO when you register the events you want to catch, obviously.

Although I starred your bug, I doubt Google will ever acknowledge it, as it looks like there could be some (disagreeable) reasoning behind the change. The Camera app is mostly a no-standard crap anyway (e.g.: fake DCIM standard compliance)

hrk
  • 56
  • 2