美文网首页LocalServer
基于AndroidAsync框架搭建android http s

基于AndroidAsync框架搭建android http s

作者: hjm1fb | 来源:发表于2017-09-16 17:46 被阅读773次

    使用的框架是AndroidAsync
    项目地址:https://github.com/koush/AndroidAsync/tree/master/AndroidAsync/src/com/koushikdutta/async
    参考的文章是:
    http://programminglife.io/android-http-server-with-androidasync/
    https://github.com/reneweb/AndroidAsyncSocketExamples
    WifiTransfer

    项目中的代码如下:

    package com.duotin.car.widget.wifiTransfer;
    
    import android.media.MediaMetadataRetriever;
    import android.net.Uri;
    import android.os.Environment;
    import android.text.TextUtils;
    
    
    import com.duotin.car.BaseApplication;
    import com.duotin.car.R;
    import com.duotin.car.constant.Constants;
    import com.duotin.car.scan.AlbumManager;
    import com.duotin.car.scan.ResultFile;
    import com.duotin.car.scan.ResultFolder;
    import com.duotin.car.util.FileUtils;
    import com.duotin.car.util.Log;
    import com.duotin.car.util.Tool;
    import com.duotin.lib.api2.Resource;
    import com.duotin.lib.api2.model.Track;
    import com.duotin.lib.util.AsyncTask;
    import com.koushikdutta.async.AsyncServer;
    import com.koushikdutta.async.AsyncServerSocket;
    import com.koushikdutta.async.AsyncSocket;
    import com.koushikdutta.async.ByteBufferList;
    import com.koushikdutta.async.DataEmitter;
    import com.koushikdutta.async.Util;
    import com.koushikdutta.async.callback.CompletedCallback;
    import com.koushikdutta.async.callback.DataCallback;
    import com.koushikdutta.async.future.Future;
    import com.koushikdutta.async.future.FutureCallback;
    import com.koushikdutta.async.http.AsyncHttpClient;
    import com.koushikdutta.async.http.AsyncHttpRequest;
    import com.koushikdutta.async.http.AsyncHttpResponse;
    import com.koushikdutta.async.http.body.MultipartFormDataBody;
    import com.koushikdutta.async.http.body.Part;
    import com.koushikdutta.async.http.callback.HttpConnectCallback;
    import com.koushikdutta.async.http.server.AsyncHttpServer;
    import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
    import com.koushikdutta.async.http.server.AsyncHttpServerRequestImpl;
    import com.koushikdutta.async.http.server.AsyncHttpServerResponse;
    import com.koushikdutta.async.http.server.HttpServerRequestCallback;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.json.JSONArray;
    import org.json.JSONObject;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileDescriptor;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.InetAddress;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.net.SocketAddress;
    import java.net.URL;
    import java.net.UnknownHostException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * * Created by hongjunmin on 15/8/26
     *
     * @author hongjunmin
     */
    public class WifiTransferServerHolder {
        private static final String TEXT_CONTENT_TYPE = "text/html;charset=utf-8";
        private static final String CSS_CONTENT_TYPE = "text/css;charset=utf-8";
        private static final String BINARY_CONTENT_TYPE = "application/octet-stream";
        private static final String JS_CONTENT_TYPE = "application/javascript";
        private static final String PNG_CONTENT_TYPE = "application/x-png";
        private static final String WOFF_CONTENT_TYPE = "application/x-font-woff";
        private static final String TTF_CONTENT_TYPE = "application/x-font-truetype";
        private static final String SVG_CONTENT_TYPE = "image/svg+xml";
        private static final String EOT_CONTENT_TYPE = "image/vnd.ms-fontobject";
        private static final String MP3_CONTENT_TYPE = "audio/mp3";
        private static final String MP4_CONTENT_TYPE = "video/mpeg4";
        public static final int AUDIO_FILE_DURATION_THRESHOLD_IN_SECOND = 600;
        public static final String MY_IMPORTED_AUDIO = "导入的音频";
        public static final String MY_IMPORTED_MUSIC = "导入的音乐";
    
        private static final String TAG = "WifiTransferServerHolder";
        private static final int DEFAULT_SOCKET_PORT = 34510;
        private AsyncHttpServer mHttpServer;
        private String defaultDirectory;
        private WifiTransferAdapter mWifiTransferAdapter;
        private AsyncServer mAsyncServer = AsyncServer.getDefault();
    
    
        private static final int BufferSize = 8190;
    
        public WifiTransferServerHolder(WifiTransferAdapter wifiTransferAdapter) {
            mWifiTransferAdapter = wifiTransferAdapter;
        }
    
        public void setUp() {
            mHttpServer = new AsyncHttpServer();
            AsyncServerSocket asyncServerSocket = mHttpServer.listen(mAsyncServer, DEFAULT_SOCKET_PORT);
            mHttpServer.post("/upload", new HttpServerRequestCallback() {
                @Override
                public void onRequest(final AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
                    final MultipartFormDataBody body = (MultipartFormDataBody) request.getBody();
                    final FileUploadHolder fileUploadHolder = new FileUploadHolder();
                    body.setMultipartCallback(new MultipartFormDataBody.MultipartCallback() {
                        @Override
                        public void onPart(final Part part) {
                            if (part.isFile()) {
                                body.setDataCallback(new DataCallback() {
                                    @Override
                                    public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
                                        if (fileUploadHolder.getFileOutPutStream() != null)
                                        //已经开始传输文件
                                        {
                                            try {
                                                fileUploadHolder.getFileOutPutStream().write(bb.getAllByteArray());
                                                mWifiTransferAdapter.onRecievingFile();
                                            } catch (IOException e) {
                                                e.printStackTrace();
                                            }
                                            bb.recycle();
                                        }
                                    }
                                });
                            } else {
                                if (body.getDataCallback() == null) {
                                    body.setDataCallback(new DataCallback() {
                                        @Override
                                        public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
                                            String fileName = getFileNameFromHttpByteBufferList(bb);
                                            //还没设置文件名
                                            if (TextUtils.isEmpty(fileUploadHolder.getFileName()) && !TextUtils.isEmpty(fileName)) {
                                                generateReceivedFileAndFileStream(fileUploadHolder, fileName);
                                                mWifiTransferAdapter.onRecievingFile();
                                            }
                                        }
                                    });
                                }
                            }
                            if (!TextUtils.isEmpty(part.getFilename())) {
                                if (!Track.isProgramFileName(part.getFilename())) {
                                    mWifiTransferAdapter.formateNotsupported(part.getFilename());
                                }
                            }
                        }
                    });
                    request.setEndCallback(new CompletedCallback() {
                        @Override
                        public void onCompleted(Exception ex) {
                            response.send(new JSONObject());
                            if (fileUploadHolder.getFileOutPutStream() != null) {
                                try {
                                    fileUploadHolder.getFileOutPutStream().close();
                                    if (fileUploadHolder.getRecievedFile() != null && fileUploadHolder.getRecievedFile().exists()) {
                                        String filePath = fileUploadHolder.getRecievedFile().getPath();
                                        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                                        try {
                                            retriever.setDataSource(filePath);
                                        } catch (Exception e) {
                                            try {
                                                FileInputStream fI = new FileInputStream(filePath);
                                                FileDescriptor fd = fI.getFD();
                                                retriever.setDataSource(fd);
                                            } catch (Exception e1) {
                                                e1.printStackTrace();
                                            }
                                        } finally {
                                            mWifiTransferAdapter.fileReceived(fileUploadHolder.getFileName());
                                            locateProgramAndReadyToSync(retriever, fileUploadHolder.getFileName());
                                        }
                                    }
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    });
                }
            });
            mHttpServer.get("/wf_images/.*", new HttpServerRequestCallback() {
                @Override
                public void onRequest(final AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
                    sendResources(request, response);
                }
            });
            mHttpServer.get("/wf_resources/.*", new HttpServerRequestCallback() {
                @Override
                public void onRequest(final AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
                    sendResources(request, response);
                }
            });
            mHttpServer.get("/wf_files/.*", new HttpServerRequestCallback() {
                @Override
                public void onRequest(final AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
                    sendResources(request, response);
                }
            });
            mHttpServer.get("/list", new HttpServerRequestCallback() {
                @Override
                public void onRequest(final AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
    
                    Log.d(TAG, request.getPath());
                    Map<String, String> headMap = new HashMap<>();
                    headMap.put("Expires:", "-1");
                    headMap.put("Cache-Control:", "no-cache");
                    headMap.put("Pragma:", "no-cache");
                    printHead(response, TEXT_CONTENT_TYPE, headMap);
                    response.send(getProgramFileNames());
                }
            });
    
            mHttpServer.get("/", new HttpServerRequestCallback() {
                @Override
                public void onRequest(final AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
                    Log.d(TAG, request.getPath());
                    try {
                        response.send(Resource.assetGet(BaseApplication.appContext, "wifiImport.html"));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
            mHttpServer.get("/temp/.*?", new HttpServerRequestCallback() {
                @Override
                public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
                    Log.d(TAG, request.getPath());
                    Map<String, String> headMap = new HashMap<>();
                    headMap.put("Expires:", "-1");
                    headMap.put("Cache-Control:", "no-cache");
                    headMap.put("Pragma:", "no-cache");
                    headMap.put("Connection:", "keep-alive");
                    printHead(response, TEXT_CONTENT_TYPE, headMap);
                    try {
                        String statusLine = ((AsyncHttpServerRequestImpl) (request)).getStatusLine();
                        String[] parts = statusLine.split(" ");
                        String fullPath = parts[1];
                        fullPath = fullPath.replace("%20", " ");
                        String resourceName = fullPath.substring(fullPath.lastIndexOf("/") + 1);
                        if (resourceName.endsWith("?")) {
                            resourceName = resourceName.substring(0, resourceName.length() - 1);
                        }
                        if (!TextUtils.isEmpty(getContentTypeByResourceName(resourceName))) {
                            response.setContentType(getContentTypeByResourceName(resourceName));
                        }
                        String path = request.getMatcher().replaceAll("");
                        String storagePath = "/storage/emulated/0/";
                        File file = new File(storagePath, path);
                        FileInputStream ex = new FileInputStream(file);
                        response.sendStream(ex, ex.available());
                    } catch (IOException e) {
                        e.printStackTrace();
                        return;
                    }
                }
            });
            mHttpServer.setErrorCallback(new CompletedCallback() {
                @Override
                public void onCompleted(Exception ex) {
                    Log.dMultiString("mHttpServer ErrorCallback onCompleted");
                }
            });
            if (asyncServerSocket != null) {
                mWifiTransferAdapter.setIpString(asyncServerSocket.getLocalPort());
            } else {
                mWifiTransferAdapter.setIpString(0);
            }
    
        }
    
        private void generateReceivedFileAndFileStream(FileUploadHolder fileUploadHolder, String fileName) {
            //取到文件名,生成目标文件和路径
            fileUploadHolder.setFileName(fileName);
            File exStorage = Environment.getExternalStorageDirectory();
            defaultDirectory = BaseApplication.getWifiMusicImportPath();
            if (TextUtils.isEmpty(defaultDirectory)) {
                mWifiTransferAdapter.showToast(R.string.no_external_cannot_import);
                return;
            }
            StringBuilder dir = new StringBuilder();
            dir.append(defaultDirectory);
            if (!dir.toString().contains(exStorage.getPath()))
                dir.insert(0, exStorage.getPath());
            File dirFile;
            dirFile = new File(dir.toString()); // convert spaces appropriately
            if (!dirFile.exists() || !dirFile.isDirectory()) // catch issues in the directory path
            {
                dir.replace(0, dir.length(), defaultDirectory); // replace it with defaultDirectory if invalid
                dirFile = new File(dir.toString());
            }
            File recievedFile = new File(dirFile, fileUploadHolder.getFileName());
            fileUploadHolder.setRecievedFile(recievedFile);
            BufferedOutputStream fs = null;
            try {
                fs = new BufferedOutputStream(new FileOutputStream(recievedFile));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            fileUploadHolder.setFileOutPutStream(fs);
        }
    
        private String getProgramFileNames() {
            List<File> importedProgramFiles = new ArrayList<>();
            importedProgramFiles.addAll(getFilesSortedByLastModified(BaseApplication.getWifiAudioImportPath()));
            importedProgramFiles.addAll(getFilesSortedByLastModified(BaseApplication.getWifiMusicImportPath()));
            JSONArray jsonArray = new JSONArray();
            for (File file : importedProgramFiles) {
                JSONObject jsonObject = new JSONObject();
                try {
                    jsonObject.put("path", file.getAbsolutePath().toString());
                    jsonObject.put("name", file.getName());
                    jsonObject.put("size", file.length());
                    jsonArray.put(jsonObject);
                } catch (Exception e) {
    
                }
            }
            return jsonArray.toString();
        }
    
        private List<File> getFilesSortedByLastModified(String path) {
            List<File> importedAudioFiles = new ArrayList<>();
            File importedAudioFolder = new File(path);
            if (importedAudioFolder.exists()) {
                File[] importedAudioArray = importedAudioFolder.listFiles();
                if (!Tool.isEmpty(importedAudioArray)) {
                    importedAudioFiles = Arrays.asList(importedAudioArray);
                    Collections.sort(importedAudioFiles,
                            new Comparator<File>() {
                                @Override
                                public int compare(File o1,
                                                   File o2) {
                                    return (int) (o1.lastModified() - o2.lastModified());
                                }
                            });
                }
    
            }
            return importedAudioFiles;
        }
    
        private void sendResources(final AsyncHttpServerRequest request, final AsyncHttpServerResponse response) {
            try {
                String statusLine = ((AsyncHttpServerRequestImpl) (request)).getStatusLine();
                String[] parts = statusLine.split(" ");
                String fullPath = parts[1];
                fullPath = fullPath.replace("%20", " ");
                String resourceName = fullPath.substring(fullPath.lastIndexOf("/") + 1);
    
                if (resourceName.endsWith("?")) {
                    resourceName = resourceName.substring(0, resourceName.length() - 1);
                }
                if (!TextUtils.isEmpty(getContentTypeByResourceName(resourceName))) {
                    response.setContentType(getContentTypeByResourceName(resourceName));
                }
                BufferedInputStream bInputStream = new BufferedInputStream(BaseApplication.appContext.getAssets().open(resourceName));
                response.sendStream(bInputStream, bInputStream.available());
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
        }
    
        private String getContentTypeByResourceName(String resourceName) {
            if (resourceName.endsWith(".css")) {
                return CSS_CONTENT_TYPE;
            } else if (resourceName.endsWith(".js")) {
                return JS_CONTENT_TYPE;
            } else if (resourceName.endsWith(".swf")) {
                return BINARY_CONTENT_TYPE;
            } else if (resourceName.endsWith(".png")) {
                return PNG_CONTENT_TYPE;
            } else if (resourceName.endsWith(".woff")) {
                return WOFF_CONTENT_TYPE;
            } else if (resourceName.endsWith(".ttf")) {
                return TTF_CONTENT_TYPE;
            } else if (resourceName.endsWith(".svg")) {
                return SVG_CONTENT_TYPE;
            } else if (resourceName.endsWith(".eot")) {
                return EOT_CONTENT_TYPE;
            } else if (resourceName.endsWith(".mp3")) {
                return MP3_CONTENT_TYPE;
            } else if (resourceName.endsWith(".mp4")) {
                return MP4_CONTENT_TYPE;
            }
            return "";
        }
    
        private void locateProgramAndReadyToSync(MediaMetadataRetriever retriever, String fileName) {
            String folderName = BaseApplication.getWifiMusicImportPath();
            String albumName = MY_IMPORTED_MUSIC;
            String duration = "0";
            Constants.TrackType trackType = Constants.TrackType.LOCAL;
            int albumId = MY_IMPORTED_MUSIC_ALBUM_ID;
            Log.dMultiString("synchronized (SingleSocketConnection.class) { 903");
            try {
                duration = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                long durationInmillisec = Long.parseLong(duration);
                long durationInsec = durationInmillisec / 1000;
                if (durationInsec > AUDIO_FILE_DURATION_THRESHOLD_IN_SECOND) {
                    FileUtils.moveFile(BaseApplication.getWifiMusicImportPath(), fileName, BaseApplication.getWifiAudioImportPath());
                    folderName = BaseApplication.getWifiAudioImportPath();
                    albumName = MY_IMPORTED_AUDIO;
                    trackType = Constants.TrackType.LOCAL;
                    albumId = MY_IMPORTED_AUDIO_ALBUM_ID;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                readtToSync(folderName, fileName, duration, albumName, trackType, albumId);
            }
        }
    
        private void readtToSync(String folderName, String fileName, String duration, String albumName, Constants.TrackType trackType, int albumId) {
            if (TextUtils.isEmpty(folderName) || TextUtils.isEmpty(fileName) || TextUtils.isEmpty(albumName))
                return;
            File folder = new File(folderName);
            Map<String, String> fileNamesAndDurations = new HashMap<>();
            fileNamesAndDurations.put(fileName, duration);
            AutoAddResultFoler autoAddResultFoler = new AutoAddResultFoler(folder, folderName, fileNamesAndDurations, albumName, trackType, albumId);
            new ImportProgramesAsynTask().execute(autoAddResultFoler);
        }
    
        public void stop() {
            mHttpServer.stop();
            mAsyncServer.stop();
        }
    
        static class ImportProgramesAsynTask extends AsyncTask<ResultFolder, String, String> {
    
            @Override
            protected String doInBackground(ResultFolder... params) {
                ResultFolder resultFolder = params[0];
                if (resultFolder != null)
                    AlbumManager.storeFolder(resultFolder);
                return null;
            }
        }
    
        class AutoAddResultFoler extends ResultFolder {
    
            public AutoAddResultFoler(File folderFile, String folderName, Map<String, String> fileNamesAndDurations, String albumName, Constants.TrackType trackType, int albumId) {
                super(folderFile);
                if (folderFile.exists() && !Tool.isEmpty(fileNamesAndDurations)) {
                    setId(albumId);
                    setSource(Constants.TrackSource.LOCAL_WIFI_IMPORT);
                    setTrackType(trackType);
                    setAlbumName(albumName);
                    for (Map.Entry<String, String> entry : fileNamesAndDurations.entrySet()) {
                        File recievedFile = new File(folderName + entry.getKey());
                        if (recievedFile.exists()) {
                            ResultFile resultFile = new ResultFile(recievedFile);
                            resultFile.setToAdd(true);
                            resultFile.setSource(Constants.TrackSource.LOCAL_WIFI_IMPORT);
                            resultFile.setDuration(com.duotin.lib.api2.util.StringUtils.formatTime(entry.getValue()));
                            resultFile.setStatus(Constants.TrackState.DOWNLOAD_SUCCESSFUL);
                            addResultFile(resultFile);
                        }
                    }
                }
            }
    
        }
    
    
        class FileUploadHolder {
            private String fileName;
    
            public File getRecievedFile() {
                return recievedFile;
            }
    
            public void setRecievedFile(File recievedFile) {
                this.recievedFile = recievedFile;
            }
    
            private File recievedFile;
    
            public BufferedOutputStream getFileOutPutStream() {
                return fileOutPutStream;
            }
    
            public void setFileOutPutStream(BufferedOutputStream fileOutPutStream) {
                this.fileOutPutStream = fileOutPutStream;
            }
    
            public String getFileName() {
                return fileName;
            }
    
            public void setFileName(String fileName) {
                this.fileName = fileName;
            }
    
            public void reset() {
                fileName = null;
                fileOutPutStream = null;
            }
    
            private BufferedOutputStream fileOutPutStream;
        }
    
        private String getFileNameFromHttpByteBufferList(ByteBufferList bb) {
            String s = bb.readString();
            Log.dMultiString(s);
            if (Track.isProgramFileName(s)) {
                return s;
            } else {
                if (s.length() > 2) {
                    s = s.substring(0, s.length() - 2);
                    if (Track.isProgramFileName(s)) {
                        return s;
                    }
                }
            }
            return null;
        }
    
        private void printHead(AsyncHttpServerResponse response, String contentType, Map<String, String> customHeads) {
            response.setContentType(contentType);
            if (!Tool.isEmpty(customHeads)) {
                for (Map.Entry<String, String> entry : customHeads.entrySet()) {
                    response.getHeaders().set(entry.getKey(), entry.getValue());
                }
            }
        }
    }
    

    代码中很多是业务,所以大家主要是参照setUp方法和get,post是怎么设置的。
    另:
    下载的jar包是2.1.6的。但用在项目中遇到
    问题一:有乱码。解决方案:项目里的 Charsets.US_ASCII 都改成了 Charsets.UTF_8
    问题二: 从客户端获取数据不完整。发现是LineEmitter 类的onDataAvailable(DataEmitter emitter, ByteBufferList bb)内的代码走不通。就把原来的:
    @Override public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) { while (bb.remaining() > 0) { byte b = bb.get(); if (b == '\n') { assert mLineCallback != null; mLineCallback.onStringAvailable(data.toString()); data = new StringBuilder(); return; } else { data.append((char)b); } } }
    改成了:
    @Override public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) { String s = bb.readString(); if (s.indexOf("\n") > 0) mLineCallback.onStringAvailable(s); }}
    就OK了
    由于我用的是jar包的引用方式,所以是依照上面改动原项目后导出了jar包,导jar包方法:http://blog.csdn.net/u012319317/article/details/48133463
    你可以直接下载我导出的jar包:http://download.csdn.net/detail/u012319317/9408485

    获取的结果中,中文乱码 更简洁的方案

    另:
    推荐一篇NIO科普文:
    Java NIO:浅析I/O模型

    更多参考:
    AndroidAsync方案:
    An HTTP server inside your Android application using AndroidAsync
    This project includes a few examples on how to create different types of sockets using AndroidAsync. It includes examples for a TCP client/server, TCP client with SSL and UDP client/server.
    WifiTransfer

    其他方案:
    AndServer
    android-http-server
    nanohttpd

    相关文章

      网友评论

        本文标题:基于AndroidAsync框架搭建android http s

        本文链接:https://www.haomeiwen.com/subject/zwhusxtx.html