iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 19
1

這次想要練怎麼在手機上播放媒體,真的難! 最後整個是照著 Play Music in Ionic Capacitor apps 這篇文章在做練習。

npm install cordova-plugin-media
npm install @ionic-native/media
ionic cap sync

在 app.module 中 import。
我這邊卡了一陣子 原來我把 Media 放到 imports: 應該放在 providers:
這時候先跑 ionic cap open android 在 Android Studio 建置看看。
XDDD

music.page.html

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button defaultHref="/"></ion-back-button>
    </ion-buttons>
    <ion-title>music</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-thumbnail>
    <img src="assets/album/BLACKPINK.jpg" />
  </ion-thumbnail>
  <p class="song-name">Lovesick Girls</p>

  <ion-range min="0" max="{{duration}}" [(ngModel)]="position"> </ion-range>

  <div class="playtime">
    <ion-label class="start">{{ displayPosition }}</ion-label>
    <ion-label class="end" *ngIf="duration == -1">--:--</ion-label>
    <ion-label class="end" *ngIf="duration != -1"
      >{{ displayDuration }}</ion-label
    >
  </div>

  <ion-grid>
    <ion-row style="height: 100%">
      <ion-col>
        <div class="player">
          <ion-button fill="clear" (click)="controlSeconds('back')"> 
            <ion-icon name="play-back"></ion-icon>
          </ion-button>

          <ion-button *ngIf="!isPlaying" (click)="play()">
            <ion-icon name="play-outline" class="darkColor"></ion-icon>
          </ion-button>
          <ion-button *ngIf="isPlaying" (click)="pause()">
            <ion-icon name="pause-outline" class="darkColor"></ion-icon>
          </ion-button>

          <ion-button fill="clear" (click)="controlSeconds('forward')">
            <ion-icon name="play-forward"></ion-icon>
          </ion-button>
        </div>
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-content>

music.page.ts
getMusic() 主要只是取得音樂的時間而已。
按下播放鍵 (執行 play 方法) 執行 setToPlayback() 才真正開始放音樂。
在 setToPlayback() 中,也可以取得目前的狀態,看是否是在播放中。 最後執行 getAndSetCurrentAudioPosition(); 主要是設置 ion-range 元件,音樂播放到哪裡。

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Media, MediaObject } from '@ionic-native/media/ngx';
import { Platform } from '@ionic/angular';

@Component({
  selector: 'app-music',
  templateUrl: './music.page.html',
  styleUrls: ['./music.page.scss'],
})
export class MusicPage implements OnInit, OnDestroy {
  myMusic: MediaObject;
  duration: any = -1;
  isPlaying = false;
  isReady = false;
  getDurationInterval: any;
  getPositionInterval: any;
  position: any = 0;
  displayPosition: any = '00:00';
  displayDuration: any = '00:00';

  constructor(public platform: Platform, private media: Media) {}

  ngOnInit() {
    this.platform.ready().then((res) => {
      this.getMusic();
    });
  }
  ngOnDestroy(): void {
    this.stop();
  }

  getMusic() {
    this.myMusic = this.media.create(
      '/android_asset/public/assets/album/Lovesick Girls.mp3'
    );
    this.myMusic.play();
    this.myMusic.setVolume(0.0);

    let temp = this.duration; // 持續時間
    this.getDurationInterval = setInterval(() => {
      if (this.duration === -1 || !this.duration) {
        this.duration = ~~this.myMusic.getDuration();
      } else {
        if (this.duration !== temp) {
          temp = this.duration;
        } else {
          this.myMusic.stop();
          this.myMusic.release();

          clearInterval(this.getDurationInterval);
          this.displayDuration = this.toHHMMSS(this.duration);
          this.setToPlayback();
        }
      }
    }, 100);
  }

  play() {
    this.myMusic.play();
  }

  pause() {
    this.myMusic.pause();
  }

  stop() {
    this.myMusic.stop();
    this.myMusic.release();
  }

  setToPlayback() {
    this.myMusic = this.media.create(
      '/android_asset/public/assets/album/Lovesick Girls.mp3'
    );
    this.myMusic.onStatusUpdate.subscribe((status) => {
      switch (status) {
        case 1:
          break;
        case 2:
          this.isPlaying = true;
          break;
        case 3:
          this.isPlaying = false;
          break;
        case 4:
        default:
          this.isPlaying = false;
          break;
      }
    });
    this.isReady = true;
    this.getAndSetCurrentAudioPosition();
  }

  getAndSetCurrentAudioPosition() {
    const diff = 1;
    const self = this;
    this.getPositionInterval = setInterval(() => {
      const lastPosition = self.position;
      this.myMusic.getCurrentPosition().then((position) => {
        if (position >= 0 && position < self.duration) {
          if (Math.abs(lastPosition - position) >= diff) {
            this.myMusic.seekTo(lastPosition * 1000);
          } else {
            self.position = position;
            this.displayPosition = this.toHHMMSS(self.position);
          }
        } else if (position >= self.duration) {
          self.stop();
          self.setToPlayback();
        }
      });
    }, 100);
  }

  controlSeconds(action) {
    const step = 5;
    const numberRange = this.position;
    switch (action) {
      case 'back':
        this.position = numberRange < step ? 0.001 : numberRange - step;
        break;
      case 'forward':
        this.position = numberRange + step < this.duration ? numberRange + step : this.duration;
        break;
      default:
        break;
    }
  }

  toHHMMSS(secs) {
    const secNum = parseInt(secs, 10);
    const minutes = Math.floor(secNum / 60) % 60;
    const seconds = secNum % 60;

    return [minutes, seconds]
      .map((v) => (v < 10 ? '0' + v : v))
      .filter((v, i) => v !== '00' || i >= 0)
      .join(':');
  }
}

Yes

真心覺得一個 Player 不好做QQ...

參考:
Play Music in Ionic Capacitor apps


上一篇
Cart & Modal
下一篇
Music & File
系列文
純粹沒有寫過行動,Ionic 學習中...30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言