root 后的android 无线传屏(服务器端与客户端)

首先我得感谢我的大师兄以及我的师姐,还有网上的一个朋友,没有他们的帮忙我也做不出来。


进入正题吧,首先在android2.3.3/development里面新建一个文件夹(比如说test),然后在test里面建两个文件,Android.mk与screencap.cpp(截屏的一些基础知识请看我的博客 浅谈android截屏http://my.oschina.net/JumpLong/blog/75556

)

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <utils/Log.h>
#include <errno.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>

#include <binder/IMemory.h>
#include <surfaceflinger/ISurfaceComposer.h>

#include <SkImageEncoder.h>
#include <SkBitmap.h>
#include <SkStream.h>

using namespace android;


long getCurrentTime()
{

	struct timeval tv;
	gettimeofday(&tv,NULL);
	return tv.tv_sec * 1000 + tv.tv_usec / 1000 ;
}

long SocketPre,SocketAft,SocketTime;
long CapPre,CapAft,CapTime;
long SendPre,SendAft,SendTime;
long EncodePre,EncodeAft,EncodeTime;



int SetSockfd(char* strip,char* strport,int* psockfd)
{
	SocketPre = getCurrentTime();
	
	struct sockaddr_in server_addr;
	in_addr_t inaddrip;
        int portnumber;

	if((inaddrip=inet_addr(strip))==INADDR_NONE)
        {
                fprintf(stderr,"ip Error!\n");
		LOGD("ip error!");
                return -1;
        }

        if((portnumber=atoi(strport))<0)
        {
                fprintf(stderr,"portnumber Error\n");
		LOGD("port error!");
                return -1;
        }

	/* 客户程序开始建立 sockfd描述符  */
        if((*psockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
        {
                fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));
		LOGD("socketcreate error!");
                return -1;
        }

        /* 客户程序填充服务端的资料       */
        bzero(&server_addr,sizeof(server_addr));
        server_addr.sin_family=AF_INET;
        server_addr.sin_port=htons(portnumber);
	server_addr.sin_addr.s_addr=inaddrip;
        /* 客户程序发起连接请求         */
        if(connect(*psockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
        {
                fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));
		LOGD("connect error!");
                return -1;
        }

	SocketAft = getCurrentTime();
	SocketTime = SocketAft - SocketPre;

	return 0; 
}

char* CapScreen(int* len)
{

	

	const String16 name("SurfaceFlinger");
	sp<ISurfaceComposer> composer;
	getService(name, &composer);

	sp<IMemoryHeap> heap;
	uint32_t w, h;
	PixelFormat f;

	EncodePre = getCurrentTime();
	status_t err = composer->captureScreen(0, &heap, &w, &h, &f, 0, 0);
	if (err != NO_ERROR) {
		fprintf(stderr, "screen capture failed: %s\n", strerror(-err));
		return NULL;
	}
		EncodeAft = getCurrentTime();

		EncodeTime = EncodeAft - EncodePre;
	printf("screen capture success: w=%u, h=%u, pixels=%p,heapsize = %zu,heapsize = %zx\n",w, h, heap->getBase() ,heap->getSize(),heap->getSize());

	SkBitmap b;
	b.setConfig(SkBitmap::kARGB_8888_Config, w, h);
	b.setPixels(heap->getBase());
	printf("size = %ld\n",sizeof(b));

	CapPre = getCurrentTime();


	SkDynamicMemoryWStream stream;
	SkImageEncoder::EncodeStream(&stream, b,SkImageEncoder::kJPEG_Type,SkImageEncoder::kDefaultQuality);

	*len=stream.getOffset();

        char* buffer=new char[*len];
	
	memcpy(buffer,stream.getStream(),*len);

	CapAft = getCurrentTime();
	CapTime = CapAft - CapPre;

	return buffer;

}


