I'm receiving URLs from server which should be translated to GIFs, These GIFs should animate whenever the user clicks on them or when receiving a response from any of the users, everything is working fine however when receiving lots of them I experience memory leakage, it doesn't go out of memory however the memory keeps increasing constantly and keeps facing hickups, please advise what can be done in order to avoid having them on the memory, I've tried initializing the animImageView with null however still the same attitude, please advise what can be done.
public void getGifts() {
Communicator.getInstance().on("sendGift", new Emitter.Listener() {
Animation anim;
EmojiModel emojiUrl = new EmojiModel();
String url = emojiUrl.getUrlFile();
#Override
public void call(Object... args) {
JSONDictionary response = (JSONDictionary) args[0];
url = (String) response.get("giftUrl");
Runnable runnable = new Runnable() {
#Override
public void run() {
animImageView = null;
animImageView = new ImageView(getApplicationContext());
animImageView.setVisibility(View.VISIBLE);
Glide.with(getApplicationContext())
.load(url)
.thumbnail(0.1f)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.crossFade()
.override(900,400)
.into(animImageView);
final RelativeLayout relativeLayout =
(RelativeLayout)findViewById(R.id.imageView_relative);
anim =
AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.move_to_right_anim);
relativeLayout.addView(animImageView);
animImageView.startAnimation(anim);
StreamActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
anim.setAnimationListener(new
Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
anim =AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.move_to_right_anim);
animImageView.startAnimation(anim);
}
#Override
public void onAnimationEnd(Animation animation) {
animImageView = null;
}
#Override
public void onAnimationRepeat(Animation animation) {
animImageView = null;
}
});
}
});
}
};
mhandler.post(runnable);
}
});
}
This has been resolved by adding relativeLayout.removeAllViewsInLayout(); before adding the view
Related
I am pretty new to Android studio, but so far, so good!
I have an android app which is up and running together with an websocket that is running on my computer.
So when both the websocket and the app is up and running.
I could write a message, which then gets printed in the websocket terminal, and the websocket also return an message which get printed on the list on my phone. Also, if the websocket receive a special message from the app, the webscocket also return a special message which is shown on and added on the list! Perfect! Isnt it?
Now what I am trying to do is that, the app listens to a special message/event from the websocket which in this case is "SuperSpecialMessage". If the websocket sends this specific message, the application is
going to react and do something. In this case make an Invisible buttong to be visible.
SO WHAT IS THE PROBLEM? The problem here is that I get the error:
"android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."
Could someone help me please?
Here is my code:
public class WebSocketActivity extends AppCompatActivity {
private Socket mSocket;
private TextView mSocketStatus;
EditText messageTextview;
ListView the_list_view_on_layout;
ArrayAdapter arrayAdapter;
String TheMessages;
List<String> list_with_messages;
Button theExtraButton;
Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_websocket);
this.mHandler = new Handler();
m_Runnable.run();
// Elements that are created on the layout
mSocketStatus = (TextView)findViewById(R.id.socketStatus);
theExtraButton = (Button)findViewById(R.id.extraBtn);
theExtraButton.setVisibility(View.INVISIBLE);
the_list_view_on_layout = findViewById(R.id.listViewID);
messageTextview = findViewById(R.id.messageTextView);
String[] TheMessages = new String[]{};
list_with_messages = new ArrayList<String>(Arrays.asList(TheMessages));
//ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list_with_messages);
arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list_with_messages);
the_list_view_on_layout.setAdapter(arrayAdapter);
TheSocketClass app = (TheSocketClass) getApplication();
mSocket = app.getSocket();
mSocket.connect();
checkIfConnectedToSocket();
Button sendMessageToSocketServer = (Button) findViewById(R.id.sendMessageToSocketBtn);
sendMessageToSocketServer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String theTextWeWrite = messageTextview.getText().toString();
mSocket.emit("sendTextToServer", theTextWeWrite);
list_with_messages.add(theTextWeWrite);
//arrayAdapter.notifyDataSetChanged();
}
});
runOnUiThread(new Runnable() {
#Override
public void run() {
mSocket.on("ServerMessage", new Emitter.Listener() {
#Override
public void call(Object... args) {
JSONObject data = (JSONObject) args[0];
list_with_messages.add(data.toString());
//arrayAdapter.notifyDataSetChanged(); // I GET ERROR HERE
}
});
}
});
runOnUiThread(new Runnable() {
#Override
public void run() {
mSocket.on("SuperSpecialMessage", new Emitter.Listener() {
#Override
public void call(Object... args) {
theExtraButton.setVisibility(View.VISIBLE);
}
});
}
});
}
private void checkIfConnectedToSocket(){
mSocket.connect();
if (mSocket.connected() == true) {
mSocketStatus.setText("Connected to socket!");
mSocketStatus.setTextColor(Color.GREEN);
}
else if (!mSocket.connected()){
mSocketStatus.setText("Error connecting to socket!");
mSocketStatus.setTextColor(Color.RED);
}
}
}
Thank you.
EDIT: Solved!
First i made an method like this:
private void makeTheButtonVisible(){
runOnUiThread(new Runnable() {
#Override
public void run() {
theExtraButton.setVisibility(View.VISIBLE);
}
});
}
and when the app recieve the message, the method is called like this:
runOnUiThread(new Runnable() {
#Override
public void run() {
mSocket.on("SuperSpecialMessage", new Emitter.Listener() {
#Override
public void call(Object... args) {
makeTheButtonVisible();
}
});
}
});
When the ImagePager load first time, some times, Picasso call onError, showing the .error drawable. If I press on back button and go back to the Activity that has the ImagePager, Picasso load the picture correctly. If the ImagePager has two or more pictures and I swipe between the pictures, those are loaded correctly some times without exit and reenter to the ImagePager.
It correctly downloads other images from web. The issue arises when I tried to download from hosted company server.
I am using Picasso 'com.squareup.picasso:picasso:2.5.0'.
I also referred to below question but it doesn't help.
First time error loading picture with Picasso
Below is my MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
configureToolbar(R.string.select_task);
init();
}
#Override
protected void init() {
//TODO: For QA Testing Purpose, Remove after Testing
mWidthField =findViewById(R.id.edt_txt_1);
mHeightField =findViewById(R.id.edt_txt_2);
mImage=findViewById(R.id.image_view_2);
mImageLoadButton=findViewById(R.id.image_load_button);
item=new Item();
item.setPrimaryImageURL("https://cdn.cnn.com/cnnnext/dam/assets/190119161516-01-trump-government-shutdown-0119-exlarge-169.jpg");
item.setUpc("0001111086751");
Log.d("ImageManager","Main Activity");
new ImageManager(getApplicationContext()).downloadImage(item.getPrimaryImageURL(),item.getUpc()+".jpeg",imageDownloadedCallBack);
mImageLoadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loadResizedImage();
}
});
}
//TODO: For QA Testing Purpose, Remove after Testing
ImageManager.ImageDownloadedCallBack imageDownloadedCallBack=new ImageManager.ImageDownloadedCallBack() {
#Override
public void imageDownloadComplete(final Bitmap bitmap, boolean status) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d("ImageManager","Image Download CallBack in Main Activity");
mImage.setImageBitmap(bitmap);
}
});
}
};
Below is my ImageManager.java
public class ImageManager {
private final Context mContext;
private int mWidth;
private int mHeight;
public ImageManager(Context mContext){
this.mContext=mContext;
}
public interface ImageDownloadedCallBack {
void imageDownloadComplete(Bitmap bitmap,boolean status);
}
private Target picassoImageTarget(Context context, final String imageDir, final String imageName,final ImageDownloadedCallBack imageDownloadedCallBack) {
ContextWrapper cw = new ContextWrapper(context);
final File directory = cw.getDir(imageDir, Context.MODE_PRIVATE); // path to /data/data/yourapp/app_imageDir
return new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
Thread thread=new Thread(new Runnable() {
#Override
public void run() {
final File myImageFile = new File(directory, imageName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myImageFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
Log.d("ImageManager","Image DownLoad CallBack");
imageDownloadedCallBack.imageDownloadComplete(bitmap,true);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
thread.start();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.d("ImageManager","Bitmap Failure");
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
if (placeHolderDrawable != null) {}
}
};
}
public void downloadImage(String url, String id,ImageDownloadedCallBack imageDownloadedCallBack){
// this.imageDownloadedCallBack=imageDownloadedCallBack;
Log.d("ImageManager","Download Image function");
Picasso.with(mContext).load(url).into(picassoImageTarget(mContext,"imageDir", id ,imageDownloadedCallBack));
}
}
Any help would be appreciated.
I found the answer from old post and I implemented this code in MainActivity. And now it is working good.
final Target target = new Target{...};
imageView.setTag(target);
Refer wrb-answer below for the above code:
wrb-answer
I have a method that takes 4 second to execute, if the user calls it again before it ended than it will refresh, I want to only start the new one after the last one has finished, putting them in a queue.
I've read the documentation, but I still don't know how to implement it, can someone provide an example please?
Code
my method:
public void popClassAdded(int amount){
classAddedText.setText(getString(R.string.you_earned) + amount + " ");
setIn = new AnimatorSet();
setIn.playTogether(
Glider.glide(Skill.QuintEaseOut, 200, ObjectAnimator.ofFloat(classAddedLayout, "translationY", -50, 165))
);
setIn.setDuration(1200);
classAddedLayout.setVisibility(View.VISIBLE);
setIn.start();
classAddedLayout.postDelayed(new Runnable(){
public void run(){
AnimatorSet set = new AnimatorSet();
set.playTogether(Glider.glide(Skill.CubicEaseInOut, 200, ObjectAnimator.ofFloat(classAddedLayout, "translationY", 165, -50)));
set.setDuration(1200);
set.start();
set.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) { }
#Override
public void onAnimationEnd(Animator animation) {
classAddedLayout.setVisibility(View.GONE);
}
#Override
public void onAnimationCancel(Animator animation) { }
#Override
public void onAnimationRepeat(Animator animation) { }
});
}
},2000);
shopPrefs.edit().putInt("coins", amount + shopPrefs.getInt("coins", 0)).apply();
}
Calling it:
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//may get clicked more than once in an interval or 4 seconds
((Activity_Main)getActivity()).popClassAdded(100);
}
});
Alright so I am working on an app that has to take pictures and send them to a server for processing. I need this for some image recognition that will eventually help control a robot. Basically I need to use the android device as a webcam that sends pictures. I figured out the Sockets part but now after fiddling with some code for a few days I ended up with this:
public class MainActivity extends AppCompatActivity {
public static final String dTag = "DBG";
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button trg = (Button)findViewById(R.id.trigger_btn);
trg.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View v)
{
SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
#Override
public void addCallback(Callback callback) {
}
#Override
public void removeCallback(Callback callback) {
}
#Override
public boolean isCreating() {
return false;
}
#Override
public void setType(int type) {
}
#Override
public void setFixedSize(int width, int height) {
}
#Override
public void setSizeFromLayout() {
}
#Override
public void setFormat(int format) {
}
#Override
public void setKeepScreenOn(boolean screenOn) {
}
#Override
public Canvas lockCanvas() {
return null;
}
#Override
public Canvas lockCanvas(Rect dirty) {
return null;
}
#Override
public void unlockCanvasAndPost(Canvas canvas) {
}
#Override
public Rect getSurfaceFrame() {
return null;
}
#Override
public Surface getSurface() {
return null;
}
};
Camera.PictureCallback mCall = new Camera.PictureCallback()
{
#Override
public void onPictureTaken(byte[] data, Camera camera)
{
ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
ImageView imW = (ImageView)findViewById(R.id.imView);
imW.setImageBitmap(bitmap);
Log.d(dTag, "" + data.length);
}
};
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Camera mCamera;
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay();
mCamera.startPreview();
}
catch(IOException e){
Log.d(dTag, "Cam is null!");
}
mCamera.takePicture(null, null, mCall);
mCamera.stopPreview();
mCamera.release();
}
});
}
Now whenever I press the button I see this in the debug log "D/Camera: app passed NULL surface", I assume this is because of mSurfaceHolder which isn't properly declared. If anyone could point to me what the problem is and how to solve it I would be grateful since I don't have a very good understanding of java and can't seem to find anything that works on the internet.
several problems -
You have no surface view and surface holder must be obtained from the surface view. You just can not create a "new" for this purpose.
You did not pass any surfaceolder in mCamera.setPreviewDisplay(); so system can not decide where to display.
Your method local anonymous inner class is just simply wrong.
Tutorial link: http://examples.javacodegeeks.com/android/core/ui/surfaceview/android-surfaceview-example/
I have already a rough idea about how to do this and I think it is by making 2 or more animation set per Image View or Text View but the code would be to long. Is there a way in which I could minimize the codes? Here is the code for every Image View and Text View:
AnimationSet setA = new AnimationSet(true);
fadeIn1.setDuration(1000);
setA.addAnimation(fadeIn1);
TranslateAnimation Trans1 = new TranslateAnimation(270, 0, 0, 0);
Trans1.setDuration(1000);
setA.addAnimation(Trans1);
ImageView1.startAnimation(setA);
//how do i place delay here??
ImageView2.startAnimation(setA);
//how do i place delay here??
TextView1.startAnimation(setA);
//how do i place delay here??
TextView2.startAnimation(setA);
//how do i place delay here??
setA.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
ImageView1.clearAnimation();
ImageView2.clearAnimation();
TextView1.clearAnimation();
TextView2.clearAnimation();
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
You can make delay by using handlers..
eg:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
ImageView1.startAnimation(setA);
}
}, 2000);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
ImageView2.startAnimation(setA);
}
}, 4000);