HarmonyOS サンプル DistributedMusicPlayer 分散音楽プレーヤー

HarmonyOS サンプル DistributedMusicPlayer 分散音楽プレーヤー

[[419218]]

詳細については、以下をご覧ください。

51CTOとHuaweiが共同で構築したHongmengテクノロジーコミュニティ

https://harmonyos..com

DistributedMusicPlayer分散型音楽プレーヤー

導入

この例では、主にデータを移行して音楽の分散再生を実行する方法を示します。再生中の曲、再生の進行状況、再生ステータスの維持など、デバイス間での音楽再生の移行が実現します。

エフェクト表示

環境を構築する

DevEco Studio をインストールします。詳細については、DevEco Studio のダウンロードを参照してください。

DevEco Studio 開発環境をセットアップします。 DevEco Studio 開発環境はネットワーク環境に依存する必要があります。ツールを正常に使用するには、ネットワークに接続する必要があります。次の 2 つの状況に応じて開発環境を構成できます。

インターネットに直接アクセスできる場合は、HarmonyOS SDK をダウンロードするだけで済みます。

ネットワークがインターネットに直接アクセスできず、プロキシ サーバー経由でアクセスする必要がある場合は、「開発環境の構成」を参照してください。

ソースコードをダウンロードし、プロジェクトをインポートします。

コード構造

  1. config.json #グローバル設定ファイル
  2. ├─ジャワ
  3. │ └─オーホス
  4. │ └─サンプル
  5. │ └─分散音楽プレーヤー
  6. │ │ メインアビリティ.java
  7. │ │
  8. │ ├─スライス
  9. │ │ MainAbilitySlice.java #プレイヤーのメインアビリティスライス
  10. │ │
  11. │ └─ユーティリティ
  12. │ LogUtil.java #ログユーティリティクラス
  13. │ PlayerManager.java #プレイヤーマネージャー
  14. │ PlayerStateListener.java #プレイヤー状態リスナー
  15. └─リソース
  16. ├─ベース
  17. │ ├─要素
  18. │ │ 文字列.json
  19. │ │
  20. │ ├─グラフィック
  21. │ │ ボタンの背景.xml
  22. │ │
  23. │ ├─レイアウト
  24. │ │ main_ability_slice.xml #プレイヤーページレイアウト
  25. │ │
  26. │ └─メディア #ポスター・ボタン画像リソース
  27. │ アルバム.png
  28. │ アルバム2.png
  29. │ bg_blurry.png
  30. │ アイコン.png
  31. │ ic_himusic_next.png
  32. │ ic_himusic_pause.png
  33. │ ic_himusic_play.png
  34. │ ic_himusic_previous.png
  35. │ リモートプレイ選択.png
  36. └─rawfile #Song メディアリソース
  37. ホーミー.mp3
  38. ホームイ.wav
  39. テクノロジー.mp3
  40. テクノロジー.wav

実装手順

1. デバイス間の移行の標準手順を実装するには、HarmonyOSサンプル - AbilityInteractionデバイス移行を参照してください。

2. プレイヤーマネージャー PlayerManager を実装する

2.1.プレーヤーのステータスを定義します(再生、一時停止、完了、再生中など)。

  1. プライベート静的最終int PLAY_STATE_PLAY = 0x0000001;
  2. プライベート静的最終int PLAY_STATE_PAUSE = 0x0000002;
  3. プライベート静的最終int PLAY_STATE_FINISH = 0x0000003;
  4. プライベート静的最終int PLAY_STATE_PROGRESS = 0x0000004;

2.2.再生、一時停止、曲の切り替え、再生の進行状況の更新などの基本的なメソッドを実装します。

メディアリソースの設定、再生の進行状況を定期的に更新、再生時間の合計の取得など、補助的な方法もいくつかあります。