int SendScreen(int sockfd)
{	
	SendPre = getCurrentTime();

        int jpglong;
	char* jpgbuffer=CapScreen(&jpglong);
	if(jpgbuffer==NULL){
		printf("CapScreen failed!\n");
		return -1;
	}
	//加jpg头和长度
	printf("screen size  is %d byte\n",jpglong);
	char* pbuffer=new char[jpglong+6];
	pbuffer[0]='\r';
	pbuffer[1]='\n';
	memcpy(pbuffer+2,&jpglong,sizeof(int));	
	memcpy(pbuffer+6,jpgbuffer,jpglong);
	delete jpgbuffer;


	if(send(sockfd,pbuffer,jpglong+6,0)<0)  
	{  
		LOGD("send error");
		printf("send error closed!\n");

		delete pbuffer;
		return -1; 
	} 

	SendAft = getCurrentTime();
	SendTime = SendAft - SendPre;

	delete pbuffer;
	return 0;
	
}




int main(int argc, char** argv)
{


	if(argc != 3)
	{
                fprintf(stderr,"Usage:%s ip portnumber\a\n",argv[0]);
                exit(1);

	}

	int sockfd;

	if(SetSockfd(argv[1],argv[2],&sockfd)==-1)
	{
		fprintf(stderr,"setsockfd failed!\n");
		exit(1);
		
	}

        while(true)
	{
		long pre = getCurrentTime();


		if(SendScreen(sockfd)!=0){
			printf("SendScreen failed!\n");
			close(sockfd);
       			return -1;
					
		}
		
		long aft = getCurrentTime();

		long useTime = aft - pre;

		printf("total %ld,setsocket %ld,cap %ld,send %ld,encode %ld\n",useTime,SocketTime,CapTime,SendTime,EncodeTime);

		


	}

    

	close(sockfd);
	return 0;
}

这里面主要是调用了screencap那个文件夹里面的screencap.cpp里面的截屏方法,然后加上了socket传输,getCurrentTime只是我用来测试截屏,传输,解码的所用时间的。这个程序运行的话需要三个参数,第一个参数就是执行嘛,第二个就是服务器的IP,第三个就是服务器的端口号。等下再说。。。。

大家都知道要想图片流畅,那么每秒显示的图片数量得有24幅,但是这个目前只能达到5幅,因为它截屏大概是60ms,但是编码得需要大概120ms,也就是平均得要0.2s,如果做成多线程的话,也就是说利用生产者与消费者的模式,生产者负责capture,消费者负责encode,那样的话至少每秒会产生10幅图片(尚未解决,求高手指点)


Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	screencap.cpp

LOCAL_SHARED_LIBRARIES := \
	libcutils \
	libutils \
	libbinder \
	libskia \
    libui \
    libsurfaceflinger_client

LOCAL_MODULE:= whilecap

LOCAL_MODULE_TAGS := tests

LOCAL_C_INCLUDES += \
	external/skia/include/core \
	external/skia/include/effects \
	external/skia/include/images \
	external/skia/src/ports \
	external/skia/include/utils

include $(BUILD_EXECUTABLE)
有了这两个文件后,进入终端,转到test目录,然后mm,没错的话就会出现

Install: out/target/product/generic/system/bin/whilecap

然后将这个whilecap push到已经root的手机里面,注意不要随便放在一个文件里面,sdcard就不行,可以放在system里面,但是在push到system的时候会提示read-only system,这个时候就需要一下几步:adb shell ->su ->mount -o rw,remount -t ext3 /dev/block/mmcblk1p21 /system,然后再次adb push whilecap /system (当然这是你的whilecap已经被你移到home文件夹的情况下)。

现在假设服务器程序已经安装了,那么你怎么去执行呢?adb shell -> /system/whilecap 192.168.0.*** ****    这就是前面说的三个参数,第二个是IP,第三个是port。

当然我们想的不是每次都要去用命令行去执行,多麻烦,于是有了下一步的使用java去调用命令行语句。


