基于NanoHTTPD Android库实现YouTube播放的功能整合问题咨询
问题核心原因
- NanoHTTPD的
serve回调运行在独立后台线程,安卓不允许在非UI线程操作View相关逻辑,你直接在serve中调用youtube方法操作YouTubePlayerView属于UI操作,会抛出线程异常 - 每次提交表单都调用YouTubePlayerView的
initialize方法重复初始化,不需要多次初始化,只需初始化一次后缓存播放器实例直接调用loadVideo即可 - MainActivity中ytPlayer变量重复声明,成员变量未赋值的冗余问题也可同步优化
修复代码
1. 修改MainActivity.class
提前初始化播放器,提供主线程执行的播放方法供WebServer调用
package com.martin.androidwebplayer; import android.os.Bundle; import com.google.android.youtube.player.YouTubeBaseActivity; import com.google.android.youtube.player.YouTubePlayer; import com.google.android.youtube.player.YouTubePlayerView; public class MainActivity extends YouTubeBaseActivity { private AndroidWebServer aws; // 缓存初始化完成的播放器实例 private YouTubePlayer mYouTubePlayer; // 替换为你自己的YouTube API密钥 private static final String API_KEY = "你的实际YouTube API密钥"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); YouTubePlayerView ytPlayer = findViewById(R.id.ytPlayer); // 提前一次性初始化播放器 ytPlayer.initialize(API_KEY, new YouTubePlayer.OnInitializedListener() { @Override public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean b) { mYouTubePlayer = youTubePlayer; } @Override public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) { // 可自行添加初始化失败的提示逻辑 } }); aws = new AndroidWebServer(8180, MainActivity.this); } // 提供给WebServer调用的播放方法,自动切到UI线程执行操作 public void playYoutubeVideo(String videoId) { if (mYouTubePlayer == null || videoId == null || videoId.trim().isEmpty()) return; runOnUiThread(() -> { mYouTubePlayer.loadVideo(videoId); mYouTubePlayer.play(); }); } }
2. 修改AndroidWebServer.class
删掉原有重复初始化播放器的逻辑,收到POST参数后直接调用MainActivity的播放方法即可
package com.martin.androidwebplayer; import android.content.Context; import fi.iki.elonen.NanoHTTPD; import android.util.Log; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; public class AndroidWebServer extends NanoHTTPD { private static final String TAG = "HTTPServer"; private Context ctx; public AndroidWebServer(int port, Context ctx) { super(port); this.ctx = ctx; try { Log.d(TAG, "Starting web server.."); start(); } catch(IOException ioe) { Log.e(TAG, "Unable to start the server"); ioe.printStackTrace(); } } @Override public Response serve(IHTTPSession session) { Map<String, String> parms = session.getParms(); String content = readFile().toString(); if (session.getMethod() == Method.POST) { Map<String, String> files = new HashMap<>(); try { session.parseBody(files); } catch (IOException | ResponseException e) { e.printStackTrace(); } String videoId = parms.get("fname"); // 调用MainActivity的播放方法 if (ctx instanceof MainActivity) { ((MainActivity) ctx).playYoutubeVideo(videoId); } return newFixedLengthResponse("播放请求已提交,视频ID:" + videoId); } return newFixedLengthResponse(content); } private StringBuffer readFile() { BufferedReader reader = null; StringBuffer buffer = new StringBuffer(); try { reader = new BufferedReader(new InputStreamReader(ctx.getAssets().open("index.html"), "UTF-8")); String mLine; while ((mLine = reader.readLine()) != null) { buffer.append(mLine); buffer.append("\n"); } } catch(IOException ioe) { ioe.printStackTrace(); } finally { if (reader != null) try { reader.close(); } catch (IOException ioe) {} } return buffer; } public void stopServer() { this.stop(); } }
3. 可选优化assets/index.html
避免IP变动导致请求失败,可把ajax的请求地址改为相对路径,将原代码中url: "http://192.168.100.42:8180",修改为url: "/",即可。
内容的提问来源于stack exchange,提问作者evilcomputer12
相关产品推荐
相关产品推荐