Player/Timer/カスタムPlayerStateListener/EventHandlerイベント処理/PlayCallBackプレーヤーコールバッククラスを使用する必要があります

  1. /**
  2. * 遊ぶ
  3. */
  4. パブリックボイドプレイ(){
  5. 試す {
  6. 準備が完了している場合
  7. LogUtil.error(TAG, "準備失敗" );
  8. 戻る;
  9. }
  10. // 再生が開始された場合は true を返します。それ以外の場合はfalseを返します
  11. 再生する場合は、
  12. LogUtil.error(TAG, "再生失敗" );
  13. 戻る;
  14. }
  15. タスクを開始します。
  16. ハンドラ.sendEvent(PLAY_STATE_PLAY);
  17. } キャッチ (IllegalArgumentException e) {
  18. LogUtil.error(TAG, e.getMessage());
  19. e.printStackTrace();
  20. }
  21. }
  22.  
  23. /**
  24. * 一時停止
  25. */
  26. パブリックボイド一時停止(){
  27. (!musicPlayer.pause())の場合{
  28. LogUtil.info(TAG, "一時停止失敗" );
  29. 戻る;
  30. }
  31. // タイミングを停止
  32. タスクを終了します。
  33. //
  34. ハンドラ.sendEvent(PLAY_STATE_PAUSE);
  35. }
  36. /**
  37. * 音楽を切り替える
  38. *
  39. * @param uri 音楽 uri
  40. */
  41. パブリックvoid switchMusic(String uri) {
  42. 現在のUri = uri;
  43. //リソースを設定する
  44. setResource(現在のUri);
  45. //遊ぶ
  46. 遊ぶ();
  47. }
  48.  
  49. /**
  50. * 再生位置を変更する
  51. * 現在の再生の進行状況を更新します
  52. *
  53. * @param currentTime現在の 時間 
  54. */
  55. パブリックvoid rewindTo( int currentTime) {
  56. musicPlayer.rewindTo(現在の時間 * 1000);
  57. }
  58.  
  59. /**
  60. *ソースを設定する
  61. *
  62. * @param uri 音楽 uri
  63. */
  64. パブリックvoid setResource(String uri) {
  65. LogUtil.info(TAG, "setResource,uri: " + uri);
  66. 試す {
  67. RawFileEntry rawFileEntry = context.getResourceManager().getRawFileEntry(uri);
  68. ベースファイル記述子 baseFileDescriptor = rawFileEntry.openRawFileDescriptor();
  69. //LogUtil.info(TAG, "setResource,baseFileDescriptor : " + baseFileDescriptor);
  70. musicPlayer.setSource(baseFileDescriptor) の場合:
  71. LogUtil.info(TAG, "uri が無効です" );
  72. 戻る;
  73. }
  74. //再生環境を準備し、メディア データをバッファリングします。
  75. isPrepared = musicPlayer.prepare ();
  76. LogUtil.info(TAG, "setResource,isPrepared: " + isPrepared);
  77. //曲名
  78. 文字列listenerUri = currentUri。部分文字列(currentUri.lastIndexOf( "/" ) + 1、currentUri.lastIndexOf( "." ));
  79. プレイヤーステートリスナーのUriを設定します。
  80. LogUtil.info(TAG, "setResource,listenerUri: " +listenerUri);
  81. } キャッチ (IOException e) {
  82. LogUtil.error(TAG, "io例外" );
  83. }
  84. }
  85. /**
  86. * スケジュールされたイベント通知は進行状況バーを更新します
  87. */
  88. プライベートvoid startTask() {
  89. LogUtil.debug(TAG, "startTask" );
  90. タスクを終了します。
  91. タイマータスク = 新しいタイマータスク() {
  92. @オーバーライド
  93. パブリックボイド実行(){
  94. ハンドラ.sendEvent(PLAY_STATE_PROGRESS);
  95. }
  96. };
  97. タイマー = 新しいタイマー();
  98. timer.schedule(timerTask, DELAY_TIME, PERIOD);
  99. }
  100.  
  101. プライベートvoid終了タスク() {
  102. LogUtil.debug(タグ、 "finishTask" );
  103. if (タイマー != null && タイマータスク != null ) {
  104. タイマーをキャンセルします。
  105. タイマー = null ;
  106. タイマータスク = null ;
  107. }
  108. }