public static int RunRootCommand(String paramString)
    {
      int i = 0;
      Process localProcess = null;
      try
      {
        localProcess = Runtime.getRuntime().exec("su");
        OutputStreamWriter localOutputStreamWriter = new OutputStreamWriter(localProcess.getOutputStream(), "UTF-8");
       // localOutputStreamWriter.write("export LD_LIBRARY_PATH=endorb:/systemb\n");
        //localOutputStreamWriter.flush();
        localOutputStreamWriter.write(paramString + "\n");
        localOutputStreamWriter.flush();
        localOutputStreamWriter.write("exit\n");
        localOutputStreamWriter.flush();
        localOutputStreamWriter.close();
        localProcess.waitFor();
        int j = localProcess.exitValue();
        if (j == 0)
          i = 1;
        try
        {
          localProcess.destroy();
          return i;
        }
        catch (Exception localException4)
        {
      	  System.out.println(localException4.getMessage());
          while (true)
            localException4.printStackTrace();
        }
      }
      catch (Exception localException2)
      {
      	System.out.println(localException2.getMessage());
        while (true)
        {
          localException2.printStackTrace();
          try
          {
            localProcess.destroy();
          }
          catch (Exception localException3)
          {
            localException3.printStackTrace();
          }
        }
      }
      finally
      {
      }

    }

新建一个android程序,在mainActivity中调用此函数,传送的字符串参数就是我们刚才使用的三个参数合在一起的结果,比如

RunRootCommand("/system/whilecap  192.168.0.100  7787");


这样,客户端的程序就完成了。

下面是服务器端的程序,分为两个,一个是android版本的,一个是java project。

android版本:

package com.example.jumplong;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.Toast;

