Android - where to save screenshots?

Started by
5 comments, last by alh420 8 years, 2 months ago

I've been trying to save screenshots of my app, which I can do but my issue is more of where to save them. If I hit the actual Android screen capture (volume down+power button) then it screen captures and goes to a folder Pictures/Screenshots and is mediately accessible from both my phone and from my computer (when it is plugged in). Ideally I'd like to replicate that some what with my own screen capturing.

I am using c++ and a native app so I used JNI to access the Environment.Pictures field and got the path (external directory) to where I should save screenshots. I can save the screenshots there but it is VERY wierd. When I save a screenshot it does not show up on the photos app (Android screencaptures do), it does not show up on my phone when I browse from my PC (Android captures do) but it does show up if I go to settings->storage->all files then navigate to the correct directory. I have to restart the phone for things to actually work correctly (they then show up in the pictures app and when I browse from the computer). I have a Nexus 5 which doesn't have an external card and so it emulates it instead which I suspect is what causes this weird behaviour.

I'm really confused as to where I can actually save my images that is also accessible to the user. I can't choose external storage since it causes this weird issue plus I can't rely on there being external storage and the other options I found in my search are to save to the private folder for my app but that won't be much use. What are my notions here? I'm not fussy about how I do this, I just wan't the user to be able to press the screenshot button (in my app), and the screenshot to be saved somewhere reasonably accessible to the user without them having to mess around. I also don't want to have to rely on external storage being present (though I can offer that as an option)

The built in screen capture isn't quite up to what I require - it always captures the navigation bar (which I can't disable) and I'd like to offer screenshots in non-native resolution too (greater than what the screen supports).

I currently use this to get the path to the pictures directory:

http://developer.android.com/reference/android/os/Environment.html#getExternalStoragePublicDirectory(java.lang.String)

From what I have read external doesn't actually mean external in the sense of having an expansion slot but more 'shared' rather than private storage.

Saving the images isn't a problem, it's where to save them that is causing me a headache and all the searches I've done just say the same things (external directory or private).

Any suggestions or advice is very welcome.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Advertisement

I have a Nexus 5 which doesn't have an external card and so it emulates it instead which I suspect is what causes this weird behaviour

Afaik, all android devices has "external storage". Most have emulated external storage, so that shouldn't be a problem.


I have to restart the phone for things to actually work correctly

For the file browsing from PC, this is a known issue since a very long time in very many android versions. It is extremely annoying and incredibly stupid.

I know of no way to get around it when it comes to creating files on external storage.

Feel free to vent in the (now pretty long) thread about it on google groups ;)

For the media files, have you tried to run the "MediaScannerConnection.scanFile" on your new file? (example in the url you posted).


For the media files, have you tried to run the "MediaScannerConnection.scanFile" on your new file? (example in the url you posted).
It might help.

That looks promising, I will try this now.

Also I edited my original post slightly, I did try with my second phone and it behaves the same way with regard to external storage emulation and the files not showing until a restart.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.


Also I edited my original post slightly, I did try with my second phone and it behaves the same way with regard to external storage emulation and the files not showing until a restart.

Yeah, most android devices has this problem.

Still is a problem on my Nexus 5X running Android 6.0

At least they have fixed so I now can delete folders that doesn't exist anymore in Android File Transfer, which helps when debugging games with big OBB-files (which you have to re-upload to your device every re-install...)

Now I don't have to remember to remove it manually _before_ uninstalling anymore...

This was absolutely hideous code wise calling from c++ but it is exactly right. After calling the scan files thing the image does show up in my pictures folder and hitting refresh while viewing the folder from my computer also then shows up :). Now to clean up my code..

Thanks alot!

I'll hopefully post my solution when I clean it up and add some error checking.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Got it all working perfectly now thanks to your help. That media scan was the missing link.

I am getting the pictures directory using getExternalStoragePublicDirectory from the Environment and saving my screenshots to /Screenshots under that. Once saved I call scanFile static method from MediaScannerConnection. It's a bit ugly but it magically works so I'm not complaining.


void ScanNewMedia(const std::string& path, const std::string* mime)
{
	if (!m_App || path.length() == 0)
		return;

	// Construction binds the VM to this thread
	JavaUtilities::JavaVMAutoDetatch autoDetatch(m_App->activity->vm);
	JNIEnv*& env = autoDetatch.env;
	if (env == nullptr) return;

	// Get the required classes/objects
	jclass mediaScannerConnectionClass = env->FindClass("android/media/MediaScannerConnection");
	if (mediaScannerConnectionClass == nullptr) return;
	jmethodID scanFileStaticMethod = env->GetStaticMethodID(mediaScannerConnectionClass, "scanFile",
		"(Landroid/content/Context;[Ljava/lang/String;"
		"[Ljava/lang/String;Landroid/media/MediaScannerConnection$OnScanCompletedListener;)V");
	if (scanFileStaticMethod == nullptr) return;

	// scanFiles takes an array of strings
	jclass arrayClass = env->FindClass("java/util/ArrayList");
	if (arrayClass == nullptr) return;
	jmethodID arrayClassConstructor = env->GetMethodID(arrayClass, "<init>", "()V");
	if (arrayClassConstructor == nullptr) return;
	jmethodID addMethod = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");
	if (addMethod == nullptr) return;
	jobject arrayObject = env->NewObject(arrayClass, arrayClassConstructor);
	if (arrayObject == nullptr) return;
	jclass stringClass = env->FindClass("java/lang/String");
	if (stringClass == nullptr) return;

	jobjectArray paths = env->NewObjectArray(1, stringClass, env->NewStringUTF(path.c_str()));
	if (paths == nullptr) return;

	// This can be null
	jobjectArray mimes = nullptr;
	if (mime)
	{
		// can't be null after this though
		mimes = env->NewObjectArray(1, stringClass, env->NewStringUTF(mime->c_str()));
		if (mimes == nullptr) return;
	}

	// Finally call the method
	env->CallStaticVoidMethod(mediaScannerConnectionClass, scanFileStaticMethod,
		m_App->activity->clazz, paths, mimes, nullptr);

	// thread auto detach on exit
}

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

Glad to help!

Nice to hear it also made the file show up in the file browser on the computer, I'll definitely use that at some point.

This topic is closed to new replies.

Advertisement