2.3.PlayerStateListener プレイヤー状態リスナーには次のメソッドがあります。

onPlaySuccessは再生が成功したときに呼び出されます

onPauseSuccessは一時停止時に呼び出されます

onPositionChangeは進行状況が変わったときに呼び出されます

onMusicFinishedは音楽の再生が完了したときに呼び出されます

onUriSetはリソースが設定されたときに呼び出されます

  1. /**
  2. * プレイヤーステートリスナー
  3. */
  4. パブリックインターフェース PlayerStateListener {
  5. void onPlaySuccess( int totalTime);
  6.  
  7. void onPauseSuccess();
  8.  
  9. void onPositionChange( int currentTime);
  10.  
  11. void onMusicFinished();
  12.  
  13. void onUriSet(文字列);
  14. }

2.4.PlayCallBack プレーヤー コールバック クラスは、Player.IPlayerCallback インターフェイスと次のメソッドを実装します。

onPrepared メディア ファイルの再生準備ができたときに呼び出されます。

onMessage は、プレーヤーのメッセージまたはアラートを受信したときに呼び出されます。

onError は、プレーヤーのエラー メッセージを受信したときに呼び出されます。

ビデオサイズが変更されると、onResolutionChanged が呼び出されます。

再生が完了すると onPlayBackComplete が呼び出されます。

onRewindToComplete Player.rewindTo(long) によって再生位置が変更されたときに呼び出されます。

バッファリングのパーセンテージが更新されると、onBufferingChange が呼び出されます。

新しいタイムドメタデータが利用可能になると、onNewTimedMetaData が呼び出されます。

onMediaTimeIncontinuity は、再生中にエラーが発生したり、Player.rewindTo(long) によって再生位置が変更されたり、再生速度が急激に変更されたりなど、メディアの時間の連続性が中断されたときに呼び出されます。

  1. /**
  2. * 再生が完了したとき、再生位置が変更されたとき、およびビデオ サイズが変更されたときに、メディア プレーヤーのコールバックを提供します。
  3. */
  4. プライベートクラス PlayCallBack は Player.IPlayerCallback を実装します {
  5.  
  6. /**
  7. * メディア ファイルの再生準備ができたときに呼び出されます。
  8. */
  9. @オーバーライド
  10. パブリックvoid onPrepared() {
  11. LogUtil.info(TAG, "onPrepared" );
  12. }
  13.  
  14. /**
  15. * プレイヤーのメッセージまたはアラートを受信したときに呼び出されます。
  16. *
  17. * @パラメータ型
  18. * @param 追加
  19. */
  20. @オーバーライド
  21. パブリックvoid onMessage( int型、 int追加) {
  22. LogUtil.info(タグ、 "onMessage" + タイプ + "-" + 追加);
  23. }
  24.  
  25.  
  26. /**
  27. * プレーヤーのエラー メッセージを受信したときに呼び出されます。
  28. *
  29. * @param エラータイプ
  30. * @param エラーコード
  31. */
  32. @オーバーライド
  33. パブリックvoid onError( int errorType, int errorCode) {
  34. LogUtil.info(タグ、 "onError " + errorType + "-" + errorCode);
  35. }
  36.  
  37. /**
  38. * ビデオサイズが変更されたときに呼び出されます。
  39. *
  40. * @param 幅
  41. * @param 高さ
  42. */
  43. @オーバーライド
  44. パブリックvoid onResolutionChanged( int幅、 int高さ) {
  45. LogUtil.info(タグ、 "onResolutionChanged" + 幅 + "-" + 高さ);
  46. }
  47.  
  48. /**
  49. * 再生が完了したときに呼び出されます。
  50. */
  51. @オーバーライド
  52. パブリックvoid onPlayBackComplete() {
  53. //自動的に呼び出されませんか? ? ? ?
  54. LogUtil.info(タグ、 「onPlayBackComplete----------------」 );
  55. ハンドラ.sendEvent(PLAY_STATE_FINISH);
  56.  
  57. }
  58.  
  59. /**
  60. * Player.rewindTo(long) によって再生位置が変更されたときに呼び出されます。
  61. */
  62. @オーバーライド
  63. パブリックvoid onRewindToComplete() {
  64. LogUtil.info(タグ、 "onRewindToComplete" );
  65. }
  66.  
  67. /**
  68. * バッファのパーセンテージが更新されたときに呼び出されます。
  69. *
  70. * @param パーセント
  71. */
  72. @オーバーライド
  73. パブリックvoid onBufferingChange( intパーセント){
  74. LogUtil.info(タグ、 「onBufferingChange:」 + パーセント);
  75. }
  76.  
  77. /**
  78. * 新しいタイムドメタデータが利用可能になったときに呼び出されます。
  79. *
  80. * @param mediaTimedMetaData
  81. */
  82. @オーバーライド
  83. パブリックvoid onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) {
  84. LogUtil.info(タグ、 "onNewTimedMetaData" );
  85. }
  86.  
  87.  
  88. /**
  89. * 再生中にエラーが発生したとき、Player.rewindTo(long) によって再生位置が変更されたとき、再生速度が急激に変更されたときなど、メディアの時間連続性が中断されたときに呼び出されます。
  90. *
  91. * @param メディア時間情報
  92. */
  93. @オーバーライド
  94. パブリックvoid onMediaTimeIncontinuity(Player.MediaTimeInfo mediaTimeInfo) {
  95. LogUtil.info(タグ、 "onNewTimedMetaData" );
  96. }
  97. }

