Intereting Posts
Является ли Secure.ANDROID_ID уникальным для каждого устройства? GetMeasuredHeight () и возвращаемая ширина 0 после измерения () Как узнать, использует ли Locale 12 или 24-часовой формат? Xamarin.Forms салфетки распознавания жестов Образец или лучшая практика для простого приложения-клиента сокета Передача объекта GoogleApiClient из одного действия в другое Пользовательские настройки, сохраненные в SharedPreferences, удаленные или потерянные между перезагрузками приложения Сепаратор между кнопками в пользовательской панели кнопок Можно ли нарисовать жизненный цикл Фрагмента и его родительского FragmentActivity? Включить OpenCV в пакет приложений для Android Как создать EditText принимает Alphabets только в android? Получение уровня сигнала Wi-Fi в Android GetSupportActionBar () Метод getSupportActionBar () не определен для типа TaskActivity. Зачем? Ошибка Android Studio Gradle во время компиляции Создание многострочного EditText программно

Как обслуживать файл на SD-карте с помощью NanoHTTPD (внутри Android)

Я написал небольшой сервер Android с помощью NanoHTTPD. Он может хорошо служить HTML-файлу (веб-страница, расположенная на sdcard / www / index.html). Может ли кто-нибудь помочь мне узнать, как я могу подавать аудио- или видеофайлы вместо html-страницы с помощью NanoHTTPD? Простите меня, если вопрос кажется глупым, поскольку я новичок в HTTP! Вот мой код на стороне сервера (я заменил путь веб-страницы на файл аудиофайла):

package com.example.zserver; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.util.Log; public class MainActivity extends Activity { private WebServer server; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); server = new WebServer(); try { server.start(); } catch(IOException ioe) { Log.w("Httpd", "The server could not start."); } Log.w("Httpd", "Web server initialized."); } @Override public void onDestroy() { super.onDestroy(); if (server != null) server.stop(); } private class WebServer extends NanoHTTPD { public WebServer() { super(8080); } @Override public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parameters, Map<String, String> files) { String answer = ""; try { // Opening file from SD Card File root = Environment.getExternalStorageDirectory(); FileReader index = new FileReader(root.getAbsolutePath() + "/www/music.mp3"); BufferedReader reader = new BufferedReader(index); String line = ""; while ((line = reader.readLine()) != null) { answer += line; } } catch(IOException ioe) { Log.w("Httpd", ioe.toString()); } return new NanoHTTPD.Response(answer); } } } 

Я включил в свой код необходимые разрешения на использование:

 <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

Любая помощь будет оценена по достоинству. Заранее спасибо!

EDIT, Добавлено разрешение:

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> 

EDIT1: Канонический способ чтения и записи в буферы:

 int read; int n=1; while((read = dis.read(mybytearray)) != -1){ dos.write(mybytearray, 0, read);} 

Solutions Collecting From Web of "Как обслуживать файл на SD-карте с помощью NanoHTTPD (внутри Android)"

Во-первых, вам нужно убедиться, что вы правильно настроили mimetype при работе с мультимедийными файлами.

Во-вторых, вы не получите очень много времени, чтобы прочитать файл в формате MP3, используя FileReader , вместо этого вы должны предоставить NanoHTTPD с помощью InputStream .

Ниже приведена рабочая измененная версия вашего кода, в которой используется файл MP3. Установив mimetype в audio/mpeg вы позволяете браузеру решать, что делать с этим контентом. В Chrome, например, запущен встроенный музыкальный проигрыватель и воспроизводит файл.

 public class StackOverflowMp3Server extends NanoHTTPD { public StackOverflowMp3Server() { super(8089); } @Override public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parameters, Map<String, String> files) { String answer = ""; FileInputStream fis = null; try { fis = new FileInputStream(Environment.getExternalStorageDirectory() + "/music/musicfile.mp3"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new NanoHTTPD.Response(Status.OK, "audio/mpeg", fis); } } 

EDIT: многие люди спрашивают, как сделать аудиофайл доступным с использованием запросов диапазона, я продемонстрирую это ниже

Чтобы сделать аудиофайл доступным, используются запросы диапазона, которые позволяют HTTP-клиентам извлекать части аудиофайла в кусках. Убедитесь, что вы обслуживаете файл со статусом ответа PARTIAL_CONTENT (HTTP 206). Пример реализации можно найти в примере кода NanoHTTPD: SimpleWebserver.java

В моей реализации вместо того, чтобы возвращать ответ NanoHTTPD непосредственно в методе serve, я создаю другой метод, называемый «servefile», который я использую в качестве ответа для обработки запросов диапазона, как вы можете видеть ниже. Этот код является модифицированной реализацией SimpleWebServer.java, указанной выше.

  @Override public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parameters, Map<String, String> files) { File f = new File(Environment.getExternalStorageDirectory() + "/music/musicfile.mp3"); String mimeType = "audio/mpeg"; return serveFile(uri, header, f, mimeType); } //Announce that the file server accepts partial content requests private Response createResponse(Response.Status status, String mimeType, InputStream message) { Response res = new Response(status, mimeType, message); res.addHeader("Accept-Ranges", "bytes"); return res; } /** * Serves file from homeDir and its' subdirectories (only). Uses only URI, * ignores all headers and HTTP parameters. */ private Response serveFile(String uri, Map<String, String> header, File file, String mime) { Response res; try { // Calculate etag String etag = Integer.toHexString((file.getAbsolutePath() + file.lastModified() + "" + file.length()).hashCode()); // Support (simple) skipping: long startFrom = 0; long endAt = -1; String range = header.get("range"); if (range != null) { if (range.startsWith("bytes=")) { range = range.substring("bytes=".length()); int minus = range.indexOf('-'); try { if (minus > 0) { startFrom = Long.parseLong(range .substring(0, minus)); endAt = Long.parseLong(range.substring(minus + 1)); } } catch (NumberFormatException ignored) { } } } // Change return code and add Content-Range header when skipping is // requested long fileLen = file.length(); if (range != null && startFrom >= 0) { if (startFrom >= fileLen) { res = createResponse(Response.Status.RANGE_NOT_SATISFIABLE, NanoHTTPD.MIME_PLAINTEXT, ""); res.addHeader("Content-Range", "bytes 0-0/" + fileLen); res.addHeader("ETag", etag); } else { if (endAt < 0) { endAt = fileLen - 1; } long newLen = endAt - startFrom + 1; if (newLen < 0) { newLen = 0; } final long dataLen = newLen; FileInputStream fis = new FileInputStream(file) { @Override public int available() throws IOException { return (int) dataLen; } }; fis.skip(startFrom); res = createResponse(Response.Status.PARTIAL_CONTENT, mime, fis); res.addHeader("Content-Length", "" + dataLen); res.addHeader("Content-Range", "bytes " + startFrom + "-" + endAt + "/" + fileLen); res.addHeader("ETag", etag); } } else { if (etag.equals(header.get("if-none-match"))) res = createResponse(Response.Status.NOT_MODIFIED, mime, ""); else { res = createResponse(Response.Status.OK, mime, new FileInputStream(file)); res.addHeader("Content-Length", "" + fileLen); res.addHeader("ETag", etag); } } } catch (IOException ioe) { res = createResponse(Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: Reading file failed."); } return res; } 

Вам также не нужно добавлять разрешение android.permission.READ_EXTERNAL_STORAGE

Потому что вы читаете файл.