2 回答
TA贡献1829条经验 获得超7个赞
问题是您无法像访问本地文件一样访问 assets 文件夹中的文件。您必须扩展 NanoHTTPD 并覆盖 serve(IHTTPSession) 才能提供资产。这是 Kotlin 中的示例。如果您看不懂,请告诉我,我会将其移植到 Java。
class FileServer(private val context: Context, port: Int) : NanoHTTPD(port) {
override fun serve(session: IHTTPSession): Response {
val uri = session.uri.removePrefix("/").ifEmpty { "index.html" }
println("Loading $uri")
try {
val mime = when (uri.substringAfterLast(".")) {
"ico" -> "image/x-icon"
"css" -> "text/css"
"htm" -> "text/html"
"html" -> "text/html"
else -> "application/javascript"
}
return NanoHTTPD.newChunkedResponse(
Response.Status.OK,
mime,
context.assets.open("www/$uri") // prefix with www because your files are not in the root folder in assets
)
} catch (e: Exception) {
val message = "Failed to load asset $uri because $e"
println(message)
e.printStackTrace()
return NanoHTTPD.newFixedLengthResponse(message)
}
}
TA贡献1802条经验 获得超5个赞
输出:
日志猫:
2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: -------Assets List-----
2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: asset-manifest.json
2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: favicon.ico
2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: index.html
2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: manifest.json
2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: precache-manifest.81af63d07b6dd6ae8e331187c522b020.js
2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: service-worker.js
2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: static
2019-08-05 15:21:53.842 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www
2019-08-05 15:21:53.865 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www/static targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static
2019-08-05 15:21:53.867 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www/static/css targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static/css
2019-08-05 15:21:53.922 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www/static/js targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static/js
2019-08-05 15:21:54.352 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www/static/media targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static/media
2019-08-05 15:21:54.526 10650-10650/com.neonxorg.neonx E/MainActivity: -------Root File List-----
2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/precache-manifest.81af63d07b6dd6ae8e331187c522b020.js
2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/service-worker.js
2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static
2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/favicon.ico
2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/manifest.json
2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/asset-manifest.json
2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/index.html
2019-08-05 15:21:54.704 10650-10650/com.neonxorg.neonx E/MainActivity: Connected : Please access! http://192.168.1.2:3000 From a web browser
代码:
public final String TAG = getClass().getSimpleName();
public void startLocalServer(int port, String root, Boolean localhost, Boolean keepAlive) {
try {
String[] filePathList = (getAssets().list("www"));
Log.e(TAG,"-------Assets List-----");
for (String s : filePathList) {
Log.e(TAG, s);
}
File externalCache = getExternalCacheDir();
if (externalCache != null) {
String path = externalCache.getAbsolutePath() + "/" + root;
copyFolderFromAssets(getApplicationContext(), "www", path);
File www_root = new File(path);
Log.e(TAG,"-------Root File List-----");
for (File f : www_root.listFiles()) {
Log.e("File ", f.getAbsolutePath());
}
server = new WebServer("localhost", port, www_root.getCanonicalFile());
server.start();
printIp();
}
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
public void copyFolderFromAssets(Context context, String rootDirFullPath, String targetDirFullPath) {
Log.e(TAG,"copyFolderFromAssets " + "rootDirFullPath-" + rootDirFullPath + " targetDirFullPath-" + targetDirFullPath);
File file = new File(targetDirFullPath);
if (!file.exists()) {
new File(targetDirFullPath).mkdirs();
}
try {
String[] listFiles = context.getAssets().list(rootDirFullPath);// 遍历该目录下的文件和文件夹
for (String string : listFiles) {// 看起子目录是文件还是文件夹,这里只好用.做区分了
if (isFileByName(string)) {// 文件
copyFileFromAssets(context, rootDirFullPath + "/" + string, targetDirFullPath + "/" + string);
} else {// 文件夹
String childRootDirFullPath = rootDirFullPath + "/" + string;
String childTargetDirFullPath = targetDirFullPath + "/" + string;
new File(childTargetDirFullPath).mkdirs();
copyFolderFromAssets(context, childRootDirFullPath, childTargetDirFullPath);
}
}
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
public void copyFileFromAssets(Context context, String assetsFilePath, String targetFileFullPath) {
InputStream assestsFileInputStream;
try {
assestsFileInputStream = context.getAssets().open(assetsFilePath);
FileOutputStream fOS = new FileOutputStream(new File(targetFileFullPath));
int length = -1;
byte[] buf = new byte[1024];
while ((length = assestsFileInputStream.read(buf)) != -1) {
fOS.write(buf, 0, length);
}
fOS.flush();
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
}
private boolean isFileByName(String str) {
return str.contains(".");
}
private void printIp() {
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
int ipAddress = wifiManager.getConnectionInfo().getIpAddress();
final String formatedIpAddress = String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff),
(ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff));
Log.e(TAG,"Connected : " + "Please access! http://" + formatedIpAddress + ":" + server.getListeningPort() + " From a web browser");
}
给定路径不是目录。
当 nanphttpd 无法定位数据时,它会给出此错误。
为什么你没有得到实际的错误
在你正在使用的catch 块中,copyFolderFromAssets由于仅显示选定的应用程序过滤器,它可能不会显示在你的 LogCat 上copyFileFromAssetse.printStackTrace()
为了打印错误,您需要使用以下内容:
Log.e(TAG, Log.getStackTraceString(e));
我用 Log.e 语句替换了所有 System.out 和 e.printStackTrace。应用程序很可能无法将内容从 www 目录复制到目标目录。我将目标目录更改为缓存目录,它在我的设备上运行。(见下文):
File externalCache = getExternalCacheDir();
if (externalCache != null) {
String path = externalCache.getAbsolutePath() + "/" + root;
File www_root = new File(path);
copyFolderFromAssets(getApplicationContext(), "www", path);
Log.e(TAG,"-------Root File List-----");
for (File f : www_root.listFiles()) {
Log.e("File ", f.getAbsolutePath());
}
server = new WebServer("localhost", port, www_root.getCanonicalFile());
server.start();
printIp();
}
边注:
static除非或除非您想将它们复制到实用程序类中,否则无需在这些函数中使用关键字
添加回答
举报