3. MainAbilitySliceはPlayerStateListenerとIAbilityContinuationインターフェースを実装する

  1. パブリッククラス MainAbilitySlice は AbilitySlice を拡張し、PlayerStateListener、IAbilityContinuation を実装します {
  2. ...

3.1. PlayerStateListenerインターフェースメソッドを実装する

  1. @オーバーライド
  2. パブリックvoid onPlaySuccess( int totalTime) {
  3. LogUtil.debug(タグ、 "onPlaySuccess" );
  4. //アイコンを設定する
  5. musicPlayButton.setPixelMap(ResourceTable.Media_ic_himusic_pause);
  6. //合計継続時間テキストを設定する
  7. this.totalTimeText.setText(getTime(totalTime));
  8. //プログレスバーを設定する
  9. slider.setMaxValue(合計時間);
  10. //現在の曲のポスターを設定する
  11. musicPosters.setPixelMap(posters[currentPos]);
  12. }
  13.  
  14. @オーバーライド
  15. パブリックvoid onPauseSuccess() {
  16. LogUtil.debug(TAG, "onPauseSuccess" );
  17. //アイコンを設定する
  18. musicPlayButton.setPixelMap(ResourceTable.Media_ic_himusic_play);
  19. }
  20.  
  21. @オーバーライド
  22. パブリックvoid onUriSet(文字列) {
  23. LogUtil.debug(タグ、 "onUriSet" );
  24. //曲のタイトルを設定する
  25. musicNameText.setText(名前);
  26. }
  27.  
  28. @オーバーライド
  29. パブリックvoid onPositionChange( int currentTime) {
  30. 現在の時間 < 合計時間){
  31. LogUtil.info(TAG, "onPositionChange currentTime = " + currentTime+ ",totalTime=" +totalTime);
  32. this.currentTime = 現在の時刻;
  33. //再生時間のテキストを設定する
  34. this.currentTimeText.setText(getTime(currentTime));
  35. //プログレスバーの現在の再生時間を設定する
  36. スライダーの進行状況を設定します。
  37. }それ以外{
  38. LogUtil.info(TAG, "onPositionChange, 現在の曲の終了" );
  39.  
  40. //プレーヤーアイコンを設定する
  41. musicPlayButton.setPixelMap(ResourceTable.Media_ic_himusic_play);
  42. }
  43. }
  44.  
  45. /**
  46. *音楽の再生が終了したときに呼び出されるはずですが、呼び出されていません
  47. */
  48. @オーバーライド
  49. パブリックvoid onMusicFinished() {
  50. //TODO???????????
  51. LogUtil.debug(TAG, "onMusicFinished" );
  52. 現在の位置 = 現在の位置 == 0 ? 1 : 0;
  53. currentUri = musics[currentPos];
  54. //曲を切り替える
  55. playerManager.switchMusic(現在のUri);
  56. //合計時間
  57. totalTime=playerManager.getTotalTime();
  58. }

