将视频和图像从本地存储加载到Google ChromeCast Android

4
如何将本地视频URI/路径/文件设置为chromecast的MediaInfo.Builder()?此外,是否有人可以帮助我提供代码片段,以便从Android存储中本地加载图像和视频并将其投射到Google Chrome Cast?已经阅读了其他问题,但在那里已经提到要在应用程序上创建本地服务器。如果真的需要这样做,则如何实现?我正在使用https://github.com/googlecast/CastVideos-android上可用的代码,但在那里视频是从URL获取并播放的。我要从本地存储加载视频,同时还要显示图片。
更新: 现在我已经使用"NanoHttpD"创建了一个本地服务器,但无法获取所选本地文件的URL。以下是我的活动代码片段:
public class VideoBrowserFragment extends Fragment implements VideoListAdapter.ItemClickListener,
        LoaderManager.LoaderCallbacks<List<MediaInfo>> {

    private static final String TAG = "zz VideoBrowserFragment";
    private static final int REQUEST_TAKE_GALLERY_VIDEO = 123;
    private static final String CATALOG_URL =
            "http://commondatastorage.googleapis.com/gtv-videos-bucket/CastVideos/f.json";
    private RecyclerView mRecyclerView;
    private VideoListAdapter mAdapter;
    private View mEmptyView;
    private View mLoadingView;
    private VideoCastManager mCastManager;
    private VideoCastConsumerImpl mCastConsumer;
    private View btnLocalVideo;
    LocalServer server;
    String chosenExt = "";
    String localFileName = "";
    String localFilePath = "";
    String formatedIpAddress = "";
    Uri selectedImageUri;

    public VideoBrowserFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        Toast.makeText(getActivity(), "VideoBrowserFragment onCreateView", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "VideoBrowserFragment onCreateView");
        return inflater.inflate(R.layout.video_browser_fragment, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Toast.makeText(getActivity(), "VideoBrowserFragment onViewCreated", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "VideoBrowserFragment onViewCreated");

        mRecyclerView = (RecyclerView) getView().findViewById(R.id.list);
        mEmptyView = getView().findViewById(R.id.empty_view);
        mLoadingView = getView().findViewById(R.id.progress_indicator);
        btnLocalVideo = getView().findViewById(R.id.btnLocalVideo);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(layoutManager);
        mAdapter = new VideoListAdapter(this);
        mRecyclerView.setAdapter(mAdapter);
        getLoaderManager().initLoader(0, null, this);
        mCastManager = VideoCastManager.getInstance();
        mCastConsumer = new VideoCastConsumerImpl() {
            @Override
            public void onConnected() {
                super.onConnected();
                mAdapter.notifyDataSetChanged();
            }

            @Override
            public void onDisconnected() {
                super.onDisconnected();
                mAdapter.notifyDataSetChanged();
            }
        };
        mCastManager.addVideoCastConsumer(mCastConsumer);


//fetch local video
        btnLocalVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent intent = new Intent();
                intent.setType("video/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent, "Select Video"), REQUEST_TAKE_GALLERY_VIDEO);


            }
        });
    }


    //get data of locally fetched videos....
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == getActivity().RESULT_OK) {
            if (requestCode == REQUEST_TAKE_GALLERY_VIDEO) {
                 selectedImageUri = data.getData();

                Toast.makeText(getActivity(), "Sending local video data", Toast.LENGTH_SHORT).show();
                MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);

                movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, "Local Subtitle");
                movieMetadata.putString(MediaMetadata.KEY_TITLE, "Local Video is playing");

                JSONObject jsonObj = null;
                try {
                    jsonObj = new JSONObject();
                    jsonObj.put("description", "Sample Descrioption over here");
                } catch (JSONException e) {
                    Log.e(TAG, "Failed to add description to the json object", e);
                }
                String filePath = getPath(selectedImageUri);
                chosenExt = filePath.substring(filePath.lastIndexOf(".") + 1);
                startLocalServer();
                String localUrl = formatedIpAddress + localFilePath;
                Log.d(TAG, "MediaInfo urlLocal: " + localUrl);
                MediaInfo item = new MediaInfo.Builder(localUrl)
                        .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
                        .setContentType("video/mp4")
                        .setMetadata(movieMetadata)
                        .setStreamDuration(333 * 1000)
                        .build();
                Log.d(TAG, "VideoBrowserFragment itemClicked media :" + Utils.mediaInfoToBundle(item));

                Intent intent = new Intent(getActivity(), LocalPlayerActivity.class);
                intent.putExtra("media", Utils.mediaInfoToBundle(item));
                intent.putExtra("shouldStart", false);
                intent.putExtra("isLocal", true);
                intent.putExtra("videoUri", selectedImageUri.toString());
               /* Pair<View, String> imagePair = Pair
                        .create((View) viewHolder.getImageView(), transitionName);*/
                ActivityOptionsCompat options = ActivityOptionsCompat
                        .makeSceneTransitionAnimation(getActivity());
                ActivityCompat.startActivity(getActivity(), intent, options.toBundle());

            }
        }
    }


    //get path of video fetched...
    public String getPath(Uri uri) {
        Log.d(TAG, "uri is " + uri);
        String[] proj = {MediaStore.Images.Media.DATA};
        CursorLoader loader = new CursorLoader(getActivity(), uri, proj, null, null, null);
        Cursor cursor = loader.loadInBackground();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();

        if (cursor.moveToFirst()) {
            //int column_index1 = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
            Uri filePathUri = Uri.parse(cursor.getString(column_index));
            String file_name = filePathUri.getLastPathSegment().toString();
            String file_path = filePathUri.getPath();
            localFileName = file_name;
            localFilePath = file_path;
            Toast.makeText(getActivity(), "File Name & PATH are:" + file_name + "\n" + file_path, Toast.LENGTH_LONG).show();
            Log.d("zz fileData: ", "fp: " + file_path + " :and: fn: " + file_name);
        }
        String result = cursor.getString(column_index);
        cursor.close();
        return result;
    }

    @Override
    public void onDetach() {
        Toast.makeText(getActivity(), "VideoBrowserFragment onDetach", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "VideoBrowserFragment onDetach");
        mCastManager.removeVideoCastConsumer(mCastConsumer);
        super.onDetach();
    }

    @Override
    public void itemClicked(View view, MediaInfo item, int position) {
        Toast.makeText(getActivity(), "VideoBrowserFragment itemClicked", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "VideoBrowserFragment itemClicked");

        if (view instanceof ImageButton) {
            Log.d(TAG, "menu was clicked");
            com.scriptlanes.cast2.utils.Utils.showQueuePopup(getActivity(), view, item);
        } else {
            String transitionName = getString(R.string.transition_image);
            VideoListAdapter.ViewHolder viewHolder =
                    (VideoListAdapter.ViewHolder) mRecyclerView.findViewHolderForPosition(position);
            Pair<View, String> imagePair = Pair
                    .create((View) viewHolder.getImageView(), transitionName);
            ActivityOptionsCompat options = ActivityOptionsCompat
                    .makeSceneTransitionAnimation(getActivity(), imagePair);

            Intent intent = new Intent(getActivity(), LocalPlayerActivity.class);
            Log.d(TAG, "VideoBrowserFragment itemClicked media :" + Utils.mediaInfoToBundle(item));

            intent.putExtra("media", Utils.mediaInfoToBundle(item));
            intent.putExtra("shouldStart", false);
            //isUrl=true, isLocal=false
            intent.putExtra("isLocal", false);
            ActivityCompat.startActivity(getActivity(), intent, options.toBundle());
        }
    }

    @Override
    public Loader<List<MediaInfo>> onCreateLoader(int id, Bundle args) {
        Toast.makeText(getActivity(), "VideoBrowserFragment onCreateLoader", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "VideoBrowserFragment onCreateLoader");

        return new VideoItemLoader(getActivity(), CATALOG_URL);
    }

    @Override
    public void onLoadFinished(Loader<List<MediaInfo>> loader, List<MediaInfo> data) {
        Toast.makeText(getActivity(), "VideoBrowserFragment onLoadFinished", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "VideoBrowserFragment onLoadFinished");
        mAdapter.setData(data);
        mLoadingView.setVisibility(View.GONE);
        mEmptyView.setVisibility(null == data || data.isEmpty() ? View.VISIBLE : View.GONE);
    }

    @Override
    public void onLoaderReset(Loader<List<MediaInfo>> loader) {
        Toast.makeText(getActivity(), "VideoBrowserFragment onLoaderReset", Toast.LENGTH_SHORT).show();
        Log.d(TAG, "VideoBrowserFragment onLoaderReset");
        mAdapter.setData(null);
    }



    /*temp code nanohttpd*/


    public class LocalServer extends NanoHTTPD {

        private  final Logger LOG = Logger.getLogger(LocalServer.class.getName());

        public  void main(String[] args) {
            ServerRunner.run(LocalServer.class);
        }
        public LocalServer() {
            super(3000);
            Log.d("zz nanaHttpd: ", "STARTED");

        }

       @Override
        public Response serve(String uri, Method method, Map<String, String> header, Map<String, String> parameters, Map<String, String> files) {
            //String mediasend = getExtension(chosenFile);

           Log.d("zz nanaHttpd:  ", "uri:  " + uri+" , method: "+method);
           FileInputStream fis = null;
           File file = new File(localFilePath);
           Log.e("Creando imputStream", "Size: ");
           try {
               fis = new FileInputStream(file);
           } catch (FileNotFoundException e) {
               e.printStackTrace();
           }

            return new NanoHTTPD.Response(Response.Status.OK, "video/mp4", fis);
        }

    }

    private void startLocalServer() {
        server = new LocalServer();
        try {
            server.start();
        } catch (IOException ioe) {
            Log.d("zz Httpd", "The server could not start.");
        }
        Log.d("zz Httpd", "Web server initialized.");
        WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
        int ipAddress = wifiManager.getConnectionInfo().getIpAddress();
        Log.d("zz Httpd IP U: ", ipAddress + "");
        String formatedIpAddress1 = String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff),
                (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff));
        formatedIpAddress = "http://" + formatedIpAddress1 + ":" + server.getListeningPort();
        Log.d("zz Httpd IP: ", "Please access! " + formatedIpAddress);


    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //server.stop();
    }
}

