首先我得感谢我的大师兄以及我的师姐,还有网上的一个朋友,没有他们的帮忙我也做不出来。
进入正题吧,首先在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的无线传屏就搞定了。
最后,还是希望大家帮帮忙,怎么去提升性能,怎么尽可能地增加每秒截取(截取与编码)的图片。