3.2. IABilityContinuation インターフェース メソッドの実装

  1. @オーバーライド
  2. パブリックブールonStartContinuation() {
  3. LogUtil.debug(TAG, "onStartContinuation" );
  4. 戻る 真実;
  5. }
  6.  
  7. @オーバーライド
  8. パブリックブールonSaveData(IntentParamsintentParams) {
  9. LogUtil.debug(タグ、 "onSaveData" );
  10. //
  11. パラメータを KEY_CURRENT_TIME に設定します。
  12. KEY_POSITION に現在の位置を設定します。
  13. intentParams.setParam(KEY_PLAY_STATE、String.valueOf(playerManager.isPlaying()));
  14. LogUtil.info(タグ、 "onSaveData:" + 現在の時刻);
  15. 戻る 真実;
  16. }
  17.  
  18. @オーバーライド
  19. パブリックブールonRestoreData(IntentParamsintentParams) {
  20. LogUtil.debug(タグ、 "onRestoreData" );
  21. if (!(intentParams.getParam(KEY_POSITION) のインスタンスがInteger の場合)) {
  22. 戻る 間違い;
  23. }
  24. if (!(intentParams.getParam(KEY_CURRENT_TIME) のインスタンスがInteger の場合)) {
  25. 戻る 間違い;
  26. }
  27. if (!(intentParams.getParam(KEY_PLAY_STATE) のインスタンスの文字列)) {
  28. 戻る 間違い;
  29. }
  30.  
  31. //データを復元し、移行されたパラメータ(再生位置、時間、再生ステータス)を取得します
  32. 現在の位置 = ( int ) intentParams.getParam(KEY_POSITION);
  33. 現在の時刻 = ( int ) intentParams.getParam(KEY_CURRENT_TIME);
  34. オブジェクトオブジェクト = intentParams.getParam(KEY_PLAY_STATE);
  35.  
  36.  
  37. if (オブジェクトインスタンスの文字列) {
  38. isPlaying = Boolean.parseBoolean((String) オブジェクト);
  39. }
  40. isInteractionPlay = true ;
  41. LogUtil.info(タグ、 「onRestoreData:」 + 現在の時刻);
  42. 戻る 真実;
  43. }
  44.  
  45. @オーバーライド
  46. パブリックvoid onCompleteContinuation( int i) {
  47. 終了();
  48. }

3.3. ValueChangedListenerImplの進捗値変更のリスナーイベントを定義します。

Slider.ValueChangedListenerインターフェースメソッドを実装する

  1. /**
  2. *プログレスバーの値の変化を監視するイベント
  3. */
  4. プライベートクラス ValueChangedListenerImpl は Slider.ValueChangedListener を実装します {
  5. @オーバーライド
  6. パブリックvoid onProgressUpdated(スライダー slider, int progress, boolean fromUser) {
  7. 現在の時間 = 進行状況;
  8. }
  9.  
  10. @オーバーライド
  11. パブリックvoid onTouchStart(スライダー スライダー) {
  12. LogUtil.debug(TAG, "onTouchStart" );
  13. }
  14.  
  15. @オーバーライド
  16. パブリックvoid onTouchEnd(スライダー スライダー) {
  17. LogUtil.debug(TAG, "onTouchEnd" );
  18. //再生の進行状況を素早く変更する
  19. playerManager.rewindTo(現在の時間);
  20. //現在の再生時間
  21. currentTimeText.setText(getTime(currentTime));
  22. }
  23. }

