ImageView won't hide or clear image on Android - java

I've been working with android this days (iOS Developer), and I am unable to clear a ImageView. I've tried everything! Literally! I take a photo with my Camera instance, I am able to place the image in the image view and then when I want to remove it. It just freezes. However, the other UIView elements altered in the code below, work normally. (So I guess the UI Thread is working just fine).
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d("DEFAULTS", "Back to Defaults");
processedTranslations = 0;
totalTranslations = 0;
nextIsProcessFaces = false;
nextIsFinish = false;
currentImage = null;
imagePreview.setVisibility(View.GONE);
imagePreview.setImageDrawable(null);
imagePreview.setImageBitmap(null);
imagePreview.setImageURI(null);
imagePreview.setImageResource(android.R.color.transparent);
imagePreview.setImageResource(0);
imagePreview.destroyDrawingCache();
imagePreview.invalidate();
loadingView.setVisibility(View.GONE);
captureButton.setEnabled(true);
}
});
And here is where I assign the resource to the ImageView (This block gets executed before the previous block) (Maybe the error is that it is nested in another thread? It is not released when the other thread tries to edit that imageView?)
runOnUiThread(new Runnable() {
#Override
public void run() {
Bitmap bitMapImage = BitmapFactory.decodeByteArray(blockData, 0, blockData.length);
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitMapImage , 0, 0, bitMapImage .getWidth(), bitMapImage .getHeight(), matrix, true);
imagePreview.setImageBitmap(rotatedBitmap);
imagePreview.setScaleType(ImageView.ScaleType.CENTER_CROP);
imagePreview.setVisibility(View.VISIBLE);
}
});
I know this appears to be a really novice question (And a very repeated question) but I've tried all of the answers in similar questions (As you can see in my code.) Thanks so much for your help!

Related

Screenshot not captured while agora.io video call Android Java

I have implemented a video calling feature in our app. There is a button which captures the screenshot of specific view. On video call there a two views Local View and Remote View. These are actually Relative and Frame layouts. In this case i want take screenshot of remote view but it's just giving me a blank image. I think somehow agora video calling not allowing it but there should be any settings or something to disable this but that i have not found yet. here is the code:
Setting up remote video:
mRemoteContainer is a RelativeLayout and mRemoteVideo is VideoCanvas by agora.io
Similarly mLocalContainer is FrameLayout.
private void setupRemoteVideo(int uid) {
ViewGroup parent = mRemoteContainer;
if (parent.indexOfChild(mLocalVideo.view) > -1) {
parent = mLocalContainer;
}
if (mRemoteVideo != null) {
return;
}
SurfaceView view = RtcEngine.CreateRendererView(getBaseContext());
view.setZOrderMediaOverlay(parent == mLocalContainer);
parent.addView(view);
mRemoteVideo = new VideoCanvas(view, VideoCanvas.RENDER_MODE_HIDDEN, uid);
mRemoteVideo.view.setWillNotDraw(false);
mRtcEngine.setupRemoteVideo(mRemoteVideo);
}
This function used to get bitmap from the view
private Bitmap getScreenShotFromView(View v) {
Bitmap screeShoot = null;
try {
screeShoot = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(screeShoot);
v.draw(canvas);
} catch (Exception e) {
Log.e("GFG", "Failed to capture screenshot because:" + e.getMessage());
}
return screeShoot;
}
I tried function call with both view but getting black or blank image
Bitmap bitmap = getScreenShotFromView(mRemoteVideo.view);
Bitmap bitmap = getScreenShotFromView(mRemoteContainer);
Your help will be really appreciated for me as i stuck on this issue.
By the way I used the same view capturing technique on iOS with swift
and Its working fine.

How to take full scrolled screenshot in flutter_native_screenshot

