Server以字节数组的形式将图像发送到我的android应用程序。在循环中,每个接收到的字节数组都被转换为位图,以显示在ImageView中。问题是,我的安卓设备(vince(在一段时间后(比如2-3分钟(会发出OutOfMemoryError
。模拟器也是如此。有什么方法可以避免这个错误吗?此外,我已将largeHeap设置为真正的
日志:
2020-03-31 20:39:28.040 30083-30158/com.rollout.pcremoteclient E/AndroidRuntime: FATAL EXCEPTION: Thread-2
Process: com.rollout.pcremoteclient, PID: 30083
java.lang.OutOfMemoryError: Failed to allocate a 153632 byte allocation with 105792 free bytes and 103KB until OOM, target footprint 536870912, growth limit 536870912
at java.lang.reflect.Array.newArray(Array.java:782)
at java.lang.reflect.Array.newInstance(Array.java:78)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1769)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1406)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:427)
at com.rollout.pcremoteclient.MainActivity$1.run(MainActivity.java:30)
MainActivity.java:
package com.rollout.pcremoteclient;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.logging.SocketHandler;
public class MainActivity extends AppCompatActivity {
ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
Thread thread = new Thread(){
@Override
public void run(){
try {
Socket socket = new Socket("192.168.43.191",6777);
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
while (true) {
final byte[] image_bytearr = (byte[])objectInputStream.readObject();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
final Bitmap bmp = BitmapFactory.decodeByteArray(image_bytearr, 0, image_bytearr.length, options);
runOnUiThread(new Runnable() {
@Override
public void run() {
imageView.setImageBitmap(bmp);
}
});
}
}catch (Exception e){
e.printStackTrace();
}
}
};
thread.start();
}
public void init(){
imageView = (ImageView) findViewById(R.id.imageView);
}
}
服务器端:
robot = new Robot();
rectangle = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
while (true) {
BufferedImage bufferedImage = robot.createScreenCapture(rectangle);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream);
byte[] image_byte_arr = byteArrayOutputStream.toByteArray();
objectOutputStream.writeObject(image_byte_arr);
}
你能做的最好的事情就是减少服务器端的图像,因为android有一个内存ram的限制,可以给每个应用程序,无论你的设备有9gb的ram,例如,操作系统根据设备屏幕分辨率给你最大的内存量。
但是,为了减少本地内存使用量(但你仍然可以获得OutOfMemoryError
(,在解析后压缩本地图像,并将这些图像转换为Webp格式,以进一步减小图像的最终大小,这些问题是处理图像的时间
转换为Webp(谷歌图像格式(并压缩
Bitmap bitmap;
String fileUrl;
//Get your file URL
//fileUrl
bitmap = BitmapFactory.decodeStream(fileUrl, null, null);
FileOutputStream out = this.openFileOutput(Utils.getFilenameFromUrl(Utils.getFilenameFromUrl(preview)), Context.MODE_PRIVATE);
bitmap.compress(Bitmap.CompressFormat.WEBP, 50, out);
此外,在AndroidManifest.xml
中,打开大型堆用法,将android:largeHeap="true"
添加到<application>
标签