public class TCA extends Activity {
	/** Called when the activity is first created. */
	Boolean state = false;
	Bitmap bitmap = null;
	ImageView iv = null;
	Thread severThread;
	static Handler mHandler;
	long pre,aft;
	int photo;
	static ServerSocket ss = null;
	static Socket cs = null;
	static InputStream in = null;
	static DataInputStream din = null;
	static CriticQueue cq;
	static imgReceiver ir;
	static imgShower is;
	static Thread tir;
	static Thread tis;
	static AtomicInteger imgCount;
	

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu, menu);
		return true;
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
		case R.id.start:
			Log.e("tc"," current Time ��"+new Date( System.currentTimeMillis()));
			start();
			return true;
		case R.id.stop:
			stop();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private void start() {		
		Log.e("tc", "enter the TCLCA start()");		
		state = true;
		iv = (ImageView) findViewById(R.id.showPhoto);
		//bitmap
		severThread = new Thread(new ServeThread()," ServeThread() ");
		severThread.start();
	}

	private void stop() {
		// TODO Auto-generated method stub
		state = false;
		
		try {
			ss.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		aft = System.currentTimeMillis();
		
		Toast.makeText(getApplicationContext(), "photo " + photo + " time " + ( aft - pre ), Toast.LENGTH_SHORT).show();
		
		// android.os.Process.killProcess((int)Thread.getId());
		finish();
		// ActivityManager manager =
		// (ActivityManager)getSystemService(ACTIVITY_SERVICE);
		// manager.killBackgroundProcesses(getPackageName());

	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		
		 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
				    WindowManager.LayoutParams.FLAG_FULLSCREEN);  
				 // 去除标题栏 
				 requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.main);
		
		
		
		
	}

	class ServeThread implements Runnable {
		
		public ServeThread() {
			mHandler = new Handler() {
				public void handleMessage(Message msg) {
					switch (msg.what) {
					case 1:
						iv.setImageBitmap(bitmap); // ��ImageView����ʾBitmap
						Log.e("tc", "setImageBitmap sucess");
						break;
					default:
						break;
					}
					super.handleMessage(msg);
				}
			};
		}
		
		@Override
		public void run() {
			try {
				ss = new ServerSocket(12345);
			} catch (IOException e) {
				Log.e("tc", "get the ServerSocket(54321) failed ");
			}				
				imgCount = new AtomicInteger();// 0

				while (true) {
					try {
						cs = ss.accept();
						
						pre = System.currentTimeMillis();

						
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					try {
						in = cs.getInputStream();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					din = new DataInputStream(in);
					cq = new CriticQueue();
					ir = new imgReceiver(cq);
					is = new imgShower(cq);
					tir = new Thread(ir, "thread-p");
					tis = new Thread(is, "thread-c");
					tir.start();
					tis.start();			
				}
		}//run end
	
	}// class ServeThread end

	class imgInfo {
		private byte[] imglocation;
		public void setimglocation(byte[] imgloc) {
			this.imglocation = imgloc;
		}
	}

	class CriticQueue {
		ArrayList<imgInfo> imgInfos = new ArrayList<imgInfo>();

		public void produce(imgInfo imginfo) {
			if (imgInfos.add(imginfo)){
				imgCount.incrementAndGet();
			}
		}// produce end

		public synchronized void consume() throws IOException {
			while (imgInfos.size() == 0) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}			
			imgInfo img = imgInfos.get(0);
			imgInfos.remove(0);

			// first stage			
			bitmap = BitmapFactory.decodeByteArray(img.imglocation, 0,img.imglocation.length);
			photo++;
			Message amessage = new Message();
			amessage.what = 1;
			mHandler.sendMessage(amessage);

			img = null;
			imgCount.decrementAndGet();
		}
	}

	class imgReceiver extends Thread {
		private CriticQueue imgReceiver_crique;
		boolean streamIsEnd = false;

		imgReceiver(CriticQueue q) {
			this.imgReceiver_crique = q;
		}

		public void run() {
			try {
				// search for mark of the image
				int s0 = 0;
				int s1 = 0;
				int imgsize = 0;
				int inter = 0;
				byte[] len = new byte[4];
				
				while ( !streamIsEnd  ) {
					// search for 13
					s0 = din.read();
					while (s0 == -1) {
						s0 = din.read();
					}
					while (s0 != 13) {
						s0 = din.read();
					}

					if (din.read() == 10) {
						try {
							s1 = din.read();
							while ((s1 != -1) && (inter < 4)) {
								len[inter] = (byte) s1;
								inter++;
								s1 = din.read();
							}
							if (inter == 4) {
								imgsize = (len[0] & 0xff)
										| ((len[1] << 8) & 0xff00)
										| ((len[2] << 24) >>> 8)
										| (len[3] << 24);
								inter=0;
							}else{
								streamIsEnd = true;
							}
							if (!streamIsEnd) {
								byte[] img = new byte[imgsize];
								int readonce = 0;
								int totalread = 0;
								img[0] = (byte) s1;
								totalread++;

								while (totalread != imgsize) {
									readonce = din.read(img, totalread, imgsize
											- totalread);
									if (readonce == -1) {
										streamIsEnd = true;
										break;
									}
									totalread += readonce;
									if (totalread == imgsize) {
										break;
									}
								}
								if (!streamIsEnd) {
									imgInfo message = new imgInfo();
									message.setimglocation(img);
									imgReceiver_crique.produce(message);
								} else {
									din.close();
									in.close();
									cs.close();
									while (imgCount.get() > 0) {
									}
									streamIsEnd = true;
								}
							} else {
								din.close();
								in.close();
								cs.close();
								while (imgCount.get() > 0) {
								}
								streamIsEnd = true;
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}// if 10 end
				}// while( !streamIsEnd ) end
			} catch (SocketException e) {
				try {
					din.close();
					in.close();
					cs.close();
					while (imgCount.get() > 0) {
					}
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}// run end
		

	}// imgReceiver end

	class imgShower extends Thread {

		private CriticQueue imgShower_crique = null;
		imgShower(CriticQueue q) {
			this.imgShower_crique = q;
		}
		public void run() {
			while (true) {
				if (state == true) {
					while (imgCount.get() < 1) {}
					try {
						imgShower_crique.consume();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}						
	}// imgShower end

}// class TCA end


main.XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    

    <ImageView
        android:id="@+id/showPhoto"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />
    
</LinearLayout>

最后添加权限

<uses-permission android:name ="android.permission.ACCESS_WIFI_STATE"/>
            <uses-permission android:name ="android.permission.CHANGE_WIFI_STATE"/>
            <uses-permission android:name ="android.permission.CHANGE_NETWORK_STATE"/>
            <uses-permission android:name ="android.permission.ACCESS_NETWORK_STATE"/>
            <uses-permission android:name="android.permission.INTERNET" />

然后java project版本:

package com.jump.screencapclient;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;





public class test{
	static JFrame frame = new JFrame();
	final static JFrame win = new JFrame("JumpLong"); ;
	static Graphics g;
	Image img;
	
	static long pre ;
	long aft;
	static int photo;
	
	static Boolean state = false;
	static ServeThread severThread;
	static ServerSocket ss = null;
	static Socket cs = null;
	static InputStream in = null;
	static DataInputStream din = null;
	static CriticQueue cq;
	static imgReceiver ir;
	static imgShower is;
	static Thread tir;
	static Thread tis;
	static AtomicInteger imgCount;
	static BufferedImage image;
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Container contentPane;

		
		
		win.setSize(480,900);
		
		win.setVisible(true);
		win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//關閉

		g = win.getGraphics();
		
		severThread = new ServeThread("tcl capture");
		
		Thread t = new Thread(severThread);
		
		t.start();

		
	}
	

	

	

	public static class ServeThread implements Runnable {
        String name;
		public ServeThread(String name){

            this.name =  name;

    }
		
		@Override
		public void run() {
			
			
			System.out.println("run");
			try {
				ss = new ServerSocket(12345);
				
				System.out.println("open the socket   ");
				
			} catch (IOException e) {
				System.out.println("get the ServerSocket(54321) failed ");
			}				
				imgCount = new AtomicInteger();// 0

				while (true) {
					try {
						cs = ss.accept();
						
						pre = System.currentTimeMillis();
						
						System.out.println("accept   ");
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					try {
						in = cs.getInputStream();
						
						
						System.out.println("get the inputstream   ");
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					din = new DataInputStream(in);
					System.out.println("after din   ");
					
					cq = new CriticQueue();
					System.out.println("after cq");
					
					ir = new imgReceiver(cq);
					System.out.println("after ir   ");
					
					is = new imgShower(cq); 
					System.out.println("after is   ");
					
					tir = new Thread(ir, "thread-p");
					System.out.println("after tir   ");
					
					tis = new Thread(is, "thread-c");
					System.out.println("after tis   ");
					
					tir.start();
					System.out.println("after tir   ");
					
					tis.start();			
					System.out.println("after tis   ");
				}
		}//run end
	
	}// class ServeThread end

	
	
	
	public static class imgInfo {

		private byte[] imglocation;
		public void setimglocation(byte[] imgloc) {
			this.imglocation = imgloc;
		}
	}
	
	
	
	
	public static class CriticQueue {
		ArrayList<imgInfo> imgInfos = new ArrayList<imgInfo>();

		public void produce(imgInfo imginfo) {
			if (imgInfos.add(imginfo)){
				imgCount.incrementAndGet();
			}
		}// produce end
		
		public synchronized void consume() throws IOException {
			
			System.out.println("consume");
			while (imgInfos.size() == 0) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}			
			imgInfo img = imgInfos.get(0);
			imgInfos.remove(0);
			System.out.print("remove  ");
			// first stage			
			ByteArrayInputStream in = new ByteArrayInputStream(img.imglocation);    //将b作为输入流;
			image = ImageIO.read(in);     //将in作为输入流,读取图片存入image中,而这里in可以为ByteArrayInputStream();
			
			System.out.print("image  " + photo++ +"time " + ( System.currentTimeMillis()-pre ));
			
			g.drawImage(image,0,0, win);

//			JFrame frame = new JFrame();
//			frame.invalidate();
//			JLabel label = new JLabel(new ImageIcon(image));		
//			System.out.print("show the image  ");
//			frame.getContentPane().add(label, BorderLayout.CENTER);
//			frame.pack();
//			frame.setVisible(true); 
//			//�رմ���--�˳�����
//			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

			
			
			img = null;
			imgCount.decrementAndGet();
		}
	}
		

	
	public static class imgReceiver extends Thread {
		private CriticQueue imgReceiver_crique;
		boolean streamIsEnd = false;

		imgReceiver(CriticQueue q) {
			this.imgReceiver_crique = q;
		}

		public void run() {
			try {
				// search for mark of the image
				int s0 = 0;
				int s1 = 0;
				int imgsize = 0;
				int inter = 0;
				byte[] len = new byte[4];
				
				while ( !streamIsEnd  ) {
					// search for 13
					s0 = din.read();
					System.out.println("din.read()  ");
					while (s0 == -1) {
						s0 = din.read();
						System.out.println("s0 == -1");
					}
					while (s0 != 13) {
						s0 = din.read();
						System.out.println("s0 != 13  ");
					}

					if (din.read() == 10) {
						try {
							System.out.println("din.read() == 10");
							s1 = din.read();
							while ((s1 != -1) && (inter < 4)) {
								len[inter] = (byte) s1;
								inter++;
								s1 = din.read();
							}
							if (inter == 4) {
								imgsize = (len[0] & 0xff)
										| ((len[1] << 8) & 0xff00)
										| ((len[2] << 24) >>> 8)
										| (len[3] << 24);
								inter=0;
							}else{
								streamIsEnd = true;
								System.out.println("streamisend = true  ");
							}
							if (!streamIsEnd) {
								
								System.out.println("!streamisend");
								byte[] img = new byte[imgsize];
								int readonce = 0;
								int totalread = 0;
								img[0] = (byte) s1;
								totalread++;
								
								System.out.println("titalread = " + totalread);
								
								while (totalread != imgsize) {
									readonce = din.read(img, totalread, imgsize
											- totalread);
									if (readonce == -1) {
										streamIsEnd = true;
										break;
									}
									totalread += readonce;
									if (totalread == imgsize) {
										break;
									}
								}
								if (!streamIsEnd) {
									imgInfo message = new imgInfo();
									message.setimglocation(img);
									imgReceiver_crique.produce(message);
								} else {
									din.close();
									in.close();
									cs.close();
									while (imgCount.get() > 0) {
									}
									streamIsEnd = true;
									
									System.out.println("streamisend is true");
								}
							} else {
								din.close();
								in.close();
								cs.close();
								while (imgCount.get() > 0) {
									
									System.out.println("imgcount.get > 0    ");
									
								}
								streamIsEnd = true;
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}// if 10 end
				}// while( !streamIsEnd ) end
			} catch (SocketException e) {
				try {
					din.close();
					in.close();
					cs.close();
					while (imgCount.get() > 0) {
					}
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}// run end
		

	}// imgReceiver end

	public static class imgShower extends Thread {

		private CriticQueue imgShower_crique = null;
		imgShower(CriticQueue q) {
			this.imgShower_crique = q;
		}
		public void run() {
			while (true) {
				
				System.out.println("imgshower run while(true)   ");
				
				if (!state) {
					System.out.println("state == true   ");
					
					
					while (imgCount.get() < 1) {}
					try {
						System.out.println("imgcount.get() < 1     ");
						
						System.out.println("imgshower try function");
						imgShower_crique.consume();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}						
	}// imgShower end
	
	
	
	
	
	
}


现在客户端与服务器端都写好,运行的步骤就是:

1:打开服务器程序:java project的话就直接运行,android project的话就是运行后点击手机的菜单按钮,就会出现两个按钮,点击左边的开启服务器端(端口号目前设置的是12345,假设服务器的IP地址是192.168.0.100)

2:运行客户端程序:你可以在android程序中添加一个editview来接受我们要传给RunRootCommand函数的参数,这个自己去写就是了,最终达到的效果就是如下

RunRootCommand("/system/whilecap  192.168.0.100  12345");

3:结束:点击服务器端的关闭服务器端,此时不再传送图片,但是客户端程序还在运行,需要去任务管理器中强行结束。因为此程序还没有优化,只是一个雏形。

到此,android的无线传屏就搞定了。

最后,还是希望大家帮帮忙,怎么去提升性能,怎么尽可能地增加每秒截取(截取与编码)的图片。










转载于:https://my.oschina.net/JumpLong/blog/146045

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值