So in my Flutter project I'm using this plugin flutter_native_screenshot
It works quite well for single screenshot of the page, but it's not taking full scrollable screenshot. I've checked behind this plugin use a code like takeScreenshotOld()
View view = this.activity.getWindow().getDecorView().getRootView();
view.setDrawingCacheEnabled(true);
Bitmap bitmap = null;
if (this.renderer.getClass() == FlutterView.class) {
bitmap = ((FlutterView) this.renderer).getBitmap();
} else if (this.renderer.getClass() == FlutterRenderer.class) {
bitmap = ((FlutterRenderer) this.renderer).getBitmap();
}
The question is:- How can I make this code to take full scrolled screenshot.
I've tried flutter screenshot plugin as well but unfortunately it fails to capture flutter_tex (webview)
and shows blank. The native plugin worked but unable to get full page.
This answer is using Java but you can follow the same logic in flutter,
You will need to do the following steps:
Implement a listener to the scrollView scrolling, then every time the height is dividable by screen height, take a screenshot
Display display = getWindowManager().getDefaultDisplay();
int height = display.getHeight();
mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
int scrollY = targetScrollView.getScrollY();
if (scrollY % height == 0){
takeScreenShotAndSaveIt();
}
}
});
Manullay scroll through the scroll view
mScrollView.post(new Runnable() {
public void run() {
mScrollView.fullScroll(mScrollView.FOCUS_DOWN);
}
});
Finally you will remove scroll listener and merge the saved images of the screen shots.
Another option is to take the full view as bitmap and save it: https://stackoverflow.com/a/43817149/19074651

Getting image data continuously from camera, SurfaceView or SurfaceHolder

So I have this camera preview set up with Camera, SurfaceView and SurfaceHolder.
I have also an ImageView where I will be putting a modified version of the camera image and I want this to update lets say once every second.
All code is ready and already working when I load images from "res" but I have a really hard time reading the image data from the camera.
I've tried following already:
Creating an intent for MediaStore.ACTION_IMAGE_CAPTURE and starting an onActivityResult getting a small thumbnail (enough for me actually) from (Bitmap)data.getExtras().get("data")
The problem is that this opens the camera App and you need to "manually" take a picture.
Creating a Camera.PreviewCallback, taking the YuvImage, and converting it to an image using YuvImage.compressToJpeg(...).
The problem here is that I can't get it to start no matter when or where i put the Camera.setPreviewCallbackWithBuffer(PreviewCallback).
Try to take the data directly from PreviewHolder by locking in to the canvas using lockCanvas() and trying to convert it to a bitmap
Obviously Doesn't work.
Edit:
What is the best way to make this work? I mean QR-Code readers must read the image data out of the camera continuously, how do they work?
I went for option number 2 and finally made it work.
used this callback, forgot the #Override before
private Camera.PreviewCallback previewCallback= new Camera.PreviewCallback()
{
#Override
public void onPreviewFrame(byte[] data,Camera cam)
{
Camera.Size previewSize = cam.getParameters().getPreviewSize();
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21,previewSize.width,previewSize.height, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0,0,previewSize.width,previewSize.height),80,baos);
byte[] jdata = baos.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jdata,0,jdata.length);
}
};
And initiating it using setPreviewCallback rather than setPreviewCallbackWithBuffer
SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback()
{
public void surfaceCreated(SurfaceHolder holder) {
camera.setPreviewCallback(previewCallback);
}
}

Add an image as background and put other images on top of it

I am creating an image by using Canvas- and Bitmap class. I want to set it as a background for the user. Then I want to add some more images on top of it.
this is the code for image that is supposed to be as background.
ImageView imgMap1 = (ImageView) findViewById(R.id.imgMap1);
imgMap1.setImageDrawable(new BitmapDrawable(Bitmap.createBitmap(bmp, 0, 0, 500, 500)));
and this is the code to make it as background:
LinearLayout ll = new LinearLayout(this);
ll.setBackgroundResource(R.drawable.nn);
this.setContentView(ll);
The Problem here is: When I set it as background, I can't see the other photo anymore.
How can I do this?
Thanks in advance.
The other Images are added in the Layout. they are movable by finger touch. user can reposition them by finger.
ImageView i1 = (ImageView) findViewById(R.id.Image1);
ImageView i2 = (ImageView) findViewById(R.id.Image2);
The layout is built from the top down in your XML file, or in the order you add elements in code. It sounds like your other images is being added to the layout first, either as a higher-up element in the XML file, or earlier in your code. You'll need to add the other code as context for a complete answer.
Just noticed that you can directly set Bitmap as your ImageView's content using setImageBitmap(Bitmap bm)See the Android Reference
Then let talk about your question.
First, create your own class extends the View;
Second, load background image and overlay image using Bitmap
Third, invoke onTouch event, so that the onDraw method will automatically redraw the overlay image using the coordinates returned by onTouch
Something like:
public class dragndrop extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// using this to load your background image
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565; // this is not a must
bmBackground = BitmapFactory.decodeFile(filePath, opt);
super.onCreate(savedInstanceState);
DrawView dv = new DrawView(dragndrop.this);
setContentView(dv);
}
public class DrawView extends View {
Point coordinate;
public DrawView(Context context) {
super(context);
setFocusable(true); //necessary for getting the touch events
}
#Override
protected void onDraw(Canvas canvas) {
// assume you have already load your background image as bitmap
canvas.drawBitmap(bmBackground, 0, 0, null);
// assume bm is the overlay image you need to put on top,
// the method here will draw the object with the coordinate you give
canvas.drawBitmap(bm, coordinate.x, coordinate.y, null);
}
// events when touching the screen
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
int x = (int)event.getX();
int y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN:
// add code here to determine the point user touched is within the object or not
break;
}
}
break;
case MotionEvent.ACTION_MOVE: // touch 'n' drag
// pass the touch point to your object
coordinate.x = x;
coordinate.y = y;
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
invalidate();
return true;
}
}
}
This is my own snippet, please edit before use, and please let me know when your question is resolved.