3.4.移行データのKEY、音楽の現在の再生時間、再生中の曲のインデックス(位置)、再生ステータスを定義します。

  1. プライベート静的最終文字列 KEY_CURRENT_TIME = "main_ability_slice_current_time" ;
  2. プライベート静的最終文字列 KEY_POSITION = "main_ability_slice_position" ;
  3. プライベート静的最終文字列 KEY_PLAY_STATE = "main_ability_slice_play_state" ;
  4. プライベートint現在の位置 = 0;
  5. プライベート文字列 currentUri;
  6. //インタラクティブ再生かどうかにかかわらず、 trueリモート移行リカバリを意味します
  7. プライベートブール値 isInteractionPlay;
  8. プライベートint現在の時刻;
  9. //現在再生中の曲の合計時間
  10. プライベートint合計時間;
  11. プライベートブール値 isPlaying;

3.5.再生する音楽の URI を定義します。ここに2曲とそれに対応するポスターがあります。

  1. プライベート静的最終文字列 URI1 = "resources/rawfile/Technology.wav" ;
  2. プライベート静的最終文字列 URI2 = "resources/rawfile/Homey.wav" ;
  3. プライベート最終String[] music = {URI1, URI2};
  4. プライベート最終int [] ポスター = {ResourceTable.Media_album、ResourceTable.Media_album2};

3.6.onStartはデータの初期化を完了します

  1. @オーバーライド
  2. パブリックvoid onStart(インテント インテント) {
  3. super.onStart(インテント);
  4. super.setUIContent(ResourceTable.Layout_main_ability_slice);
  5.  
  6. コンポーネントを初期化します。
  7.  
  8. initMedia();
  9.  
  10. UI を更新します。
  11. }

インターフェースコンポーネントを初期化し、対応するボタン監視イベントを実装する

再生または一時停止、前の曲、次の曲、移行、進行状況バーの進行状況変更イベントをリッスンします

  1. /**
  2. * インターフェースコンポーネントを初期化し、対応するボタン監視イベントを実装する
  3. * 再生または一時停止、前の曲、次の曲、移行、進行状況バーの進行状況変更イベントをリッスンします
  4. */
  5. プライベートvoid initComponents() {
  6. LogUtil.debug(タグ、 "initComponents" );
  7. musicNameText = (テキスト) findComponentById(ResourceTable.Id_music_name);
  8. currentTimeText = (テキスト) findComponentById(ResourceTable.Id_play_progress_time);
  9. totalTimeText = (テキスト) findComponentById(ResourceTable.Id_play_total_time);
  10.  
  11. musicPosters = (画像) findComponentById(ResourceTable.Id_music_posters);
  12.  
  13. musicPlayButton = (画像) findComponentById(ResourceTable.Id_music_play_btn);
  14. コンポーネント ID を検索します (ResourceTable.Id_remote_play)。クリックされたリスナーを設定します (this::continueAbility);
  15. コンポーネント ID を検索します (ResourceTable.Id_music_play_prev_btn)。クリックされたリスナーを設定します (this::prevMusic);
  16. コンポーネント ID を検索します (ResourceTable.Id_music_play_next_btn)。クリックされたリスナーを設定します (this::nextMusic);
  17.  
  18. musicPlayButton.setClickedListener(this::playOrPauseMusic);
  19.  
  20. //
  21. スライダー = (スライダー) findComponentById(ResourceTable.Id_play_progress_bar);
  22. スライダーにValueChangedListenerを設定します。
  23. }
  24.  
  25. プライベートvoid continueAbility(コンポーネントコンポーネント) {
  26. 試す {
  27. 継続能力();
  28. } キャッチ (IllegalStateException e) {
  29. LogUtil.info(TAG、e.getMessage());
  30. }
  31. }
  32.  
  33. /**
  34. * 前の
  35. * @param コンポーネント
  36. */
  37. プライベートvoid prevMusic(コンポーネントコンポーネント) {
  38. 現在の位置 = 現在の位置 == 0 ? 1 : 0;
  39. currentUri = musics[currentPos];
  40. //
  41. playerManager.switchMusic(現在のUri);
  42. //合計期間
  43. totalTime=playerManager.getTotalTime();
  44. }
  45.  
  46. /**
  47. * 次
  48. * @param コンポーネント
  49. */
  50. プライベートvoid nextMusic(コンポーネントコンポーネント) {
  51. 現在の位置 = 現在の位置 == 0 ? 1 : 0;
  52. currentUri = musics[currentPos];
  53. //音楽を切り替える
  54. playerManager.switchMusic(現在のUri);
  55. //合計期間
  56. totalTime=playerManager.getTotalTime();
  57. }
  58.  
  59. /**
  60. * 音楽を再生または一時停止する
  61. * @param コンポーネント
  62. */
  63. プライベートvoid playOrPauseMusic(コンポーネントコンポーネント) {
  64. //
  65. 再生または一時停止();
  66. }
  67.  
  68. /**
  69. * 再生または一時停止
  70. */
  71. プライベートvoid再生または一時停止(){
  72.  
  73. LogUtil.debug(TAG, "playOrPause,playerManager:" +playerManager);
  74. 試す {
  75. //
  76. プレイヤーマネージャーが再生中の場合(){
  77. LogUtil.debug(TAG, "playOrPause pause" );
  78. プレイヤーマネージャーを一時停止します。
  79. }それ以外{
  80. //リソースを設定する
  81. playerManager.setResource(currentUri);
  82. //進行状況を設定する
  83. playerManager.rewindTo(現在の時間);
  84. プレイヤーマネージャーを再生します。
  85. LogUtil.debug(TAG, "playOrPause 再生" );
  86. }
  87. } キャッチ (例外 e) {
  88. LogUtil.error(TAG, "playOrPause" );
  89. e.printStackTrace();
  90. }
  91. }

