Skip to content

Commit

Permalink
Fix shaky crash due to : Software rendering doesn't support hardware …
Browse files Browse the repository at this point in the history
…bitmaps (#73)

Using PixelCopy API in Android O and beyond to prevent the IllegalState crash caused by hardware bitmaps. Should fix this issue: #48 (comment)

This solution is based on recommendation here: https://bumptech.github.io/glide/doc/hardwarebitmaps.html#whats-broken-when-we-use-hardware-bitmaps

* Fix shaky crash due to IllegalStateException

* Return null bitmap incase of no base activity and other formatting updates.
  • Loading branch information
advait8 authored Mar 25, 2024
1 parent aa11f89 commit a1d2400
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 10 deletions.
16 changes: 15 additions & 1 deletion shaky/src/main/java/com/linkedin/android/shaky/Paper.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.linkedin.android.shaky;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
Expand All @@ -27,8 +28,10 @@
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.ContextThemeWrapper;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -158,7 +161,18 @@ public void undo() {
* @return the current drawing as a Bitmap
*/
public Bitmap capture() {
return Utils.capture(this);
Window window = null;
if (getContext() instanceof Activity) {
window = ((Activity)(getContext())).getWindow();
} else if (getContext() instanceof ContextThemeWrapper) {
Context baseContext = ((ContextThemeWrapper)getContext()).getBaseContext();
if (baseContext instanceof Activity) {
window = ((Activity)baseContext).getWindow();
}
} else {
return null;
}
return Utils.capture(this, window);
}

private void applyEvents() {
Expand Down
2 changes: 1 addition & 1 deletion shaky/src/main/java/com/linkedin/android/shaky/Shaky.java
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ private Bitmap getScreenshotBitmap() {
// Fallback to using the default screenshot capture mechanism if Falcon does not work (e.g. if it has not
// been updated to work on newer versions of Android yet)
View view = activity.getWindow().getDecorView().getRootView();
return Utils.capture(view);
return Utils.capture(view, activity.getWindow());
}
}

Expand Down
34 changes: 26 additions & 8 deletions shaky/src/main/java/com/linkedin/android/shaky/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,23 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.annotation.WorkerThread;
import androidx.core.content.FileProvider;

import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.PixelCopy;
import android.view.View;
import android.view.Window;

import java.io.ByteArrayOutputStream;
import java.io.File;
Expand Down Expand Up @@ -103,15 +110,26 @@ static File writeBitmapToFile(@NonNull Bitmap bitmap, @NonNull File file) {
* Saves the view as a Bitmap screenshot.
*/
@Nullable
static Bitmap capture(View view) {
if (view.getWidth() == 0 || view.getHeight() == 0) {
return null;
}
static Bitmap capture(View view, Window window) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
int[] location = new int[2];
view.getLocationInWindow(location);
PixelCopy.request(window,
new Rect(location[0], location[1], location[0] + view.getWidth(), location[1] + view.getHeight()),
bitmap, copyResult -> {},
new Handler(Looper.getMainLooper()));
return bitmap;
} else {
if (view.getWidth() == 0 || view.getHeight() == 0) {
return null;
}

Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
}

/**
Expand Down

0 comments on commit a1d2400

Please sign in to comment.