Combine canvas and layout?

Presumably it must be quite common to desire a screen in which
there are graphical elements (for which you may like to use a canvas) and widgets/buttons on the same screen. But everything I've looked at so far gives examples of either screens full of widgets OR whole screen canvases. Can someone point me to some example code for using both at the same time.
...or is this not the done thing?
EDIT: Following on from Steve's suggestion my code now looks like this:
public class CanLay extends Activity
{
Bitmap bm;
#Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.canlay);
InputStream is = getResources().openRawResource(R.drawable.ella);
bm = BitmapFactory.decodeStream(is);
SurfaceView sv;
SurfaceHolder sh;
Canvas can = null;
sv = (SurfaceView)findViewById(R.id.surview);
sh = sv.getHolder();
try
{
can = sh.lockCanvas(null);
synchronized(sh)
{
can.drawBitmap(bm, 0, 0, null);
}
}
finally
{
if (can != null)
{
sh.unlockCanvasAndPost(can);
}
}
}
}
The only problem now is that sh.lockCanvas(null); always returns null.
I don't know of any sample code, but you usually get a Canvas from a SurfaceView, which is a View like other widgets (eg, TextView and Button). I would try just laying out the SurfaceView along with the other elements of the layout. The your basic XML structure might look something like
<LinearLayout >
<TextView />
<Button />
<SurfaceView />
</LinearLayout>
EDIT:
To get the Canvas from SurfaceView, first get the SurfaceHolder, then lock the canvas, draw your stuff, and unlock the canvas to have it displayed. In code that normally looks like:
SurfaceHolder holder = surfaceView.getHolder();
Canvas c = null;
try {
c = holder.lockCanvas(null);
synchronized(holder) {
// draw here
// c.drawBitmap() or whatever
}
} finally {
if(c != null)
holder.unlockCanvasAndPost(c);
}
DOUBLE EDIT:
According to the docs, lockCanvas returns null when the surface isn't ready. When you're still in onCreate(), the surface is definitely not ready. The way you know a surface is ready is by handling a callback to SurfaceHolder.Callback.surfaceCreated(). (Games often use surfaceCreated() to know when to start running their non-event thread.)
I know this may sound like more and more stuff you have to do, but it's really not that bad. You can even do it inline with something like this:
void onCreate(Bundle savedInstanceState) {
// inflate the XML with setContentView(), create your Bitmap, etc
sv = (SurfaceView)findViewById(R.id.surview);
sv.addCallback(new SurfaceHolder.Callback() {
#Override
void surfaceCreated(SurfaceHolder holder) {
Canvas can;
try {
can = holder.lockCanvas(null);
synchronized(holder) {
can.drawBitmap(bm, 0, 0, null);
}
} finally {
if(can != null) {
holder.unlockCanvasAndPost(can);
}
}});
// the rest of onCreate()
}
I may have messed up some of the braces, but you get the idea. Overall, it might be easier to put your SurfaceHolder.Callback implementation in its own non-anoymous class since there are restrictions on being anonymous, but that's the way you know your SurfaceView is ready for business. And of course, it's good to implement SurfaceHolder.Callback.surfaceDestroyed() so that you know when SurfaceView is going out of business. (Games often use surfaceDestroyed() to know when to stop running their non-event thread!)

Categories