3.7.メディアオブジェクトの初期化

現在再生中の曲リソース、プレーヤーマネージャー

  1. /**
  2. * メディアオブジェクトを初期化する
  3. * 現在再生中の曲のリソース
  4. * プレイヤーマネージャー
  5. */
  6. プライベートvoid initMedia() {
  7. LogUtil.debug(タグ、 "initMedia" );
  8. //現在のメディアURI
  9. currentUri = musics[currentPos];
  10. LogUtil.debug(TAG, "initMedia,currentUri:" +currentUri);
  11. // playerManager を初期化する
  12. プレイヤーマネージャー = 新しいプレイヤーマネージャー (getApplicationContext()、現在の Uri);
  13.  
  14. // 弱参照オブジェクトは、参照先オブジェクトの終了、ファイナライズ、およびリサイクルを妨げません。弱参照は、正規のマッピングを実装するために最もよく使用されます。
  15. WeakReference<PlayerStateListener> playerStateListener = 新しい WeakReference<>(this);
  16. //ステータスリスナーを設定する
  17. プレイヤーの状態リスナーを設定します。
  18. // プレイヤー情報を初期化する
  19. プレイヤーマネージャーを初期化します。
  20. LogUtil.debug(タグ、 「initMedia FINISH」 );
  21. }

3.8.リモート移行後に再生インターフェースを復元する

プレーヤーの再生進行状況、再生ステータス、ポスター、現在の時間と合計時間、スライダーの再生進行状況を復元します

  1. /**
  2. * リモート移行後に再生を再開し、プレーヤーの再生進行状況を復元します
  3. * UIインターフェースの更新
  4. */
  5. プライベートvoid updateUI() {
  6. LogUtil.debug(タグ、 「updateUI」 );
  7. //ポスター
  8. musicPosters.setPixelMap(posters[currentPos]);
  9. //現在の時刻と合計継続時間
  10. currentTimeText.setText(getTime(currentTime));
  11. totalTimeText.setText(getTime(playerManager.getTotalTime()));
  12. // プレイの進行状況
  13. slider.setMaxValue(playerManager.getTotalTime());
  14. スライダーの進行状況を設定します。
  15.  
  16. //合計時間
  17. totalTime=playerManager.getTotalTime();
  18.  
  19. //リモート移行リカバリ
  20. if (isInteractionPlay) {
  21. LogUtil.debug(TAG, "remotePlay,rewindTo:" +currentTime);
  22. playerManager.rewindTo(現在の時間);
  23. if (!isPlaying) {
  24. 戻る;
  25. }
  26. //遊ぶ
  27. プレイヤーマネージャーを再生します。
  28. }
  29. }

