Nexus 10 blank screenshot

Hi,

I am trying to save a png file from a screenshot taken from c++ code on an Android device.

To save the screenshot I first attach my class to the OnScreenshotCaptured delegate, then I convert the compressed TArray to a TArray using FImageUtils::CompressImageArray to a jbyteArray and pass the byte[] to the Java part of the application where the Bitmap is created and saved as a png.

The png file is properly saved on a Samsung Galaxy S4, but on a Nexus 10 the same code produces a white png (or a black jpg if I change format).

What could be the cause of that?

I noticed that on the Galaxy S4 the compressedBitmap TArray has a resolution of 1024x576 instead of the native 1920x1080 whereas on the Nexus 10 the log shows a resolution of 921x576 (instead of the native res of 2560 x 1600).

If I take the screenshot including SlateUI elements, on the Samsung Galaxy S4 everything is saved correctly, whereas on Nexus10 I can only see Slate elements on a black backround.

The delegate callback is as follows:

void AndroidInterface::SaveBitmap(const TArray<FColor>& colorData, int32 width, int32 height) {
	
	JNIEnv* env = FAndroidApplication::GetJavaEnv(true);
	
	TArray<FColor> bitmap = colorData;
	
	TArray<uint8> compressedBitmap;
	
	FImageUtils::CompressImageArray(width, height, bitmap, compressedBitmap);
	
	
	size_t len = width*height*compressedBitmap.GetTypeSize();
	
	LOGD("===========Width: %i, height: %i - Len of bitmap element: %i==========", width, height, len);
	
	jbyteArray bitmapData = env->NewByteArray(len);
	
	LOGD("===========Called new byte array==========");
	
	env->SetByteArrayRegion(bitmapData, 0, len, (const jbyte*)compressedBitmap.GetData() );
	
	LOGD("===========Populated byte array==========");
	
	check (bitmapData != NULL && "Couldn't create byte array");
	
	jclass gameActivityClass = FAndroidApplication::FindJavaClass("com/epicgames/ue4/GameActivity");
	check (gameActivityClass != nullptr && "GameActivityClassNotFound");
	
	//get the method signature to take a game screenshot
	jmethodID saveScreenshot = env->GetMethodID(gameActivityClass, "saveScreenshot", "([BII)V");
	
	env->CallVoidMethod(AndroidInterface::sGameActivity, saveScreenshot, bitmapData, width, height);
	
	env->DeleteLocalRef(bitmapData);
	
}

Whereas the java code that handles the png creation is:

public void saveScreenshot(final byte[] colors, int width, int height) {

		android.util.Log.d("GameActivity", "======saveScreenshot called. Width: " + width + " height: " + height + "=======");
		android.util.Log.d("GameActivity", "Color content---->\n " + Arrays.toString(colors));
		final BitmapFactory.Options opts = new BitmapFactory.Options();
		opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
		final Bitmap bitmap = BitmapFactory.decodeByteArray(colors, 0, colors.length, opts);

		final FlipBitmap flipBitmapTask = new FlipBitmap();
		flipBitmapTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, bitmap);

	}

FlipBitmap is an AsyncTask that just creates the png file on another thread.

Hey Luigitni,

In order to better assist you, would you mind providing a sample project with this screenshot capability within it, so I can test out different Android devices and see if it’s an issue with the phone, code or the engine.

Looking forward to hearing back from you, thanks!

Hey Samantha,

thanks for your response.
Sure I can do it, but…how and in which format? Would a repo on Bitbucket/Github be ok?

You can upload a sample project to any site and simply provide the downloadable link to me. In your next reply, please include the full reproduction steps so I too can see the issue you’re experiencing.

Thanks! :slight_smile:

Hey Samantha,

From this link you can download the archives.
You will need both the Unreal Project and the Android Studio project to launch the game.

Here are the instructions:

  1. Open the project with UE4Editor
  2. Cook for Android (All)
  3. Generate the intermediates APK folder making sure libUE4.so is
    there.
  4. Now open the Android Studio Project. It’s built with the
    experimental gradle plugin, which
    should already be there. In case it
    will download it automatically.
  5. Copy/paste ibUE4.so and libgnustl_shared.so from UnrealProject/Intermediate/Android/APK/libs/armeabi-v7a
    to app/jniLibs/armeabi-v7a
  6. push the main.1.package.name.obb file to
    the device
    Android/obb/package.name using
    adb push
  7. Launch the App.

The mainActivity of the app will be presented. Pressing the button launches UE4 and the game content. Once in the level, press the button to take a screenshot or the other one to take a screenshot including Slate Widget.

I apologize for the unconventional build routine but I tried to keep the sample project as close as possible to the one I am having issues with.

I have attempted the steps above. I was unable to reproduce this issue with what you provided. The Nexus 10 is a device that we do not have. The closest device that we have is a Nexus 9, which is a few generations newer than the Nexus 10.

What version of Android is the Galaxy and the Nexus on?

I also tested this on a Nexus 5 and I was crashing when using the buttons. I didn’t notice any pictures being taken. Are there any parts of the steps you provided above that I may have misunderstood or perhaps were left out?

Thanks!

Hey Samantha,
The nexus 10 is on Android 5.1.1, whereas the Samsung Galaxy S4 is on 5.0.1.

I am not sure if it’s possible to reproduce the issue on a Nexus 9 for maybe its related to some specific device drivers/GL implementation, given that the same code works on all other devices except for that one, but who knows.

Regarding the crash I tested everything before uploading the archives, albeit I removed intermediate build files to reduce archive size, but if that were the cause of the crash I doubt it would even compile.
Did it work properly on the Nexus 9?
Could you please post your crash stacktrace from the Android logcat so I can see what went wrong and fix it?
Pressing a button should fire Blueprint code that in turn calls Unreal c++ code which shouldn’t fail.
Thanks in advance!

Hey,

I’ve discussed this with our Android developer and we’ve succeeded in getting your test project to work on a Nexus 5 here so it is likely there is an issue with the glReadPixels on the Nexus 10. Unfortunately, we do not have one of these for testing here. Also, in 4.10 the AndroidJNI.* are exposed publicly so it is easier to access the GameActivity and the new AndroidPlugin system may be a better way to do this since it allows extending the GameActivity.java and allows modification to the AndroidManifest and Proguard.

Thank you!

Hey Samantha,

publicly exposed Android methods sounds like great news! Thanks for the info! Indeed the hardest times I had with UE4 was to integrate it with iOS and Android SDKs due to not having/being able to find a way to access some JNI objects or not controlling the lifecycle of the engine (i.e. IOSLauncher.cpp and AndroidLauncher.cpp objects/methods).

Back IT, I imagined it would be something device-specific and out of my reach. I posted this same question on StackOverflow (here) and a very kind Google’s Android developer tried to help with this but I don’t have enough knowledge to provide him in-depth further infos. If you wouldn’t mind to elaborate a little on what you think might be the issue with glReadPixels it could be a nice occasion to also report this problem also to Google.

I think for now I will just avoid publishing the app for Nexus 10 devices.
In any case, many many thanks for your help, it’s been very useful even if we didn’t solve the issue!

We believe that there is a glitch or error with your devices glReadPixels. This returns pixel data from the frame buffer. Since we don’t have a Nexus 10 here to test ourselves, you may want to let Google know of the information as they should be able to look into it further.

4.10 should make your project a lot easier to deploy to Android devices without having to use AndroidStudio.

Good luck! :slight_smile:

I have the same issue in Huawei P9. When I captured the screenshot with ‘ShowUI’ by input console command, the result is just a black image.