你解决了这个问题吗? - Nasib
@Nasib 不,还没有。 - pravingaikwad07
如果您已经解决了问题,能否请您发布解决方案?我们共享相同的情境。 - hardik9850
2个回答

0

正如您在其他帖子中所看到的,您需要向应用程序添加嵌入式Web服务器,并在该Web服务器中公开本地内容。然后,您需要将这些本地内容的URL发送到您的Chromecast。如果您不想构建自己的微型HTTP服务器,可以使用许多开源小型嵌入式HTTP服务器,您可以通过谷歌搜索此类嵌入式解决方案。


感谢@Ali Naddaf……虽然我尝试使用“NanoHttpD”创建本地服务器,但我不知道如何传递所选视频/图像的URL。我已经完成了以下工作:(1)通过意图打开了一个库以选择视频文件,然后在onActivityResult中获得了所选视频的URI。之后我应该做什么? - pravingaikwad07
阿里·纳达夫,我已经更新了我的问题,加入了整个活动代码,请问您有什么方法可以通过“NanoHttpD”本地服务器获取所选视频文件的URL。 - pravingaikwad07
建议参考 https://github.com/KaustubhPatange/Android-Cast-Local-Sample。 - cwc

0

你做得对,只需将选定的URL放在这样的位置:

mediaMetadata.addImage(new WebImage(Uri.parse(http://192.168.0.XX:8080/video.mp4));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接