最近在开发同屏,做了个Dome,记录下成果!
首先是web端和服务器端,这里我使用node.js来做的
服务端:service.js
var http = require('http'); var sio = require('socket.io'); var fs = require('fs'); var server = http.createServer(function(req,res){ res.writeHead(200, { 'Content-type':'text/html' } ); res.end(fs.readFileSync('./main.html')); }); server.listen(8083); var socket = sio.listen(server); var webs = socket; socket.on('connection',function(socket){ console.log("Connection..."); setTimeout(function(){ socket.emit('news',{shuju:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMkAAAArCAYAAADSSqyMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTMyIDc5LjE1OTI4NCwgMjAxNi8wNC8xOS0xMzoxMzo0MCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDphZjg5Njc3Mi01MWVhLTUxNDUtOTBiNS00YmI5M2I5MWEyZDYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjBCRTQyNDlDQTg2MTFFNkExQjlGQzgwNDkwMzhDMTMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjBCRTQyNDhDQTg2MTFFNkExQjlGQzgwNDkwMzhDMTMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUuNSAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOmEzM2Y2NjI4LTljMWUtNDBkZC05MWE4LWZjZDVlZmI0ZDNjNyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDphZjg5Njc3Mi01MWVhLTUxNDUtOTBiNS00YmI5M2I5MWEyZDYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5nk1vKAAANoklEQVR42uxdC5RVVRneDMggMNEgWIiC8dB4agkCKiDNECQEAsKQSlqtjJVPCjKi4qEGghJgYGAEBoIMT4EwYFCxkEIGFZUwQwJBFARBCARmnPa37rfX3RzOuWef15w70/3X+tc5c+bsffbe53///z63SllZmdDheP48kYEMOMBXJU6X2FXiSYl/lPgziWcqywRzioacd62azX2XSZwq8QaJtSWelfiOxDES18Q4/gKJ+RKbSsyV+F+JeyRu4YsrydBwpFBH4gsSGyh6kni/xBoSh1bmiVfRNYnUIvfJw28lZjncv4GEWp7QXuJkMq0T7JQ4XuKfMrQcGdwq8Rmb6yVkoJMxju1T0uwIiU+GrUmyNAb5HjVIVoo+8iT+rRwn30viKhcGUWbALIm/zNByZJDrcL0amSRWK0liLYnZUXSeRQbBcYZhm+sl3lwOE29OM+pLhvdnk0luTTPi+qbEDyS+L/ELFZhJNqfQ4gcqs3RQWmMobUtTGFMOYxsnsbHHNtl0JKuk0RrXpB1/qYuWTnfYJvEJyzX4qz+s7CpUvbSeHts1jXhcX5HYz2fbqwzMswz4g2ES12l/Dy1n8ztWJvFqBlSNeFx9AtqXfTP0HAmUShxEjXKXSISAKz2oEPAukYh9pwu0Dtj+igw9RwbHJN73/zRhpUlmeGz3ecTjahOwfa0MLWcgVCbJKRpSLBIJQ68aKAqoLrFVwD4+zrzaDIStSQDdRCKLbUrIUUFnkcj0B4FNmVebgbB9EmiTA8fz57WQp2+LRHImFSDEWi8iid0uYHuEJZd7bNNEYheRSEpeRCGALO5uiW9I/KuoRPVJMQrkjiKRZ2vLNUfA6FSI5vsDEgfbXK8qzk8LnJb4kcTX+X5fZmDifGK3KXCsR8K4xGVA2YaEA+Lrx3vniETyKRU8LfG7ARbqdxLvNXxpSDyOlNjS5V68yNkSJ0jcn+K+MRJHB3zRKMH5aYD2CMuq0gwkY+8J0Fd3cW7I1woICU8xEMSIhCHR2yCNmfgg5zJFKoxTbkyiCKiIJpgd/EvilYam03MiWdKwm5IkVYZ2q8RrfE4UzI0cyQmX+zD2RSKRU1FQRsnyAbURxtxYnBuKhvQZQUYsi4hJwISXBmj/kkhGKvHiv+wwVhOYSQL3yyT1RaIoVrcOUOu1iz7w0QBj0+EOHl+VuMOwDYI7jUgD+jvG++8nGWWLG5MoQKjvcYujjom1dpGoClaI83MWD0qcmGLghyRe6GOhkNTqz/apoCfHpRbmXWoIMPNhBxPhRxJv13y45VTrVk16NVGHr2ua7W7hXAgIxniI54juveVjDepy/rqvifH/w6d5dIh9ruD66MxT3YVJalPgXakJsLESn5f4WchaoMyDZrMzxXqQLrtoJnsvySjrTaJU00Sisna4SNRSbaIUNbEhexCt0DxFm5t8MAgIdRwJvdTlXtRRrebClFArPJGiHeb5CvFRiYUiEXmD+biMAkBv+zpRWISKYpIF/NuJKLHOddivHybpozHIGRJyP59M0oEMApjENVBgkjIYqzHIYyTCqFMHfqCU2m4Nze85XLeVUmG0lYzyrkkt0VHakwVkGpOJdqM9bFcPhsreyxza3eZDe0BSP2LAIE2oAapSmneh1Ck1fNYOmoFrtHk8HOLL+lwLOAz22Ydq957EhTy/3WdfA3g8IvHvHtvivf+Y50UURunIIFZYQEFayjk8LUT4BXeoDp5P1exU3wXnbQkjHAqgPWYJ83IS+A7fJ6G/bdgG46rJlwWTa7OP+Z2mZN6smY7Xhrh+y3hs7cMvQaQoT3vZi3neUPhLziqGW+yDwLtoAnJcRQrBSc2xUTN7O0ltcl0YTHINJfKblITQBm4h5GsZdlvPNpDSJtWk0AC/ock2x4PTB+btxPPRfLZfgBlzi0jklKrQ/AwLisiIQnivP7tJM58L2dcpi1YwhTZkLqExmxdormnHzaLiwePa2t0WhEkQUVhLP+V+4b3eCpIvnwR8ucu9GDA2hDWTOArxBY/PUhGnfSmCBl4AEZBf8bw9I3ZhAOapQq4FHtuqfTR7KLBO0+H2Y8b25xFRwo0+5lFPm0+F21YttQnm/Rf+me+VSSCpfs5Q21zab9kRjhfRlV8zVIdEkZ/NPS20iNMEEV5ScKZIhpp/EOKcl/AIxvuiYZsLtSCJvsVWaYFmLgETJ4Zb5pPIP9LGlSMqJmzl8XJTJsF9IxlxwV7ydhEPELVkd5E5YB8GyeyrfSkltNXDgpOac9xfhLfRazXNlCyaUKamVnWLXyMoDU97NLngS15hYVivsEmjm19UUCY5yGN1EyaBWbWNvoBbAhGEiD0GyJjfTZ/DFPbTFGpFJnxKhBNP76Ex3ichL+QqHuuI4EWZwiaaNNCwzSBtDYst5ttqi3Yw8d8E136dzzm8qZlpsDwmC3+5rzihRNcQTvA1SiI4yFcZ2tNdaXogIzmD5tgwl3bIK/Sm1nhQmGdMTUGZWi9EsJCvWNYrLFjEY08Dcxb//zbP59v8f7HmjDfyYGr9WdNCfgB+0Ic8Bw3spTXSsKKplCyHa0gebaAUNjUjHrUQjQJEvl5MYVp05AuJIo5eSyR3Xb4TQf+HtSBCkxD7VdlthFHzXO7N16T0Upv/Y23PWrSEEzTQmH1xwDlAqyGH9bLmzMMaeZ+aBrmtbwhv31aIn0mO58/rSEJH5jfXY1+pFnWFzbWjNMtMpFVnLjqcbuyMG2U4pvraeVR7TI7YPCsoIEK10xJpcoKBmg291eb/eqTGLbHYl0LxLJkrKBygdQFhi7B7GftvTV9lA98nTLMRZNCstGUSySAIOa4UiXIEr3BCpK7uLba5NtvQR7iT0ghVyRdQMzxMonDbd6JHhz6JaA1Vv7VD7vdZjUmcCKea5pA/I5zzRkqAwde7OMUzB2um6YkQ5wLfBglGVFogXbBWJPMQ1fm/ifR9EdHEBxJbphWTSAa5gT6EX2n4mou5tImOuAIsxnjDvv+QQktACnVz8ZMUROU41uTxbMj9Ku2bS5PUDrpqzFmYoq+VdEQhxfulECideb4worWCNTCNvhaEHehuDDWgoh/UiyHcj0gqInWN04JJRKIYrW6AfkwK6BDSbUqV2l6cX3FrB7BXq7qMH1LP6cMEn2rndSNaw9yINNUbmuPrlH0v0EzJVO/gmBa4cEpS9uZ6glhXlVP0aBNpD/SgCjsLKXAUQ++g7xIfk0gt0ttFGptAseF97zGaZeqkm9431UEzIamlChgviWD9qmlMsj+C/gstZpBVQNyiRcPKDPvq6uBvDtK0/pEYaPEENV4BI2BTOSdoapTXt4mNSSTeKIInwoojGp+X7Dji8ffYMNkunrePYHwtRLJe6q0I+ldVwY34LB2u14h9kWFfKknZ2/I/PWO/QMQPh2hy5VOrwG+ZGSeTBP1GFcyMf0c4Ri8716bZXHuJx+4RjC1PY8ZXI+gfESEVYraGb5UWOSLMPnxxRCTDsd+x/K8HCRFr/VwaBZZgIqoauU7CLM8TCZNcEIIWKUuTRYVGnGS59jyPiOp0CPl5qnBwq8X/CQtKaYJYTa4q2t+LPJilSuPki3OjcQO1d5luH79+Vju/Oi4m+TBNTS2/MMCGSdSnkh4I8TlIlKkatrkRzkclCNtqflV7kQzlLvXQ1zIKNAjGb/EazvvYEGS6gC58cuJiku0B+3gxzRbV+lsZSFZO15zTtiE9Z5LmcEb5G3prRTK8rKJcKsF4TDMnTQC5JVUXVqA58kqrLElDJtEDLh/HxSRLA5hLhz2+JD/gtVzFLhT7GLUJ5rtQBP+4HnZFqrDkIyLcxJsVUG28wWIWqcx5oTDffqxA5UBQOZyt+TYIte5JQybppfmmr8XCJDlFQ1B45vdn1MaLYEVwJrDX4/2zHaIlqtCyJSM4fr+Mf6MWaUE92GSX+/WE5sU+n6nCt0j2IQHX0HLdq/kGgkNEq6fGeAvSkEGwhXmU5vcdjEuTAH4ivEeoEHmYUg5j9LL1tFQ4Z/Kf0mzuAXSIvf6M2SCaP9WomWD+uIWpd2vnnX2uwWoSNp77e83M87NrELsqt/Ece3Xq+vBtygPg7yFqpwpUR8Y1EPXBbIQHUda+07DdRtrFpeUwRqhY04pUt2JA7I1Zo5kb+ObWEOH+aSXso0GeYRFNNZhAecKsshgf8tvHc1RK+ymphyZUIeZWGlH7LYVRJpdK0P3Hw7uPCrLpL+K3O9dxvirkO1ozOWPTJGCU3eTesXQInRw/fIIzP8U9UQAk+CwXDdJXJMOlTnCGkRxlItWnqYl5zRWJZOTNROyrwJc+iklAKk+xi9ElL9+yGs7jRZTipdREOu5z6cOaMAwSibIKnfk++5lIgREU8V6wyQulONi0113zx+4QMX9xxekLjjVoGoCzcyjJtlP9xfn9pBok6i6UPMe4qH4W8TqR+NKJqWQHIU9gEMDPjklEk6aTUZz6T1VJ3EQkqwdwb64IVlS5XdMk7YS3UD6eXzNiPxSFrU8aRrSCfMHxHFA/US354E6R2HDoaGaACNYLb9tvywM+E8kao6CAfTPIdXSgmQZzs6lIxuJLaL9D7aPgb4kw/2kKJ02wnI53MxsicwuAoO5tKB3uvSJ41fG9FBBnhfdc13AR/gdAsL8I0bV/Cu+5u2GaGxAWbFH9/k+AAQAlSCdTUUkVKgAAAABJRU5ErkJggg=='}); },1000); setTimeout(function(){ socket.emit('news',{shuju:'data:image/jpeg;base64,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'}); },3000); socket.on('users',function(data){ console.log(data) if(data=="web"){ webs = socket; } }); socket.on('data',function(data){ console.log("data is OK.."); webs.emit('news',{shuju:data}); }); })web端接收图片显示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>MAIN</title> </head> <body> <img id="imgs" style="width:100%" src=""/> </body> <script src="http://abcwhatsappad.com:8080/wa/dist/easyui/jquery.min.js"></script> <script src="http://cdn.bootcss.com/socket.io/1.7.3/socket.io.js"></script> <script> var socket = io.connect("ws://192.168.1.194:8083"); socket.emit("users","web"); socket.on('news',function(data){ $(function(){ $("#imgs").attr("src",data.shuju); }); }); </script> </html>
接下来是Android端,这里要求是在5.0以下版本上开发同屏功能,我找了好多网上案例,现在也只能做到截图传输,效果也不尽人意。
首先导入io.socket有关的jar包:engine.io-client-0.8.3.jar, okhttp-3.6.0.jar,okio-1.11.0.jar,socket.io-client-0.8.4-SNAPSHOT.jar
连接服务器:SocketStreamWork.java
public class SocketStreamWork implements Runnable { private static final String TAG = "Alin-SocketStreamWork"; private final static String SOCKET_SERVER_URL = "http://192.168.1.194:8083"; private static final String IMAGE_TITLE = "data:image/png;base64,"; private Socket mSocket; private boolean isConnected; private String result; public SocketStreamWork(String result) { this.result = result; } @Override public void run() { //建立Socket连接 Log.e(TAG, "run"); initSocketHttp(); connectSocket(); } private void initSocketHttp() { try { mSocket = IO.socket( SOCKET_SERVER_URL ); // 初始化Socket Log.e(TAG, "initSocketHttp"); } catch ( URISyntaxException e ) { e.printStackTrace(); } } private void connectSocket() { try { mSocket.connect(); mSocket.emit("data", IMAGE_TITLE + result); Log.e(TAG, "connectSocket"); } catch (Exception e ) { e.printStackTrace(); } mSocket.on( Socket.EVENT_CONNECT, onConnect );// 连接成功 mSocket.on( Socket.EVENT_DISCONNECT, onDisconnect );// 断开连接 mSocket.on( Socket.EVENT_CONNECT_ERROR, onConnectError );// 连接异常 mSocket.on( Socket.EVENT_CONNECT_TIMEOUT, onConnectTimeoutError );// 连接超时 mSocket.on( "data", onConnectMsg );// 监听消息事件回调 } private void disConnectSocket() { mSocket.disconnect(); mSocket.off( Socket.EVENT_CONNECT, onConnect );// 连接成功 mSocket.off( Socket.EVENT_DISCONNECT, onDisconnect );// 断开连接 mSocket.off( Socket.EVENT_CONNECT_ERROR, onConnectError );// 连接异常 mSocket.off( Socket.EVENT_CONNECT_TIMEOUT, onConnectTimeoutError );// 连接超时 mSocket.off( "data", onConnectMsg );// 监听消息事件回调 } private Emitter.Listener onConnectMsg = new Emitter.Listener() {// 监听消息事件回调 @Override public void call( final Object... args ) { // 在这里处理你的消息 Log.e( TAG, "服务器返回来的消息 : " + args[0] ); } }; /*实现消息回调接口*/ private Emitter.Listener onConnect = new Emitter.Listener() {// 连接成功 @Override public void call( final Object... args ) { Log.e( TAG, "连接成功 "); if (!isConnected) { // 如果已经断开,重新发送 /*try { mSocket.emit("data", result); } catch (Exception e ) { e.printStackTrace(); }*/ isConnected = true; } } }; private Emitter.Listener onDisconnect = new Emitter.Listener() {// 断开连接 @Override public void call( Object... args ) { Log.e( TAG, "断开连接 " + args[0] ); isConnected = false; } }; private Emitter.Listener onConnectError = new Emitter.Listener() {// 连接异常 @Override public void call( final Object... args ) { Log.e( TAG, "连接 失败" + args[0] ); } }; private Emitter.Listener onConnectTimeoutError = new Emitter.Listener() {// 连接超时 @Override public void call( final Object... args ) { Log.e( TAG, "连接 超时" + args[0] ); } }; }截取屏幕图片:ScreenUtil.java
这里使用的是adb截屏功能,截取的图片是保存在路径里的,要获取还是要用FileInputStream()方法获取
public class ScreentUtil {
private static final String TAG = "ScreentShotUtil"; private static final String CLASS1_NAME = "android.view.SurfaceControl"; private static final String CLASS2_NAME = "android.view.Surface"; private static final String METHOD_NAME = "screenshot"; private static ScreentUtil screentShotUtil; private Display mDisplay; private DisplayMetrics mDisplayMetrics; private Matrix mDisplayMatrix; private WindowManager wm; private SimpleDateFormat format; private static File outputImage = null; public static ScreentUtil getInstance(){ synchronized (ScreentUtil.class) { if (screentShotUtil == null){ screentShotUtil = new ScreentUtil(); } } return screentShotUtil; } private Bitmap screenShot(int width, int height){ Log.i(TAG, "android.os.Build.VERSION.SDK : " + android.os.Build.VERSION.SDK_INT); Class<?> surfaceClass = null; Method method = null; try{ Log.i(TAG, "width : " + width); Log.i(TAG, "height : " + height); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2){ surfaceClass = Class.forName(CLASS1_NAME); } else { surfaceClass = Class.forName(CLASS2_NAME); } method = surfaceClass.getDeclaredMethod(METHOD_NAME, new Class[]{int.class, int.class}); method.setAccessible(true); return (Bitmap) method.invoke(null, width, height); }catch (NoSuchMethodException e){ Log.e(TAG, e.toString()); }catch (IllegalArgumentException e){ Log.e(TAG, e.toString()); }catch (IllegalAccessException e){ Log.e(TAG, e.toString()); }catch (InvocationTargetException e){ Log.e(TAG, e.toString()); }catch (ClassNotFoundException e){ Log.e(TAG, e.toString()); } return null; } /** * Takes a screenshot of the current display and shows an animation. * @return */ @SuppressLint("NewApi") public Bitmap ScreenShot(Context context){ Bitmap mBitmap = null; if(outputImage == null){ format = new SimpleDateFormat("yyyyMMddHHmmss"); String fileName = format.format(new Date(System.currentTimeMillis())) + ".png"; File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); outputImage = new File(path, fileName); Log.e("Alin", "path : " + path + " , outputImage : " + outputImage); } if(ShellUtil.checkRootPermission()){ if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH){ ShellUtil.execCommand("/system/bin/screencap -p "+ outputImage, true); Log.d("Alin", "保存截图"); if(outputImage.exists()){ try { mBitmap = FileUtil.getInstance().getBitmapFromBytes(FileUtil.getInstance().readInputStream(new FileInputStream(outputImage)), null); } catch (Exception e) { e.printStackTrace(); } } } } else { if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH){ wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); mDisplay = wm.getDefaultDisplay(); mDisplayMatrix = new Matrix(); mDisplayMetrics = new DisplayMetrics(); // We need to orient the screenshot correctly (and the Surface api seems to take screenshots // only in the natural orientation of the device :!) mDisplay.getRealMetrics(mDisplayMetrics); float[] dims = { mDisplayMetrics.widthPixels/2, mDisplayMetrics.heightPixels/2 }; float degrees = getDegreesForRotation(mDisplay.getRotation()); boolean requiresRotation = (degrees > 0); if (requiresRotation){ // Get the dimensions of the device in its native orientation mDisplayMatrix.reset(); mDisplayMatrix.preRotate(-degrees); mDisplayMatrix.mapPoints(dims); dims[0] = Math.abs(dims[0]); dims[1] = Math.abs(dims[1]); } Bitmap mScreenBitmap = screenShot((int) dims[0], (int) dims[1]); if (requiresRotation){ // Rotate the screenshot to the current orientation Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels/2, mDisplayMetrics.heightPixels/2, Bitmap.Config.RGB_565); Canvas c = new Canvas(ss); c.translate(ss.getWidth() / 2, ss.getHeight() / 2); c.rotate(degrees); c.translate(-dims[0] / 2, -dims[1] / 2); c.drawBitmap(mScreenBitmap, 0, 0, null); c.setBitmap(null); mScreenBitmap = ss; if (ss != null && !ss.isRecycled()){ ss.recycle(); } } // If we couldn't take the screenshot, notify the user if (mScreenBitmap == null){ Toast.makeText(context, "Alin : screen shot fail", Toast.LENGTH_SHORT).show(); }else { // Optimizations mScreenBitmap.setHasAlpha(false); mScreenBitmap.prepareToDraw(); saveBitmap2file(context, mScreenBitmap, outputImage.toString()); } mBitmap = mScreenBitmap; } } return mBitmap; } public void saveBitmap2file(Context context, Bitmap bmp, String fileName){ //Log.e("Alin", bmp.getWidth()+"----------"+fileName); int quality = 100; ByteArrayOutputStream baos = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.JPEG, quality, baos); InputStream is = new ByteArrayInputStream(baos.toByteArray()); byte[] buffer = new byte[1024]; int len = 0; File file = new File(fileName); if (!file.exists()){ try{ file.getParentFile().mkdir(); file.getParentFile().createNewFile(); }catch (IOException e){ Log.e("Alin", e.toString()); } }else{ try{ file.getParentFile().delete(); file.getParentFile().createNewFile(); }catch (IOException e){ Log.e("Alin", e.toString()); } } FileOutputStream stream = null; try{ stream = new FileOutputStream(file); while ((len = is.read(buffer)) != -1){ stream.write(buffer, 0, len); } stream.flush(); }catch (FileNotFoundException e){ Log.i(TAG, e.toString()); }catch (IOException e){ Log.i(TAG, e.toString()); }finally{ if (is != null) { try{ is.close(); } catch (IOException e) { Log.i(TAG, e.toString()); } } if (stream != null){ try{ stream.close(); }catch (IOException e){ Log.i(TAG, e.toString()); } } } if (bmp != null && !bmp.isRecycled()){ bmp.recycle(); } } /** * @return the current display rotation in degrees */ private float getDegreesForRotation(int value){ switch (value){ case Surface.ROTATION_90: return 360f - 90f; case Surface.ROTATION_180: return 360f - 180f; case Surface.ROTATION_270: return 360f - 270f; } return 0f; } }adb shell命令文件ShellUtil.java
/** * ShellUtils * <ul> * <strong>Check root</strong> * <li>{@link ShellUtil#checkRootPermission()}</li> * </ul> * <ul> * <strong>Execte command</strong> * <li>{@link ShellUtil#execCommand(String, boolean)}</li> * <li>{@link ShellUtil#execCommand(String, boolean, boolean)}</li> * <li>{@link ShellUtil#execCommand(List, boolean)}</li> * <li>{@link ShellUtil#execCommand(List, boolean, boolean)}</li> * <li>{@link ShellUtil#execCommand(String[], boolean)}</li> * <li>{@link ShellUtil#execCommand(String[], boolean, boolean)}</li> * </ul> */ public class ShellUtil { public static final String COMMAND_SU = "su"; public static final String COMMAND_SH = "sh"; public static final String COMMAND_EXIT = "exit\n"; public static final String COMMAND_LINE_END = "\n"; private ShellUtil() { throw new AssertionError(); } /** * check whether has root permission * * @return */ public static boolean checkRootPermission() { return execCommand("echo root", true, false).result == 0; } /** * execute shell command, default return result msg * * @param command command * @param isRoot whether need to run with root * @return * @see ShellUtil#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String command, boolean isRoot) { return execCommand(new String[] {command}, isRoot, true); } /** * execute shell commands, default return result msg * * @param commands command list * @param isRoot whether need to run with root * @return * @see ShellUtil#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(List<String> commands, boolean isRoot) { return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, true); } /** * execute shell commands, default return result msg * * @param commands command array * @param isRoot whether need to run with root * @return * @see ShellUtil#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String[] commands, boolean isRoot) { return execCommand(commands, isRoot, true); } /** * execute shell command * * @param command command * @param isRoot whether need to run with root * @param isNeedResultMsg whether need result msg * @return * @see ShellUtil#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) { return execCommand(new String[] {command}, isRoot, isNeedResultMsg); } /** * execute shell commands * * @param commands command list * @param isRoot whether need to run with root * @param isNeedResultMsg whether need result msg * @return * @see ShellUtil#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(List<String> commands, boolean isRoot, boolean isNeedResultMsg) { return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, isNeedResultMsg); } /** * execute shell commands * * @param commands command array * @param isRoot whether need to run with root * @param isNeedResultMsg whether need result msg * @return <ul> * <li>if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and * {@link CommandResult#errorMsg} is null.</li> * <li>if {@link CommandResult#result} is -1, there maybe some excepiton.</li> * </ul> */ public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) { int result = -1; if (commands == null || commands.length == 0) { return new CommandResult(result, null, null); } Process process = null; BufferedReader successResult = null; BufferedReader errorResult = null; StringBuilder successMsg = null; StringBuilder errorMsg = null; DataOutputStream os = null; try { process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH); os = new DataOutputStream(process.getOutputStream()); for (String command : commands) { if (command == null) { continue; } // donnot use os.writeBytes(commmand), avoid chinese charset error os.write(command.getBytes()); os.writeBytes(COMMAND_LINE_END); os.flush(); } os.writeBytes(COMMAND_EXIT); os.flush(); result = process.waitFor(); // get command result if (isNeedResultMsg) { successMsg = new StringBuilder(); errorMsg = new StringBuilder(); successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); String s; while ((s = successResult.readLine()) != null) { successMsg.append(s); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s); } } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null) { os.close(); } if (successResult != null) { successResult.close(); } if (errorResult != null) { errorResult.close(); } } catch (IOException e) { e.printStackTrace(); } if (process != null) { process.destroy(); } } return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null : errorMsg.toString()); } /** * result of command * <ul> * <li>{@link CommandResult#result} means result of command, 0 means normal, else means error, same to excute in * linux shell</li> * <li>{@link CommandResult#successMsg} means success message of command result</li> * <li>{@link CommandResult#errorMsg} means error message of command result</li> * </ul> * * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16 */ public static class CommandResult { /** result of command **/ public int result; /** success message of command result **/ public String successMsg; /** error message of command result **/ public String errorMsg; public CommandResult(int result) { this.result = result; } public CommandResult(int result, String successMsg, String errorMsg) { this.result = result; this.successMsg = successMsg; this.errorMsg = errorMsg; } } }文件操作类FileUtil.java
public class FileUtil { private static FileUtil mFileUtil; public static FileUtil getInstance(){ synchronized (FileUtil.class) { if (mFileUtil == null){ mFileUtil = new FileUtil(); } } return mFileUtil; } /** * InputStream to byte * @param inStream * @return * @throws Exception */ public byte[] readInputStream(InputStream inStream) throws Exception { byte[] buffer = new byte[1024]; int len = -1; ByteArrayOutputStream outStream = new ByteArrayOutputStream(); while ((len = inStream.read(buffer)) != -1) { outStream.write(buffer, 0, len); } byte[] data = outStream.toByteArray(); outStream.close(); inStream.close(); return data; } /** * Byte to bitmap * @param bytes * @param opts * @return */ public Bitmap getBitmapFromBytes(byte[] bytes, BitmapFactory.Options opts) { if (bytes != null){ if (opts != null){ return BitmapFactory.decodeByteArray(bytes, 0, bytes.length,opts); } else{ return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); } } return null; } }使用Base64加密传输图片BitmapUtil.java
public class BitmapUtil { private static final String TAG = "Alin"; private static BitmapUtil mBitmapUtil; /** * bitmap转为base64 * @param bitmap * @return */ public static BitmapUtil getInstance(){ synchronized (BitmapUtil.class) { if (mBitmapUtil == null){ mBitmapUtil = new BitmapUtil(); } } return mBitmapUtil; } public String bitmapToBase64(Bitmap bitmap) { Log.d(TAG, "-----bitmapToBase64-----" + bitmap); String result = null; ByteArrayOutputStream baos = null; try { if (bitmap != null) { baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 40, baos); baos.flush(); baos.close(); byte[] bitmapBytes = baos.toByteArray(); result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (baos != null) { baos.flush(); baos.close(); } } catch (IOException e) { e.printStackTrace(); } } return result; } /** * base64转为bitmap * @param base64Data * @return */ public Bitmap base64ToBitmap(String base64Data) { Log.d(TAG, "-----base64ToBitmap-----" + (base64Data == null)); byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT); return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); } }最后我是用 service服务来运行的,这里就不在贴出来了。