2017-08-17 4 views
18

私はアンドロイドアプリでビデオを再生するためにExo PlayerExtractorMediaSourceを使用しています。私はサーバーからメディアをダウンロードしてローカルデータベースに保存し、特定の時間にアラームを出します。このメディアはexoプレーヤーのConcatenatingMediaSourceを使って再生します。しかし、まず私はすべてのビデオファイルがダウンロードされているかどうかをチェックし、ダウンロードされたメディアソースでプレーヤーを開始します。すべてのビデオは、ダウンロードされていない場合と、私は私のすでに作成したプレイリストにこのビデオを追加したい、それがその後、ダウンロードしたときに、バックグラウンドでそれをダウンロードしたいexoplayerのメディアソースをリフレッシュ

これはサンプルコードでは、

private void playAndUpdateVideo(ArrayList<String> mediaSourc) { 



     simpleExoPlayerView.setVisibility(View.VISIBLE); 
     simpleExoPlayerView.setDefaultArtwork(null); 

     mainHandler = new Handler(); 
     DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); 
     TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(bandwidthMeter); 
     TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); 
     dataSourceFactory = new DefaultDataSourceFactory(context, 
       Util.getUserAgent(context, "com.cloveritservices.hype"), bandwidthMeter); 
// 2. Create a default LoadControl 
     extractorsFactory = new DefaultExtractorsFactory(); 
     LoadControl loadControl = new DefaultLoadControl(); 

// 3. Create the player 
     player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl); 
     player.addListener(this); 

//Set media controller 
     simpleExoPlayerView.setUseController(false); 
     simpleExoPlayerView.requestFocus(); 
// Bind the player to the view. 
     simpleExoPlayerView.setPlayer(player); 




     MediaSource[] mediaSources = new MediaSource[mediaSourc.size()]; 
     for (int i=0;i<mediaSourc.size();i++) 
     { 

      mediaSources[i]= buildMediaSource(Uri.parse(mediaSourc.get(i))); 

     } 

     MediaSource mediaSource = mediaSources.length == 1 ? mediaSources[0] 
       : new ConcatenatingMediaSource(mediaSources); 
     LoopingMediaSource loopingSource = new LoopingMediaSource(mediaSource); 
     player.prepare(loopingSource); 
     SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); 
     boolean isChecked = settings.getBoolean("switch", false); 
     if (!isChecked) 
     player.setVolume(0f); 
     else player.setVolume(2f); 
     player.setPlayWhenReady(true); 

    } 

そして、ここにありますダウンロードされたビデオファイルを確認しています

if (CommonUtils.isExternalStorageExistAndWritable()) { 
       for (int i = 0; i < videoUrl.size(); i++) { 


        if (!new File(Environment.getExternalStorageDirectory().toString() + Constants.PROFILE_VIDEO_FOLDER + CommonUtils.fileFromUrl(videoUrl.get(i))).exists() && !CommonUtils.currentlyDownloading(context,CommonUtils.fileFromUrl(videoUrl.get(i)))) { 
         downloadByDownloadManager(videoUrl.get(i), CommonUtils.fileFromUrl(videoUrl.get(i))); 
         if (flag==Constants.FLAG_PLAY){downloadFlag=true;} 
        } 
       } 

      } else { 
       Toast.makeText(getApplicationContext(), "SD Card not mounted.Please Mount SD Card", Toast.LENGTH_SHORT).show(); 
      } 
      if (flag==Constants.FLAG_PLAY && !downloadFlag) 
      { 
       playAndUpdateVideo(videoUrl); 
      } 

    public void downloadByDownloadManager(String url, String fileName1) { 
     downloadUrl=url; 
     fileName=fileName1; 
     request = new DownloadManager.Request(Uri.parse(url)); 
     request.setDescription("video file"); 
     request.setTitle(fileName); 

     request.setNotificationVisibility(2); 
     request.allowScanningByMediaScanner(); 

        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); 
        request.setDestinationInExternalPublicDir(Constants.PROFILE_VIDEO_FOLDER, fileName); 
        DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); 

        manager.enqueue(request); 







     // get download service and enqueue file 



    } 

ダウンロードしていない場合は、後で再生リストに追加する方法をお手伝いしてください。

+0

ファイルをダウンロードした後にプレイリストに追加しますか? –

+0

はい、プレイリストを再度初期化したくありません@ SagarPujari –

+0

あなたはファイルをダウンロードしているコードを共有できます。 –

答えて

3

新しいビデオファイルをプレイリストに追加するには、サイズ変更を有効にするソースリストを処理できる新しいMediaSourceの実装が必要です。これは非常に簡単ですが、これを行う最も簡単な方法は、ConcaternatingMediaSourceの変更された実装を作成し、配列の代わりにリストを使用してメディアソースを格納および反復する方法です。 playAndUpdateVideoConcaternatingMediaSourceをリストを使用して新しい実装に置き換えます。これにより、必要に応じてプレイリストに追加したり削除したりすることができます。ダウンロード完了リスナがトリガーされたときに新しいメディアファイルを追加できます。ここではリストを使用して、メディアソース実装の完全なクラスがある:

public final class DynamicMediaSource implements MediaSource { 

    private List<MediaSource> mediaSources; 
    private SparseArray<Timeline> timelines; 
    private SparseArray<Object> manifests; 
    private Map<MediaPeriod, Integer> sourceIndexByMediaPeriod; 
    private SparseArray<Boolean> duplicateFlags; 
    private boolean isRepeatOneAtomic; 

    private Listener listener; 
    private DynamicTimeline timeline; 

    /** 
    * @param mediaSources The {@link MediaSource}s to concatenate. It is valid for the same 
    *  {@link MediaSource} instance to be present more than once in the array. 
    */ 
    public DynamicMediaSource(List<MediaSource> mediaSources) { 
     this(false, mediaSources); 
    } 

    /** 
    * @param isRepeatOneAtomic Whether the concatenated media source shall be treated as atomic 
    *  (i.e., repeated in its entirety) when repeat mode is set to {@code Player.REPEAT_MODE_ONE}. 
    * @param mediaSources The {@link MediaSource}s to concatenate. It is valid for the same 
    *  {@link MediaSource} instance to be present more than once in the array. 
    */ 
    public DynamicMediaSource(boolean isRepeatOneAtomic, List<MediaSource> mediaSources) { 
     for (MediaSource mediaSource : mediaSources) { 
      Assertions.checkNotNull(mediaSource); 
     } 
     this.mediaSources = mediaSources; 
     this.isRepeatOneAtomic = isRepeatOneAtomic; 
     timelines = new SparseArray<Timeline>(); 
     manifests = new SparseArray<Object>(); 
     sourceIndexByMediaPeriod = new HashMap<>(); 
     duplicateFlags = buildDuplicateFlags(mediaSources); 
    } 

    @Override 
    public void prepareSource(ExoPlayer player, boolean isTopLevelSource, Listener listener) { 
     this.listener = listener; 
     for (int i = 0; i < mediaSources.size(); i++) { 
      if (!duplicateFlags.get(i)) { 
       final int index = i; 
       mediaSources.get(i).prepareSource(player, false, new Listener() { 
        @Override 
        public void onSourceInfoRefreshed(Timeline timeline, Object manifest) { 
         handleSourceInfoRefreshed(index, timeline, manifest); 
        } 
       }); 
      } 
     } 
    } 

    @Override 
    public void maybeThrowSourceInfoRefreshError() throws IOException { 
     for (int i = 0; i < mediaSources.size(); i++) { 
      if (!duplicateFlags.get(i)) { 
       mediaSources.get(i).maybeThrowSourceInfoRefreshError(); 
      } 
     } 
    } 

    @Override 
    public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { 
     int sourceIndex = timeline.getChildIndexByPeriodIndex(id.periodIndex); 
     MediaPeriodId periodIdInSource = 
      new MediaPeriodId(id.periodIndex - timeline.getFirstPeriodIndexByChildIndex(sourceIndex)); 
     MediaPeriod mediaPeriod = mediaSources.get(sourceIndex).createPeriod(periodIdInSource, allocator); 
     sourceIndexByMediaPeriod.put(mediaPeriod, sourceIndex); 
     return mediaPeriod; 
    } 

    @Override 
    public void releasePeriod(MediaPeriod mediaPeriod) { 
     int sourceIndex = sourceIndexByMediaPeriod.get(mediaPeriod); 
     sourceIndexByMediaPeriod.remove(mediaPeriod); 
     mediaSources.get(sourceIndex).releasePeriod(mediaPeriod); 
    } 

    @Override 
    public void releaseSource() { 
     for (int i = 0; i < mediaSources.size(); i++) { 
      if (!duplicateFlags.get(i)) { 
       mediaSources.get(i).releaseSource(); 
      } 
     } 
    } 

    private void handleSourceInfoRefreshed(int sourceFirstIndex, Timeline sourceTimeline, 
             Object sourceManifest) { 
     // Set the timeline and manifest. 
     timelines.put(sourceFirstIndex, sourceTimeline); 
     manifests.put(sourceFirstIndex, sourceManifest); 

     // Also set the timeline and manifest for any duplicate entries of the same source. 
     for (int i = sourceFirstIndex + 1; i < mediaSources.size(); i++) { 
      if (mediaSources.get(i).equals(mediaSources.get(sourceFirstIndex))) { 
       timelines.put(i, sourceTimeline); 
       manifests.put(i, sourceManifest); 
      } 
     } 

     for(int i= 0; i<mediaSources.size(); i++){ 
      if(timelines.get(i) == null){ 
       // Don't invoke the listener until all sources have timelines. 
       return; 
      } 
     } 

     timeline = new DynamicTimeline(timelines, isRepeatOneAtomic); 
     listener.onSourceInfoRefreshed(timeline, new ArrayList(asList(manifests))); 
    } 