問題の概要

1. 音楽の再生が終了したときに onMusicFinished を呼び出す必要がありますが、ほとんどの場合は呼び出されず、たまにしか呼び出されません。コンピュータのパフォーマンスが追いつかないからでしょうか?

2. ソースコードでアプリケーションを起動した後、クリックしてもビデオが再生されない問題を最適化しました。

3. 現在の曲を再生した後に再生アイコンを更新するようにプレーヤーを最適化しました

4. 関連メモを追加

添付ファイルからDistributedMusicPlayer.zipをダウンロードしてください。

詳細については、以下をご覧ください。

51CTOとHuaweiが共同で構築したHongmengテクノロジーコミュニティ

https://harmonyos..com

<<:  Elastic、クラウドネイティブ環境のセキュリティ強化のためbuild.securityを買収

>>:  Longhorn、エンタープライズレベルのクラウドネイティブコンテナ分散ストレージのバックアップとリカバリ

推薦する

BigbirdWeb - 2.5 USD/1 GB RAM/20 GB SSD/200 GB トラフィック

bigbirdweb.com の特別プロモーション VPS をご紹介します。同社は 年に設立され、以...

モバイルモールシステムを構築する際にはどのような点に注意すべきでしょうか?

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますモバイルモ...

#まずはレビューを# hostdare-c3 データセンター/中国最適化/3.49 USD/512M メモリ VPS シンプルレビュー

Hostdare は本日、新しいデータセンターを発表しました。ロサンゼルスの C3 データセンターは...

OpenHarmony 分散ソフトバスプロセス分析 v1.0丨1。発見終了、リリースサービス

[[408690]]詳細については、以下をご覧ください。 51CTOとHuaweiが共同で構築したH...

VPSにスピードテストをインストールしてアップロードとダウンロードの速度をテストします

私は Debian/Ubuntu を使用することを好みます。ここでは、VPS で speedtest...

2012年湖南インターネットウェブマスター会議が8月11日に長沙で開催されました。

8月13日、2012年湖南インターネットウェブマスターカンファレンスが8月11日に長沙で成功裏に開催...

casbay: マレーシア VPS/マレーシア クラウド サーバー、月額 11.59 ドルから、帯域幅 100M、トラフィック無制限

Casbayは2010年に設立され、主にマレーシアとシンガポールでVPS、クラウドサーバー、外貨両替...

企業が今すぐデータセンターからクラウドプラットフォームに移行すべき理由

クラウドへのシームレスで成功した移行を確実に行うには、企業はデータセンターの移行に伴う潜在的な複雑さ...

低価格がなければ、Viya と Li Jiaqi はどうやってユーザーを維持するのでしょうか?

Eコマースのライブストリーミングに新たな「ルーチン」が誕生しました。ライブストリーミングルームが依然...

budgetvm-新しいクラウドサーバーオンライン/SSD/10g DDoS保護/4つのコンピュータルーム

budgetvm のクラウド サーバー ホスティングからメールを受け取りました。SSD ハード ドラ...

私の人生哲学はこれらの広告から学んだ

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービステキスト | 脳を燃やす...

毎日の話題:モバイルインターネットの波でシャンダの「伝説」時代は終わった

A5ウェブマスターネットワーク(www.admin5.com)は4月18日、かつてのインターネット大...

検索後半:WeChatは大規模な検索を行うか?

先ほど終了したWeChatオープンクラスPROでは、WeChat検索には有望な未来があるという非常に...

APPが店頭から撤去されるも、小紅書は「大惨事を乗り越える」

販売中止となった小紅書は、コンテンツコンプライアンスの問題が発生している。小紅書は棚から撤去されまし...

COVID-19はクラウドとエッジコンピューティングを促進する可能性がある

PMMI Business Intelligence の新しいレポートによると、現在、大手 CPG ...