我是 android Surfaceview 实现的新手。我正在android3.0 中开发RDP 客户端应用程序。我从套接字获取图像流,使用 Surfaceview 和 Thread 将此图像绘制到表面。
表面视图示例代码:
class mySurfaceView extends SurfaceView implements SurfaceHolder.Callback
{
private TutorialThread _thread;
Canvas c=null;
public mySurfaceView(Context context)
{
super(context);
getHolder().addCallback(this);
_thread = new TutorialThread(getHolder(), this);
matrix= new Matrix();
m = new float[9];
paint = new Paint();
}
public void surfaceCreated(SurfaceHolder arg0) {
//setWillNotDraw(false) ;
Log.e("surfaceCreated","surfaceCreated");
if(_thread==null ){
Log.e("_thread.created","thread created");
_thread = new TutorialThread(getHolder(),this);
_thread.setRunning(true);
_thread.start();
// <-- added fix
}else {
Log.e("_thread.getState()",_thread.getState()+"");
_thread.setRunning(true); //original code
_thread.start(); //original code
}
}
public void surfaceDestroyed(SurfaceHolder arg0) {
Log.e("surfaceDestroyed","surfaceDestroyed");
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
}
class TutorialThread extends Thread
{
private SurfaceHolder _surfaceHolder;
private mySurfaceView _panel;
private boolean _run = false;
private InputStream is;
private Socket socket;
Bitmap resizeBmp;
public TutorialThread(SurfaceHolder surfaceHolder,mySurfaceView panel)
{
Log.e("TutorialThread","TutorialThread-->Constructor");
_surfaceHolder = surfaceHolder;
_panel = panel;
}
public void setRunning(boolean run) {
_run = run;
}
@Override
public void run()
{
Log.e("TutorialThread","TutorialThread-->run()");
try
{
socket = new Socket("172.19.1.144", 4444);
is = socket.getInputStream();
DataInputStream inputputStream = new DataInputStream(is);
//long time = System.currentTimeMillis();
int i=0;
while (socket.isConnected() )
{
Log.e("tutorial thread","While running");
c = null;
i++;
if(i==10){
System.gc();
i=0;
}
Log.e("BEFORE","BEFORE");
synchronized (_surfaceHolder)
{
Log.e("AFTER","AFTER");
ByteBuffer inputHeaderBuffer = ByteBuffer.allocate(20);
inputHeaderBuffer.order(ByteOrder.LITTLE_ENDIAN);
inputputStream.readFully(inputHeaderBuffer.array());
SurfaceViewPinchZoom.serverWidth=inputHeaderBuffer.getInt();
SurfaceViewPinchZoom.serverHeight=inputHeaderBuffer.getInt();
//Log.e("serverWidth","serverWidth "+ SurfaceViewPinchZoom.serverWidth+"serverHeight===="+SurfaceViewPinchZoom.serverHeight);
SurfaceViewPinchZoom.left=inputHeaderBuffer.getInt();
SurfaceViewPinchZoom.top=inputHeaderBuffer.getInt();
int dataLength = inputHeaderBuffer.getInt();
ByteBuffer imageDataCompress = ByteBuffer.allocate(dataLength);
imageDataCompress.order(ByteOrder.LITTLE_ENDIAN);
inputputStream.readFully(imageDataCompress.array());
byte[] imagedata = new byte[imageDataCompress.remaining()];
imageDataCompress.get(imagedata);
//Decompress the image
//Log.e("imagedata.length::::::::::",imagedata.length+"");
// Create the decompressor and give it the data to compress
Inflater decompressor = new Inflater();
decompressor.setInput(imagedata);
// Create an expandable byte array to hold the decompressed data
ByteArrayOutputStream bos = new ByteArrayOutputStream(imagedata.length);
// Decompress the data
byte[] buf = new byte[1024];
while (!decompressor.finished()) {
try {
int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
} catch (DataFormatException e) {
}
}
try {
bos.close();
} catch (IOException e) {
}
// Get the decompressed data
byte[] decompressedData = bos.toByteArray();
/
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
// Log.e("decompressedData.length::::::::::",decompressedData.length+"");
/*SurfaceViewPinchZoom.*/bmp = BitmapFactory.decodeByteArray(decompressedData, 0,decompressedData.length,options);
options.inDither=true;
/*scaleX=(float)screen_width/bmp.getWidth();
scaleY=(float)screen_height/bmp.getHeight();
matrix.setScale(scaleX, scaleY);*/
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, screen_width, screen_height);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
/*SurfaceViewPinchZoom.*/bmp= BitmapFactory.decodeByteArray(decompressedData, 0,decompressedData.length,options);
bmp=BitmapFactory.decodeByteArray(decompressedData, 0,decompressedData.length,options);
c = _surfaceHolder.lockCanvas();
c.drawBitmap(bmp, matrix, paint);
//draw(c);
//postInvalidate();
onDraw(c);
inputHeaderBuffer.clear();
imageDataCompress.clear();
inputHeaderBuffer = null;
imageDataCompress = null;
imagedata = null;
}
if (c != null)
{
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
catch (ArrayIndexOutOfBoundsException ae)
{
ae.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
finally {
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
private int calculateInSampleSize(Options options, int screen_width,
int screen_height) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > screen_height || width > screen_width) {
if (width > height) {
inSampleSize = Math.round((float)height / (float)screen_height);
} else {
inSampleSize = Math.round((float)width / (float)screen_width);
}
}
return inSampleSize;
}
}
}
问题是
1)如果我按下主页按钮然后surfaceDestroyed()
被调用thread
并被终止。
但是在按下从主页按钮打开应用程序后,我需要继续线程并更新图像(来自套接字的输入流)。
2)如果我将事件上的doubletap
活动称为子活动,surfaceDestroyed()
则调用Thread
并终止。
从子活动返回后,我需要在哪里继续显示图像。
在这两种情况下,由于线程已经启动,我都遇到了异常。java.lang.IllegalThreadStateException:
请帮助如何在不按下主页按钮或调用另一个子活动的情况下运行相同的线程?
感谢和问候亚米尼