    private static SparseArray<Boolean> buildDuplicateFlags(List<MediaSource> mediaSources) { 
     SparseArray<Boolean> duplicateFlags = new SparseArray<Boolean>(); 
     IdentityHashMap<MediaSource, Void> sources = new IdentityHashMap<>(mediaSources.size()); 
     for (int i = 0; i < mediaSources.size(); i++) { 
      MediaSource source = mediaSources.get(i); 
      if (!sources.containsKey(source)) { 
       sources.put(source, null); 
       duplicateFlags.append(i,false); 
      } else { 
       duplicateFlags.append(i,true); 
      } 
     } 
     return duplicateFlags; 
    } 

    /** 
    * A {@link Timeline} that is the concatenation of one or more {@link Timeline}s. 
    */ 
    public static final class DynamicTimeline extends AbstractConcatenatedTimeline { 

     private final SparseArray<Timeline> timelines; 
     private final int[] sourcePeriodOffsets; 
     private final int[] sourceWindowOffsets; 
     private final boolean isRepeatOneAtomic; 

     public DynamicTimeline(SparseArray<Timeline> timelines, boolean isRepeatOneAtomic) { 
      super(timelines.size()); 
      int[] sourcePeriodOffsets = new int[timelines.size()]; 
      int[] sourceWindowOffsets = new int[timelines.size()]; 
      long periodCount = 0; 
      int windowCount = 0; 
      for (int i = 0; i < timelines.size(); i++) { 
       Timeline timeline = timelines.get(i); 
       periodCount += timeline.getPeriodCount(); 
       Assertions.checkState(periodCount <= Integer.MAX_VALUE, 
        "ConcatenatingMediaSource children contain too many periods"); 
       sourcePeriodOffsets[i] = (int) periodCount; 
       windowCount += timeline.getWindowCount(); 
       sourceWindowOffsets[i] = windowCount; 
      } 
      this.timelines = timelines; 
      this.sourcePeriodOffsets = sourcePeriodOffsets; 
      this.sourceWindowOffsets = sourceWindowOffsets; 
      this.isRepeatOneAtomic = isRepeatOneAtomic; 
     } 

     @Override 
     public int getWindowCount() { 
      return sourceWindowOffsets[sourceWindowOffsets.length - 1]; 
     } 

     @Override 
     public int getPeriodCount() { 
      return sourcePeriodOffsets[sourcePeriodOffsets.length - 1]; 
     } 

     @Override 
     public int getNextWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode) { 
      if (isRepeatOneAtomic && repeatMode == Player.REPEAT_MODE_ONE) { 
       repeatMode = Player.REPEAT_MODE_ALL; 
      } 
      return super.getNextWindowIndex(windowIndex, repeatMode); 
     } 

     @Override 
     public int getPreviousWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode) { 
      if (isRepeatOneAtomic && repeatMode == Player.REPEAT_MODE_ONE) { 
       repeatMode = Player.REPEAT_MODE_ALL; 
      } 
      return super.getPreviousWindowIndex(windowIndex, repeatMode); 
     } 

     @Override 
     public int getChildIndexByPeriodIndex(int periodIndex) { 
      return Util.binarySearchFloor(sourcePeriodOffsets, periodIndex, true, false) + 1; 
     } 

     @Override 
     protected int getChildIndexByWindowIndex(int windowIndex) { 
      return Util.binarySearchFloor(sourceWindowOffsets, windowIndex, true, false) + 1; 
     } 

     @Override 
     protected int getChildIndexByChildUid(Object childUid) { 
      if (!(childUid instanceof Integer)) { 
       return C.INDEX_UNSET; 
      } 
      return (Integer) childUid; 
     } 

     @Override 
     protected Timeline getTimelineByChildIndex(int childIndex) { 
      return timelines.get(childIndex); 
     } 

     @Override 
     public int getFirstPeriodIndexByChildIndex(int childIndex) { 
      return childIndex == 0 ? 0 : sourcePeriodOffsets[childIndex - 1]; 
     } 

     @Override 
     protected int getFirstWindowIndexByChildIndex(int childIndex) { 
      return childIndex == 0 ? 0 : sourceWindowOffsets[childIndex - 1]; 
     } 

     @Override 
     protected Object getChildUidByChildIndex(int childIndex) { 
      return childIndex; 
     } 

    } 

} 

ファイルがダウンロードされたときにチェックし、ダウンロード完了リスナーを設定するには、あなたがBroadcastReceiverを使用することができます。 A detailed example of how to set up the BroadcastReceiver is provided here.

関連する問題