精华内容
下载资源
问答
  • 我是qt新手, 要从一个手机传输文件到另一个手机,请教看哪些方面的内容? 有哪些好的参考资料
  • 我想做这样一个APP, A手机有这款APP通过连接B手机WIFI热点,相互传递手机里面的一些电影,音乐文件,或者只获取B手机的里面的一些电影,音乐文件. 有没有人知道怎么做,或者有类似的Demo.求解答,或者发份类似的Demo给我!...
  • 船 :ship: Ship是一个命令行应用程序,可以轻松地将... 将网址复制到另一个设备浏览器(可以是电话或计算机)中。 Make sure to click ' ctrl-c ' to kill after usage Mon Jul 6 22:37:27 2020 Sharing Server Start
  • 我个人先去大概了解了一下音视频的一些基本概念,然后做了一个小demo,实现了一台手机录制,另一手机实时播放。视屏录制采用的Camera,预览用的SurfaceView,把采集的视频压缩成bitmap,通过socket进行传输到另外一...

    最近无聊,做一下android音视频方面的学习和研究。网上有很多案例值得我们去学习。我个人先去大概了解了一下音视频的一些基本概念,然后做了一个小demo,实现了一台手机录制,另一台手机实时播放。视屏录制采用的Camera,预览用的SurfaceView,把采集的视频压缩成bitmap,通过socket进行传输到另外一台手机上。这个demo只是用来学习android Camera,bitmap传输比较耗流量,所以该demo仅供学习。

    视频采集客户端:
    录制页面activity

    package com.fm.camero;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.List;
    
    import com.fangming.myframwork.R;
    import com.fm.qxtapp.MyApp;
    
    import android.content.Intent;
    import android.content.res.Configuration;
    import android.graphics.ImageFormat;
    import android.graphics.Rect;
    import android.graphics.YuvImage;
    import android.hardware.Camera;
    import android.hardware.Camera.PreviewCallback;
    import android.hardware.Camera.Size;
    import android.os.Bundle;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    import android.view.SurfaceHolder.Callback;
    import android.view.View.OnClickListener;
    import android.view.Window;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageView;
    
    /**
     * @describe 视频录制成图片压缩socket传输
     * @author fangming
     * @CreateTime 2016年8月16日下午2:32:41
     */
    public class TestcamoraActivety2 extends ServiceActivity implements Callback, PreviewCallback {
    
        private TestcamoraActivety2 _this;
        private String TAG = TestcamoraActivety2.class.getSimpleName();
        private Button btn_start;
        private SurfaceView sf_surfaceView;
        private SurfaceHolder suHolder;
        private int width;// 分辨率宽度
        private int height;// 分辨率高度
        private Camera mCamera;
        private boolean isStreaming = false;
        private MyApp myApp;
        private Button btn_puse;
        private ImageView iv_show;
        private Boolean isShow = true;
        int mwidth, mheight;
        private Button btn_switch;
        private Button btn_conn;
        private Button btn_disconn;
        private EditText et_ip;
        private EditText et_port;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_testcamora);
            _this = this;
            initView();
            myApp = MyApp.getInstance();
        }
    
        private void initSurfaceholder() {
            suHolder = sf_surfaceView.getHolder();
            suHolder.addCallback(this);
            // width = 352;
            // height = 288;
            width = 320;
            height = 480;
            mwidth = width;
            mheight = height;
            System.out.println("*****相机初始化完成*****");
        }
    
        private void initView() {
            btn_start = (Button) findViewById(R.id.btn_start);
            btn_puse = (Button) findViewById(R.id.btn_puse);
            iv_show = (ImageView) findViewById(R.id.iv_show);
            sf_surfaceView = (SurfaceView) findViewById(R.id.sf_surfaceView);
            initSurfaceholder();
            btn_start.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    mCamera.startPreview();
                    // new DumpFrameTask().execute();
                }
            });
            btn_puse.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    mCamera.stopPreview();
                }
            });
            btn_switch = (Button) findViewById(R.id.btn_switch);
            btn_switch.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
    
                }
            });
    
            btn_conn = (Button) findViewById(R.id.btn_conn);
            btn_disconn = (Button) findViewById(R.id.btn_disconn);
            et_ip = (EditText) findViewById(R.id.et_ip);
            et_port = (EditText) findViewById(R.id.et_port);
            btn_conn.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    ip = et_ip.getText().toString();
                    port = et_port.getText().toString();
                    bindMyService();
                }
            });
            btn_disconn.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    unBindMyService();
                }
            });
    
        }
    
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            isStreaming = true;
            System.out.println("*****相机采集到的数组长度" + data.length + "*****");
            if (isShow) {
                mwidth = camera.getParameters().getPreviewSize().width;
                mheight = camera.getParameters().getPreviewSize().height;
                isShow = false;
            }
            YuvImage image = new YuvImage(data, ImageFormat.NV21, mwidth, height, null);
            if (image != null) {
                ByteArrayOutputStream outstream = new ByteArrayOutputStream();
                image.compressToJpeg(new Rect(0, 0, mwidth, height), 80, outstream);
    
                byte[] arr=outstream.toByteArray();
    //          Bitmap bitmap =BitmapFactory.decodeByteArray(arr,0, arr.length);
    //          iv_show.setRotation(90);
    //          iv_show.setImageBitmap(bitmap);
    
                mService.sendDate(arr);
                try {
                    outstream.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            mCamera = Camera.open();
            try {
                mCamera.setPreviewDisplay(suHolder);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            mCamera.setPreviewCallback(this);
            List<Size> previewSizes = mCamera.getParameters().getSupportedPreviewSizes();
            width = previewSizes.get(0).width;
            height = previewSizes.get(0).height;
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setPreviewSize(width, height);
            // 横竖屏镜头自动调整
            if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
                parameters.set("orientation", "portrait"); //
                parameters.set("rotation", 90); // 镜头角度转90度(默认摄像头是横拍)
                mCamera.setDisplayOrientation(90); // 在2.2以上可以使用
            } else// 如果是横屏
            {
                parameters.set("orientation", "landscape"); //
                mCamera.setDisplayOrientation(0); // 在2.2以上可以使用
            }
            System.out.println("*****surfaceCreated*****");
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            System.out.println("*****系统执行surfaceChanged*****");
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            System.out.println("*****surfaceDestroyed*****");
            if (mCamera != null) {
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unBindMyService();
        };
    
        @Override
        public void finish() {
            super.finish();
            Intent mintent = new Intent();
            mintent.setAction(ConnectionService.ACTION);
            stopService(mintent);
        }
    }
    

    该activity布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <SurfaceView
            android:id="@+id/sf_surfaceView"
            android:layout_width="match_parent"
            android:layout_height="300dp" />
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >
    
            <Button
                android:id="@+id/btn_start"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="start" />
    
            <Button
                android:id="@+id/btn_puse"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="暂停" />
    
            <Button
                android:id="@+id/btn_switch"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="转码" />
    
            <Button
                android:id="@+id/btn_conn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="connect" />
    
            <Button
                android:id="@+id/btn_disconn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="disconnect" />
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
    
            <EditText
                android:id="@+id/et_ip"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="192.168.1.108" />
    
            <EditText
                android:id="@+id/et_port"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="6001" />
        </LinearLayout>
    
        <ImageView
            android:id="@+id/iv_show"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:src="@drawable/ic_launcher" />
    
    </LinearLayout>

    在这个录制中,遇到的几个比较坑的地方,第一个是视频的宽和高,没有设置好,播放时会导致黑屏或者花屏。还有就是对于camera采集的视频格式的一些问题。默认是ImageFormat.NV21,也就是YUV420sp。

    // yuv420P(YV12)或者yuv420SP(NV21/NV12)
    parameters.setPreviewFormat(ImageFormat.NV21);

    我们采集的视频最后通过onPreviewFrame这个回调接口获得

        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            isStreaming = true;
            System.out.println("*****相机采集到的数组长度" + data.length + "*****");
            if (isShow) {
                mwidth = camera.getParameters().getPreviewSize().width;
                mheight = camera.getParameters().getPreviewSize().height;
                isShow = false;
            }
            YuvImage image = new YuvImage(data, ImageFormat.NV21, mwidth, height, null);
            if (image != null) {
                ByteArrayOutputStream outstream = new ByteArrayOutputStream();
                image.compressToJpeg(new Rect(0, 0, mwidth, height), 80, outstream);
    
                byte[] arr=outstream.toByteArray();
    //          Bitmap bitmap =BitmapFactory.decodeByteArray(arr,0, arr.length);
    //          iv_show.setRotation(90);
    //          iv_show.setImageBitmap(bitmap);
                //视频发送
                mService.sendDate(arr);
                try {
                    outstream.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    采集到的视频通过mService.sendDate(arr);进行发送。mService是我自己定义的一个service用来后台处理数据。

    ConnectionService类

    package com.fm.camero;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.net.SocketException;
    
    import com.fm.constants.Constants;
    import com.fm.utill.ByteConvertUtils;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.util.Log;
    
    public class ConnectionService extends Service {
        public final static String ACTION = "com.connectionService";
        private final static int PACKATHEADER_SIGN_LENGTH = 2;// 我的包标识
        private final static int PACKATHEADER_TYPE_LENGTH = 4;// 包类型 4byte
        private final static int PACKATHEADER_DATALEN_LENGTH = 4;// 包长度 4byte
        private final static int PACKATHEADER_LENGTH = PACKATHEADER_SIGN_LENGTH + PACKATHEADER_TYPE_LENGTH
                + PACKATHEADER_DATALEN_LENGTH;// 包头
        private String ipAdd = "192.168.1.109";
        private int port = 6001;
        private String TAG = "ConnectionService";
        private Socket mSocket;
        private OutputStream outStream;
        private InputStream inStream;
        private InitSocketThread initSocketThread;
        private Boolean isAccepte = true;
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.e(TAG, "---->" + "onCreateservice");
        }
    
        @Override
        public void onDestroy() {
            Log.e(TAG, "---->service停止");
            super.onDestroy();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.e(TAG, "---->" + "onStartCommand");
            return super.onStartCommand(intent, flags, startId);
        }
    
        /**
         * 初始化socket线程
         */
        class InitSocketThread extends Thread {
    
            @Override
            public void run() {
                super.run();
                initSocket();
            }
        }
    
        /**
         * 初始化socket
         */
        private synchronized void initSocket() {
            Log.e(TAG, "---->创建socket成功");
            try {
                mSocket = new Socket(ipAdd, port);
                if (mSocket.isConnected()) {
                    Log.e(TAG, "---->连接成功");
                    outStream = mSocket.getOutputStream();
                    inStream = mSocket.getInputStream();
                }
            } catch (SocketException e) {
                Log.d(TAG, "socket conn fail");
                e.printStackTrace();
            } catch (IOException e) {
                Log.d(TAG, "socket conn fail");
                e.printStackTrace();
            }
        }
    
        public class MyBinder extends Binder {
    
            public ConnectionService getService() {
                return ConnectionService.this;
            }
        }
    
        public MyBinder mBinder = new MyBinder();
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        public void sendDate(byte[] data) {
            int datalength = data.length;
            byte[] buffer = new byte[PACKATHEADER_LENGTH + datalength];
            // 设置包头3000
            System.arraycopy(Constants.APPREQUEST_HEAD, 0, buffer, 0, 2);
            // 设置type
            byte[] type = { 0, 0, 0x26, (byte) 0x48 };
            System.arraycopy(type, 0, buffer, 2, 4);
            // 设置长度
            byte[] len = ByteConvertUtils.intToBytes(datalength);
            System.arraycopy(len, 0, buffer, 6, 4);
            // 设置内容
            System.arraycopy(data, 0, buffer, 10, datalength);
            new sendDataThread(buffer).start();
        }
    
        public class sendDataThread extends Thread {
            byte byteBuffer[] = null;
    
            public sendDataThread(byte[] data) {
                this.byteBuffer = data;
            }
    
            public void run() {
                try {
                    outStream.write(byteBuffer, 0, byteBuffer.length);
                    System.out.println("发送的数据长度:" + byteBuffer.length);
                    outStream.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public void setIpAndPort(String ip, String port) {
            if (ip != null && !ip.equals("")) {
                ipAdd = ip;
            }
            if (port != null && !port.equals("")) {
                this.port = Integer.valueOf(port);
            }
            if (initSocketThread == null) {
                initSocketThread = new InitSocketThread();
                initSocketThread.start();
            }
        }
    
    }
    

    以上就是客户端录制,下面是播放客户端

    播放端activity

    package com.fm.server;
    
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
        private MainActivity _this;
        private ImageView iv_btmap;
        private EditText et_port;
        private Button btn_bind;
        private Button btn_unbind;
        public String mPort;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            _this = this;
            initView();
        }
    
        private void initView() {
            iv_btmap = (ImageView) findViewById(R.id.iv_btmap);
            et_port = (EditText) findViewById(R.id.et_port);
            btn_bind = (Button) findViewById(R.id.btn_bind);
            btn_unbind = (Button) findViewById(R.id.btn_unbind);
            btn_bind.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    String port = et_port.getText().toString();
                    if (port == null || port.equals("")) {
                        Toast.makeText(_this, "端口为null", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    mPort = port;
                    bindService();
                }
            });
            btn_unbind.setOnClickListener(new OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    unBindService();
                }
            });
        }
    
        Handler mHandler = new Handler() {
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case 0:
                    byte[] data = (byte[]) msg.obj;
                    if (data == null) {
                        return;
                    }
                    System.out.println("handle收到的数据:" + data.length);
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inSampleSize = 2;
                    // Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
                    // data.length, options);
                    Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                    if (bitmap != null) {
                        iv_btmap.setRotation(90);
                        iv_btmap.setImageBitmap(bitmap);
                    }
                    break;
    
                default:
                    break;
                }
            };
        };
    
        @Override
        public void finish() {
            super.finish();
            if (mService != null) {
                unBindService();
            }
        }
    
        public void bindService() {
            Intent mintent = new Intent();
            mintent.setClass(_this, BindService.class);
            bindService(mintent, conn, Context.BIND_AUTO_CREATE);
        }
    
        public void unBindService() {
            if (mService != null) {
                unbindService(conn);
            }
        }
    
        public BindService mService = null;
    
        ServiceConnection conn = new ServiceConnection() {
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mService = null;
            }
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mService = ((BindService.MyBinder) service).getService();
                mService.startConn(mPort);
                mService.setHandler(mHandler);
            }
        };
    
    }
    

    播放端service

    
    package com.fm.server;
    
    import java.io.BufferedInputStream;
    import java.io.DataInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.SocketException;
    import java.util.Arrays;
    
    import com.fm.constants.Constants;
    import com.fm.utill.ByteConvertUtils;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.util.Log;
    
    public class BindService extends Service {
        private String TAG = "BindService";
        public int port = 6001;
        public OutputStream outStream;
        public InputStream inStream;
        public Socket mSocket;
        private InitSocketThread initSocketThread;
        private ReadThread readThread;
        private Boolean isAccepte = true;
        ServerSocket server;
        private final static int PACKATHEADER_SIGN_LENGTH = 2;// 我的包标识
        private final static int PACKATHEADER_TYPE_LENGTH = 4;// 包类型 4byte
        private final static int PACKATHEADER_DATALEN_LENGTH = 4;// 包长度 4byte
        private final static int PACKATHEADER_LENGTH = PACKATHEADER_SIGN_LENGTH + PACKATHEADER_TYPE_LENGTH
                + PACKATHEADER_DATALEN_LENGTH;// 包头
    
        public void setPort(int port) {
            this.port = port;
        }
    
        private Handler hander;
    
        public void setHandler(Handler hander) {
            this.hander = hander;
        }
    
        public void startConn(String port) {
            if (port != null && !port.equals("")) {
                this.port = Integer.valueOf(port);
            }
            initSocketThread = new InitSocketThread();
            initSocketThread.start();
        }
    
        /**
         * 初始化socket线程
         */
        class InitSocketThread extends Thread {
    
            @Override
            public void run() {
                super.run();
                initSocket();
            }
        }
    
        /**
         * 初始化socket
         */
        private void initSocket() {
            Log.e(TAG, "---->创建socket成功");
            try {
                server = new ServerSocket(port);
                mSocket = server.accept();
                if (mSocket.isConnected()) {
                    Log.e(TAG, "---->连接成功");
                    outStream = mSocket.getOutputStream();
                    inStream = mSocket.getInputStream();
                    readThread = new ReadThread();
                    readThread.start();
                }
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        class ReadThread extends Thread {
            @Override
            public void run() {
                super.run();
                while (isAccepte) {
                    if (mSocket != null && mSocket.isConnected()) {
                        devide(new DataInputStream(new BufferedInputStream(inStream)));
                    }
                }
            }
        }
    
        public synchronized void devide(DataInputStream ds) {
            try {
                if (ds.available() > 0) {
                    recv(ds);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public void recv(DataInputStream dis) throws IOException {
            byte[] head = new byte[PACKATHEADER_LENGTH];
            Log.e(TAG, "---->>接收数据的长度" + dis.available());
            try {
                dis.readFully(head, 0, PACKATHEADER_LENGTH);
            } catch (IOException e) {
                return;
            }
            // 读取前两个字节我的数据包标识head[]
            byte[] sign = new byte[2];
            sign = Arrays.copyOfRange(head, 0, 2);
            if (ByteConvertUtils.bytesToInt2(sign) != Constants.APP_CTL_HEAD) {
                return;
            }
            // 读取4byte包类型
            byte[] type = new byte[4];
            type = Arrays.copyOfRange(head, 2, 6);
            int nType = ByteConvertUtils.bytesToInt(type);
    
            // 读取4byte内容长度
            byte[] datalen = new byte[4];
            datalen = Arrays.copyOfRange(head, 6, 10);
            int nDatalen = ByteConvertUtils.bytesToInt(datalen);
            Log.e(TAG, "type:" + nType);
    
            switch (nType) {// App登陆/查询网关
            case Constants.VEDIO_STREAM:
                byte[] data = null;
                if (nDatalen > 0) {
                    // 接收指定长度的内容
                    data = new byte[nDatalen];
                    dis.readFully(data, 0, nDatalen);
                    Log.e(TAG, "len:" + nDatalen);
                    sendMessage(data);
                }
                break;
            default:
                Log.e(TAG, "---->不识别的命令");
                break;
            }
        };
    
        public void sendMessage(byte[] data) {
            Message msg = hander.obtainMessage();
            msg.what = 0;
            msg.obj = data;
            hander.sendMessage(msg);
        }
    
        @Override
        public void onCreate() {
            Log.e(TAG, "---->" + "onCreateservice");
            super.onCreate();
        }
    
        @Override
        public void onDestroy() {
            Log.e(TAG, "---->service停止");
            super.onDestroy();
            isAccepte = false;
            if (readThread != null && readThread.isAlive()) {
                readThread.interrupt();
                readThread = null;
            }
            initSocketThread.interrupt();
            initSocketThread = null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.e(TAG, "---->" + "onStartCommand");
            return super.onStartCommand(intent, flags, startId);
        }
    
        public class MyBinder extends Binder {
    
            public BindService getService() {
                return BindService.this;
            }
        }
    
        public MyBinder mBinder = new MyBinder();
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    }
    
    主要用来和视频采集端进行socket通信。
    
    另外附上一个简单的静态类
    
    package com.fm.constants;
    
    public class Constants {
        public static final int APP_CTL_HEAD = 3000;// 包头标识
        public static final byte[] APPREQUEST_HEAD={0x0b,(byte) 0xB8};//包头标识
    
        public static final int VEDIO_STREAM = 9800;//服务端将要发送播放视频命令
    }

    工具类:

    package com.fangming.utill;
    
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    
    import android.util.Log;
    
    public class ByteConvertUtils {  
    
        /** 
         * 长整形转byte数组 
         *  
         * @param n 
         *            长整形数字 
         * @return 转换后的数组 
         */  
        public static byte[] longToBytes(long n) {  
            byte[] b = new byte[8];  
            b[7] = (byte) (n & 0xff);  
            b[6] = (byte) (n >> 8 & 0xff);  
            b[5] = (byte) (n >> 16 & 0xff);  
            b[4] = (byte) (n >> 24 & 0xff);  
            b[3] = (byte) (n >> 32 & 0xff);  
            b[2] = (byte) (n >> 40 & 0xff);  
            b[1] = (byte) (n >> 48 & 0xff);  
            b[0] = (byte) (n >> 56 & 0xff);  
            return b;  
        }  
    
        public static short[] ByteToShortArray(byte[] byteArray)
        {
            short[] shortArray = new short[byteArray.length/2];
            ByteBuffer.wrap(byteArray).order(ByteOrder.BIG_ENDIAN).asShortBuffer().get(shortArray);
            return shortArray;
        }
    
        public static byte[] StringToByteArray(String houseNo)
        {
    
            Log.i("houseNo.length","houseNo.length"+houseNo.length());
            byte[] byteArray=new byte[houseNo.length()];
            for(int i=0;i<houseNo.length();i++)
            {
                byteArray[i]=Byte.parseByte(""+houseNo.charAt(i));
            }
            return byteArray;
        }
    
        /** 
         * 长整形转byte数组 
         *  
         * @param n 
         *            长整形数字 
         * @param array 
         *            转换后的结果 
         * @param offset 
         *            从第offset位开始转换 
         */  
        public static void longToBytes(long n, byte[] array, int offset) {  
            array[7 + offset] = (byte) (n & 0xff);  
            array[6 + offset] = (byte) (n >> 8 & 0xff);  
            array[5 + offset] = (byte) (n >> 16 & 0xff);  
            array[4 + offset] = (byte) (n >> 24 & 0xff);  
            array[3 + offset] = (byte) (n >> 32 & 0xff);  
            array[2 + offset] = (byte) (n >> 40 & 0xff);  
            array[1 + offset] = (byte) (n >> 48 & 0xff);  
            array[0 + offset] = (byte) (n >> 56 & 0xff);  
        }  
    
        /**
         * 将指定byte数组以16进制的形式打印到控制台
         * @param hint String
         * @param b byte[]
         * @return void
         */
        public static String printHexString( byte[] b) {
            StringBuffer returnValue = new StringBuffer();
            for (int i = 0; i < b.length; i++) {
                String hex = Integer.toHexString(b[i] & 0xFF);
                if (hex.length() == 1) {
                    hex = '0' + hex;
                }
                System.out.print(hex.toUpperCase() + " ");
                returnValue.append(hex.toUpperCase() + " ");
            }
    
            return "[" + returnValue.toString() + "]";
        }
    
        /**
         *
         * @param b byte[]
         * @return String
         */
        public static String Bytes2HexString(byte[] b) {
            String ret = "";
            for (int i = 0; i < b.length; i++) {
                String hex = Integer.toHexString(b[i] & 0xFF);
                if (hex.length() == 1) {
                    hex = '0' + hex;
                }
                ret += hex.toUpperCase();
            }
            return ret;
        }
    
        /*
         * 字节数组转换成Int数    读取后四个字节的内容长度
         */
        public static int byte2Int(byte[] b) {
            int intValue = 0;
            for (int i = 0; i < b.length; i++) {
                intValue += (b[i] & 0xFF) << (8 * (i));
            }
            return intValue;
        }
    
        /** 
         * bytes 转 Long 
         *  
         * @param array 
         *            要转换的byte 
         * @return long长整形数字 
         */  
        public static long bytesToLong(byte[] array) {  
            return ((((long) array[0] & 0xff) << 56) | (((long) array[1] & 0xff) << 48) | (((long) array[2] & 0xff) << 40)  
                    | (((long) array[3] & 0xff) << 32) | (((long) array[4] & 0xff) << 24)  
                    | (((long) array[5] & 0xff) << 16) | (((long) array[6] & 0xff) << 8) | (((long) array[7] & 0xff) << 0));  
        }  
    
        public static short[] bytesToShorts(byte byteBuffer[]) {
            int len = byteBuffer.length/2;
            short[] output = new short[len];
            int j = 0;
    
            for (int i = 0; i < len; i++) {
                output[i] = (short) (byteBuffer[j++] << 8);
                output[i] |= (byteBuffer[j++] & 0xff);
    
    //            output[i] = (short) (byteBuffer[j++] << 8);
    //            output[i] += ((0x7f &byteBuffer[j]) + (byteBuffer[j] < 0 ? 128 : 0));
    //            j++;
    
            }
            return output;
        }
    
    
        public static byte[] shortsToBytes(short shortBuffer[]) {
            int len = shortBuffer.length;
            byte[] output = new byte[len*2];
            int j = 0;
    
            for (int i = 0; i < len; i++) {
                output[j++] = (byte) (shortBuffer[i] >>> 8);
                output[j++] = (byte) (0xff & shortBuffer[i]);
            }
            return output;
        }
    
        /**
         * 将指定字符串src,以每两个字符分割转换为16进制形式 如:"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF,
         * 0xD9}
         * 
         * @param src
         *            String
         * @return byte[]
         */
        public static byte[] hexString2Bytes(String src) {
            if (src == null || "".equals(src)) {
                return null;
            }
            byte[] tmp = src.getBytes();
            int len = tmp.length / 2;
            if (len <= 0) {
                return null;
            }
            byte[] ret = new byte[len];
    
            for (int i = 0; i < len; i++) {
                ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
            }
            return ret;
        }
    
        /**
         * 将两个ASCII字符合成一个字节; 如:"EF"--> 0xEF
         * 
         * @param src0
         *            byte
         * @param src1
         *            byte
         * @return byte
         */
        public static byte uniteBytes(byte src0, byte src1) {
            byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 }))
                    .byteValue();
            _b0 = (byte) (_b0 << 4);
            byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 }))
                    .byteValue();
            byte ret = (byte) (_b0 ^ _b1);
            return ret;
        }
    
        /** 
         * byte数组转长整形数字 
         *  
         * @param array 
         *            要转换的byte数组 
         * @param offset 
         *            从第offset开始转换 
         * @return 转换后的长整形数字 
         */  
        public static long bytesToLong(byte[] array, int offset) {  
            return ((((long) array[offset + 0] & 0xff) << 56) | (((long) array[offset + 1] & 0xff) << 48)  
                    | (((long) array[offset + 2] & 0xff) << 40) | (((long) array[offset + 3] & 0xff) << 32)  
                    | (((long) array[offset + 4] & 0xff) << 24) | (((long) array[offset + 5] & 0xff) << 16)  
                    | (((long) array[offset + 6] & 0xff) << 8) | (((long) array[offset + 7] & 0xff) << 0));  
        }  
    
        public static byte[] intToBytes(int n) {  
            byte[] b = new byte[4];  
            b[3] = (byte) (n & 0xff);  
            b[2] = (byte) (n >> 8 & 0xff);  
            b[1] = (byte) (n >> 16 & 0xff);  
            b[0] = (byte) (n >> 24 & 0xff);  
            return b;  
        }  
    
        public static void intToBytes(int n, byte[] array, int offset) {  
            array[3 + offset] = (byte) (n & 0xff);  
            array[2 + offset] = (byte) (n >> 8 & 0xff);  
            array[1 + offset] = (byte) (n >> 16 & 0xff);  
            array[offset] = (byte) (n >> 24 & 0xff);  
        }  
    
        /** 
         * @param b 
         * @return 
         */  
        public static int bytesToInt(byte b[]) {  
            return b[3] & 0xff | (b[2] & 0xff) << 8 | (b[1] & 0xff) << 16 | (b[0] & 0xff) << 24;  
        } 
    
        /** 
         * @param b 
         * @return 
         */  
        public static int bytesToInt2(byte b[]) {  
            return b[1] & 0xff | (b[0] & 0xff) << 8;  
        }  
    
        /** 
         * byte 数组转 int 
         *  
         * @param b 
         *            byte数组 
         * @param offset 
         *            从数组的第几位开始转 
         * @return 整形 
         */  
        public static int bytesToInt(byte b[], int offset) {  
            return b[offset + 3] & 0xff | (b[offset + 2] & 0xff) << 8 | (b[offset + 1] & 0xff) << 16  
                    | (b[offset] & 0xff) << 24;  
        }  
    
        /** 
         * 无符号整形转数组 
         *  
         * @param n 
         *            要转换的整形 
         * @return byte数组 
         */  
        public static byte[] uintToBytes(long n) {  
            byte[] b = new byte[4];  
            b[3] = (byte) (n & 0xff);  
            b[2] = (byte) (n >> 8 & 0xff);  
            b[1] = (byte) (n >> 16 & 0xff);  
            b[0] = (byte) (n >> 24 & 0xff);  
    
            return b;  
        }  
    
        public static void uintToBytes(long n, byte[] array, int offset) {  
            array[3 + offset] = (byte) (n);  
            array[2 + offset] = (byte) (n >> 8 & 0xff);  
            array[1 + offset] = (byte) (n >> 16 & 0xff);  
            array[offset] = (byte) (n >> 24 & 0xff);  
        }  
    
        public static long bytesToUint(byte[] array) {  
            return ((long) (array[3] & 0xff)) | ((long) (array[2] & 0xff)) << 8 | ((long) (array[1] & 0xff)) << 16  
                    | ((long) (array[0] & 0xff)) << 24;  
        }  
    
        public static long bytesToUint(byte[] array, int offset) {  
            return ((long) (array[offset + 3] & 0xff)) | ((long) (array[offset + 2] & 0xff)) << 8  
                    | ((long) (array[offset + 1] & 0xff)) << 16 | ((long) (array[offset] & 0xff)) << 24;  
        }  
    
        public static byte[] shortToBytes(short n) {  
            byte[] b = new byte[2];  
            b[1] = (byte) (n & 0xff);  
            b[0] = (byte) ((n >> 8) & 0xff);  
            return b;  
        }  
    
        public static void shortToBytes(short n, byte[] array, int offset) {  
            array[offset + 1] = (byte) (n & 0xff);  
            array[offset] = (byte) ((n >> 8) & 0xff);  
        }  
    
        public static short bytesToShort(byte[] b) {  
            return (short) (b[1] & 0xff | (b[0] & 0xff) << 8);  
        }  
    
        public static short bytesToShort(byte[] b, int offset) {  
            return (short) (b[offset + 1] & 0xff | (b[offset] & 0xff) << 8);  
        }  
    
        public static byte[] ushortToBytes(int n) {  
            byte[] b = new byte[2];  
            b[1] = (byte) (n & 0xff);  
            b[0] = (byte) ((n >> 8) & 0xff);  
            return b;  
        }  
    
        public static void ushortToBytes(int n, byte[] array, int offset) {  
            array[offset + 1] = (byte) (n & 0xff);  
            array[offset] = (byte) ((n >> 8) & 0xff);  
        }  
    
        public static int bytesToUshort(byte b[]) {  
            return b[1] & 0xff | (b[0] & 0xff) << 8;  
        }  
    
        public static int bytesToUshort(byte b[], int offset) {  
            return b[offset + 1] & 0xff | (b[offset] & 0xff) << 8;  
        }  
    
        public static byte[] ubyteToBytes(int n) {  
            byte[] b = new byte[1];  
            b[0] = (byte) (n & 0xff);  
            return b;  
        }  
    
        public static void ubyteToBytes(int n, byte[] array, int offset) {  
            array[0] = (byte) (n & 0xff);  
        }  
    
        public static int bytesToUbyte(byte[] array) {  
            return array[0] & 0xff;  
        }  
    
        public static int bytesToUbyte(byte[] array, int offset) {  
            return array[offset] & 0xff;  
        }  
        // char 类型、 float、double 类型和 byte[] 数组之间的转换关系还需继续研究实现。  
    
    
    }
    

    就写到这里,欢迎加我的qq和我交流,也可以加入我们的开发交流群。
    个人qq:2385313404
    开发交流qq群:574424529

    展开全文
  • 我是要做一个APP,我的思路是通过安卓自带摄像头采集视频并预览,回调函数获取实时视频帧数据,通过wifi环境下的Socket UDP传输采集到的原始YUV420sp数据到另一手机上去,另一台手机上将获得的YUV420sp数据转换成...
  • 树莓派板子上建立nginx本地服务器,采集的视频发布至树莓派本地服务器,然后另一个服务器提供客户端接收视频服务。为什么不把树莓派采集的视频直接推送至提供客户端连接的服务器,然后手机、电脑客户端访问...

            树莓派板子上建立nginx本地服务器,采集到的视频发布至树莓派本地服务器,然后另一个服务器提供客户端接收视频服务。为什么不把树莓派采集到的视频直接推送至提供客户端连接的服务器,然后手机、电脑客户端访问服务器观看视频?因为直接让树莓派把视频推送到客户端连接的服务器,在树莓派采集端数量巨大时,成千上万的采集端往一个服务器推流,提供客户端连接的服务器会因承受不了而崩溃。

    视频数据传输流程图如下:


    树莓派本地服务器的端口与提供客户端连接的服务器进行端口绑定,手机或电脑等客户端请求服务器接受视频数据,就间接的请求树莓派本地服务器的视频数据。

    Linux通过ssh反向隧道绑定端口命令:

    ssh -N -R 8080:localhost:1935 root@192.168.2.96

    其中,8080和192.168.2.96分别为提供客户端连接的服务器端口和服务器IP地址,1935为树莓派本地服务器视频流端口。


    展开全文
  • 如果启动yaacc upnp渲染器服务,则可以通过网络中的另一个upnp控制器来控制设备。 这对于插入电视的android hdmi-sticks非常有用。 如果在它们上安装了yaacc并启动upnp渲染器服务,则可以使用智能手机或平板电脑上...
  • 此外,传感器数据可以流式传输(通过 WiFi 或蓝牙)到另一个运行 snsrlog 的设备,以便可以远程执行标记。 可以使用 iTunes 文件共享将录音上传到任何计算机。 请注意,持续记录手机传感器数据(尤其是 GPS)会显...
  • 电脑快速复制文件到手机--使用FTP

    千次阅读 2018-08-19 13:03:52
    这里介绍另一种比蓝牙快的无线传输方式:使用FTP,使用FTP的话需要安装支持FTP的软件,这里使用ES文件浏览器,好多手机上都装了这浏览器(个人觉得)。 手机上安装了ES文件浏览器 在手机下载安装APP“ES文...

    电脑快速复制文件到手机

    平时我们从电脑和手机之间传输文件的方式有:
    - 数据线
    - 蓝牙

    数据线不可能随身带,不通用。所以通常使用蓝牙来传输。但是蓝牙不好的地方就是慢。这里介绍另一种比蓝牙快的无线传输方式:使用FTP,使用FTP的话需要安装支持FTP的软件,这里使用ES文件浏览器,好多手机上都装了这个浏览器(个人觉得)。

    手机上安装了ES文件浏览器

    在手机下载安装APP“ES文件管理器“(其他文件管理器只要具有“远程管理器”功能的也可以)

    ES文件浏览器中的设置

    • 首先将手机连上wifi(和电脑在同一个局域网),或者直接连接到电脑开的热点

    • 打开APP后点左上角的菜单。

    • 点“网络”项,
    • 然后点“远程管理器

    这里解释一下为什么不用 “局域网” 和 “FTP” ,这两种方法也可以实现无线传输文件的功能,但使用局域网可能会由于权限而导致拒绝访问的问题,对普通用户来说解决这个问题有点头疼。而”FTP”和”远程管理器”的其实都是使用的FTP协议,区别在于:
    - “FTP”是手机做为FTP客户端,电脑上需要安装一个FTP服务器软件。
    - “远程管理器”则手机是FTP服务端,电脑上安装的是FTP客户端,这里直接使用电脑自带的文件资源管理器即可访问手机(FTP服务端)。

    • 点“打开“即可看到主机地址和端口号,

    • 把这个记下来,在电脑上要使用,如图

    • 按下Win+E快捷键,打开文件资源管理器输入这个地址

    • 按下回车,就可进入手机中的目录啦

    传输文件

    进入手机目录,可以很方便的在手机和电脑之间互相传输(复制粘贴)文件,这种方式比蓝牙快的多了。

    • 从电脑中复制文件:


    - 粘贴到手机中:


    - 很快就传输好啦:


    - 复制成功:

    关闭连接

    • 最后再ES文件浏览器中关闭连接即可:

    参考:http://baijiahao.baidu.com/s?id=1596833763494677229&wfr=spider&for=pc

    展开全文
  • 传输层协议 TCP

    2021-05-08 20:00:31
    TCP 提供的是 Host-To-Host 传输,一台主机通过 TCP 发送数据给另一台主机。这里的主机(Host)是一个抽象的概念,可以是手机、平板、手表等。收发数据的设备都是主机,所以双方是平等的。 TCP 协议往上是应用...

    TCP 协议

    TCP(Transport Control Protocol)是一个传输层协议,提供 Host-To-Host 数据的可靠传输,支持全双工,是一个连接导向的协议。

     

    主机到主机(Host-To-Host)

    TCP 提供的是 Host-To-Host 传输,一台主机通过 TCP 发送数据给另一台主机。这里的主机(Host)是一个抽象的概念,可以是手机、平板、手表等。收发数据的设备都是主机,所以双方是平等的。

    TCP 协议往上是应用到应用(Application-To-Application)的协议。比如微信,微信有自己的聊天协议,微信的聊天协议是应用到应用的协议;如果微信的聊天协议想要工作,就需要一个主机到主机的协议帮助它实现通信。而 TCP 上层有太多的应用,因此 TCP 上层的应用层协议使用 TCP 能力的时候,需要告知 TCP 是哪个应用,使用端口号区分应用

    TCP 要实现主机到主机通信,就需要知道主机们的网络地址(IP 地址),但是 TCP 不负责实际地址到地址(Address-To-Address)的传输,因此 TCP 协议把 IP 地址给底层的网络层处理,提供地址到地址的通信,IP 协议就在这一层工作。

    网络层解决地址到地址的通信,但是不负责信号在具体两个设备间传递。因此,网络层会调用下方的链路层在两个相邻设备间传递信息。

    链路层负责信号在两个设备间传递信息。

    当信号在两个设备间传递的时候,又设计出了物理层封装最底层的物理设备、传输介质等,由最下方的物理层提供最底层的传输能力

     

    连接和会话

    连接(Connection)是数据传输双方的契约。

    连接是通信双方的一个约定,目标是让两个在通信的程序之间产生一个默契,保证两个程序都在线,而且尽快地响应对方的请求,这就是连接(Connection)。

    设计上,连接是一种传输数据的行为。传输之前,建立一个连接。具体来说,数据收发双方的内存中都建立一个用于维护数据传输状态的对象,比如双方 IP 和端口是多少?现在发送了多少数据了?状态健康吗?传输速度如何?等。所以,连接是网络行为状态的记录。

    会话是应用的行为。比如微信聊天,创建一个聊天窗口,这个就是会话。

    会话是应用层的概念,连接是传输层的概念。

     

    双工/单工问题

    在任何一个时刻,如果数据只能单向发送,就是单工,所以单工需要至少一条线路。如果在某个时刻数据可以向一个方向传输,也可以向另一个方向反方向传输,而且交替进行,叫作半双工;半双工需要至少 1 条线路。最后,如果任何时刻数据都可以双向收发,这就是全双工,全双工需要大于 1 条线路。当然这里的线路,是一个抽象概念,你可以并发地处理信号,达到模拟双工的目的。

    TCP 是一个双工协议,数据任何时候都可以双向传输

     

    可靠性问题

    可靠性指数据保证无损传输。可靠性要求每个接收方都无损收到相同的副本,多播情况还有强可靠性,就是如果有一个消息到达任何一个接收者,那么所有接受者都必须收到这个消息。

     

    TCP 的握手和挥手

    TCP 协议有这样几个基本操作:

    1. 如果一个 Host 主动向另一个 Host 发起连接,称为 SYN(Synchronization),请求同步;

    2. 如果一个 Host 主动断开请求,称为 FIN(Finish),请求完成;

    3. 如果一个 Host 给另一个 Host 发送数据,称为 PSH(Push),数据推送。

    以上 3 种情况,接收方收到数据后,都需要给发送方一个 ACK(Acknowledgement)响应。请求/响应的模型是可靠性的要求,如果一个请求没有响应,发送方可能会认为自己需要重发这个请求。

    建立连接的过程(三次握手)

    1. 客户端发消息给服务端(SYN)

    2. 服务端针对客户端的 SYN 给一个 ACK,服务端发送一个 SYN 给客户端,注:ACK与SYN合并成ACK-SYN一起发送给客户端

    3. 客户端给服务端发送一个 ACK

    断开连接的过程(4 次挥手)

    1. 客户端要求断开连接,发送一个断开的请求,这个叫作(FIN)。

    2. 服务端收到请求,然后给客户端一个 ACK,作为 FIN 的响应。

    3. 服务端发送FIN给客户端。

    4. 客户端收到FIN,然后返回ACK给服务端,然后断开连接,服务端收到ACK,断开连接。

    断开连接比建立连接多一次交互多在服务端返回ACK时不和FIN一起合并返回,比如服务端可能还有发送出去的消息没有得到 ACK;也有可能服务端自己有资源要释放。因此断开连接不能像握手那样操作——将两条消息合并。所以,服务端经过一个等待,确定可以关闭连接了,再发一条 FIN 给客户端。

     

    展开全文
  • 手机_编程-源码

    2021-02-25 08:07:09
    创建至少2个将数据从一个屏幕传输到另一个屏幕的屏幕 对您在2号屏幕中收到的数据进行一些数据更改,然后将其传递回1号屏幕 在屏幕上添加至少一个活动元素,例如。 按钮,文本字段并处理其操作。 欢迎一些不重要的...
  • 需求是这样子的:一个app的新版本要通过另一手机去检测升级并下载好这个新版本,然后使用局域网将这个apk传输到那台手机上在更新,听着是不是有点蛋疼。那么问题来了,我要怎么知道这个apk文件是新版本呢?1.先来...
  • 近日发现了python一个很有趣的功能,今天在这里给大伙儿做一下分享需求前提1.想要拷贝电脑的文件到另一台电脑但是又没有U盘2.手机上想获取到存储在电脑的文件3.忘带U盘…您也太丢三落四...
  • 本文讲解python的一个内置文件传输下载器,可以用来在局域网内进行文件传输,当然可能有人会问,我用微信QQ也能传,为什么还要用python来传输下载?在此,其实我个人感觉的是,这种操作更简单,省了时间,比如之前在...
  • 现代的手机设备更新换代非常快,很多人总喜欢在最新版手机上市的时候就...不丢失数据的情况下,可以有选择性的传输两台手机之间的任何数据,无风险的直接从一部手机传输到另一个手机中。 Wondershare MobileTrans截图:
  • 程序会自己建立一个热点 ,另一个手机或PC 连接网络 即可通过程序发送文件 。 不需要cmcc 等 第三方的无限网络 。 不耗GPRS 流量 可以放心 传送文件。可以两个手机随时随地传送文件 注意 1:程序第一次运行时 ...
  • 手机、电脑彼此间经常需要文件交互,以满足移动办公的需要,在手机端处理好的文件能及时的同步到另一台电脑上,这对办公族来说很重要!如何将保存在手机里的文件,快速的同步到PC电脑上查看?简单的方式:通过手机和...
  • 这是一个Android手机间文件传输的例子,两个手机同时装上此app,然后输入接收端的ip,选择文件,可以多选,点确定,就发送到另一个手机,一个简单快捷文件快传实例。可以直接运用到项目中。 下面是文件选择器: ...
  • 问题/发现:本人在为一款路由器写一个统计局域网互传流量的Linux内核模块的时候,发现如下问题: 局域网内的一台设备和该局域网内另一台设备进行通信时,我在路由器的netfilter链表处设下钩子,以捕获数据。后来...
  • 说明这是一个Android手机间文件传输的例子,两个手机同时装上此app,然后输入接收端的ip,选择文件,可以多选,点确定,就发送到另一个手机,一个简单快捷文件快传实例。可以直接运用到项目中。 下面是文件选择器...
  • 文件跨平台传输

    2021-05-24 17:35:36
    生活中总想这太电脑上文件到另一台电脑,或者手机,pc上都可以下载。下面这方法可能会满足你的需求。 拷贝兔基本上能够满足文件多端使用。 不过还是anywhere感觉实在。毕竟开发人员都用vscode方便简单。 首先以...
  • 文件传输作为日常生活、工作中需求量较高的一项功能,工作中总会遇到需要将文件从一个设备转移到另一个设备上查看、存储,或者将资料回传的情况。一般大小的文件可以用QQ或者微信的文件传输助手来解决,或者任意一个...
  • InstantSis.v1.0 传输软件的好工具简单说明一下,这软件可以通过蓝牙,红外,彩信任意传输手机里得应用程序到另一手机或电脑。收到得文件将是SIS格式的 附件 1: i1.jpg (2005-7-23 11:03 PM,9.69 K) 附件 2: i2...
  • 我现在用UDP做一个文件传输的功能,(UDP原理我就不缀述了) 服务器S在公网IP下,客户端A在另一个具有公网IP的网络下,客户端B在手机3G网络下,问题是:1,A和S能互相发送和接收,B向S发送数据报时,S能接收,S根据...
  • 华为近距离通信服务(Nearby Service)使用华为自研协议,应用集成Nearby Service后,即可...这几类应用的传输文件功能主要是借助网盘、云服务器将文件传输到另一个设备上。这类方式都需要使用用户流量或者需要在有Wi
  • 华为近距离通信服务(Nearby Service)使用华为自研协议,应用集成Nearby Service后,即可...这几类应用的传输文件功能主要是借助网盘、云服务器将文件传输到另一个设备上。这类方式都需要使用用户流量或者需要在有Wi
  • 华为近距离通信服务(Nearby Service)使用华为自研协议,应用集成Nearby Service后,即可...这几类应用的传输文件功能主要是借助网盘、云服务器将文件传输到另一个设备上。这类方式都需要使用用户流量或者需要在有Wi
  • Dukto 是一个非常简单实用的文件传输工具:打开两台设备,连接同一网络(局域网或无线),一端拖拽文件,一端立马就收到啦。Dukto最大的特点就是其“易用性”和“跨平台”,另外也许从 Dukto 的图标您也能猜...
  • 流传 ShuttlePlay 是一个安卓应用程序,帮助用户将他们手机上的应用,文件传送其它人的手机上。 一般传送软件要求双方设备都安装,甚至都要联上互联网才能真正互传文件。比如Hoccer,Bump。 另一种常用互传的是...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 172
精华内容 68
关键字:

手机传输到另一个手机