Posted at
kintoneDay 23

kintoneでミュージックプレイヤーを作ってみた

🎄こちらは kintone Advent Calendar 2018 23日目 の記事です。

kintone Advent Calendar 2018 オーナーのBBです。

まずは、kintone Advent Calendarに参加してくださったみなさまへ感謝の気持ちを。

参加していただき、ありがとうございます!!

(来年も開催したいと思っているのでぜひご協力を! めざせ Part2!)


はじめにの前に

このkintone Advent Calendarを立ててすぐに

初日でもなく最終日でもなくこの 23日 を選んだのには理由があります。

それは、、







23日が My Birthday だからです🎉🎉







え? それだけかって?

はい、それだけです。


はじめに

では気を取り直して、

「ネタ系で頑張る」と最初から宣言してしまった以上、ネタで攻めさせていただきました。

タイトルからも分かる通り、「え?それkintoneでやる必要あるの?」って内容です 笑

ただ、普通にやるだけではつまらないので

勉強も兼ねて今流行りの 「Vue.js」 を使ってみました。


完成イメージ



※ 小さくてすみません m(_ _)m

※ そして僕の趣味丸出しですみません m(_ _)m

GitHubPagesにも同じやつを作ってみました。

https://rybb.github.io/MusicPlayer/

※ 著作フリーなやつに差し替えています。ついでにクリスマスっぽくしています☃


きっかけ

なぜこのカスタマイズをしようと思ったかというと、


  • 2018年12月版で搭載されたモバイルカスタマイズビューを使ってみたかった


  • 業務以外でのkintoneの使い道を模索したかった

  • 去年あたりにも、実は音楽プレイヤー化に挑戦していた

という理由があります。

一番の理由はやはり 「モバイルカスタマイズビューを使ってみたかった」 ですね!


仕組み

仕組み自体はとてもシンプルです


  1. モバイルの一覧表示イベント(mobile.app.record.index.show)で発火🔥

  2. レコードを全件取得する (GET,records)

  3. 画像ファイル、音楽ファイルの Blob URL を取得する

  4. HTMLタグにそれらを埋め込む

  5. 下に全件リスト表示させて、クリックしたらTOPと変更する

みたいな動きです。


Blob URL

kintoneでは添付ファイルはBlob形式で保存されています。

なのでこのBlob URLを作ることで、いわゆる 直リンク が生成できるわけです。

Blob URLの取得方法は cybozu developer network に記事があります!

https://developer.cybozu.io/hc/ja/articles/202166180


アプリの作り方

では、さっそく作り方のご紹介を。

フィールドはこんな感じです

フィールド
フィールドコード
用途

添付ファイル
image
画像ファイル用

添付ファイル
music
音楽ファイル用

めっちゃシンプル


コード

GitHub にもあげています。


カスタマイズビュー用HTML

<style>

.main {
max-width: 500px;
margin: auto;
text-align:center;
}
.title {
margin: 1em;
cursor: pointer;
border-bottom:1px solid #555555;
}
#img {
height: 300px;
width: auto;
}
#list {
font-size: 1.5em;
margin: 0.5em;
}
audio {
width: 100%;
}
</style>
<body>
<div class=bg>
<div class="main">
<div id="app">
<div class="wrapper">
<div>
<img id="img" :src="imglink">
</div>
</div>
<div>
<a><audio :src="musiclink" v-on:ended="nextMusic" autoplay controls></audio></a>
</div>
</div>
<ol id="list">
<li class="title" v-for="item in items" v-on:click="changeMusic(item)">
{{ item.music.value[0].name }}
</li>
</ol>
</div>
</div>


app.js

// イベント発火とかメイン処理

(() => {
'use strict';
const mykintone = window.mykintone;

const events = [
'app.record.index.show',
'mobile.app.record.index.show'
];
kintone.events.on(events, async e => {
// カスタマイズビュー以外なら終了
if (!e.viewId === 5740139) {
return;
}

// kintoneのレコードを全件取得する
const kinData = await mykintone.getRecords(e.appId);
const records = kinData.records;

// 添付ファイルの直リンク生成
const URL = await mykintone.getImageMusicURL(records[0]);

// Vue.js
const app = new Vue({
el: '#app',
data: {
index: URL.index,
imglink: URL.img,
musiclink: URL.music,
},
methods: {
nextMusic: async function() {
let newURL;
const index = records.findIndex(obj => {
return obj.$id.value === this.index;
});
if (!records[index + 1]) {
newURL = await mykintone.getImageMusicURL(records[0]);
app.index = newURL.index;
app.imglink = newURL.img;
app.musiclink = newURL.music;
return;
}
newURL = await mykintone.getImageMusicURL(records[index + 1]);
app.index = newURL.index;
app.imglink = newURL.img;
app.musiclink = newURL.music;
}
}
});

new Vue({
el: '#list',
data: {
items: records
},
methods: {
changeMusic: async function(event) {
let newURL = await mykintone.getImageMusicURL(event);
app.index = newURL.index;
app.imglink = newURL.img;
app.musiclink = newURL.music;
}
}
});
});
})();



kin.js

// kintone API系の処理

(() => {
'use strict';

// kintoneのフィールドコードとか
const common = {
image: 'image',
music: 'music'
};

const xhr = new XMLHttpRequest();

// レコードを全件取得する処理
const getRecords = APPID => {
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {app: APPID})
.then(resp => {
return resp;
})
.catch(err => {
console.log('Error:kintone\n' + err);
});
};

// 添付ファイルの直リンクを作る関数
const filedownload = filekey => {
return new Promise((resolve, reject) => {
const url = '/k/v1/file.json?fileKey=' + filekey;
xhr.open('GET', url, true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.responseType = 'blob';
xhr.onload = () => {
// blobからURL生成
let blob = xhr.response;
let url = window.URL || window.webkitURL;
let file = url.createObjectURL(blob);
resolve(file);
};
xhr.onerror = () => {
reject('Error:XHR');
};
xhr.send();
});
};

// 画像ファイルと音楽ファイルの直リンク生成
const getImageMusicURL = DATA => {
return new Promise(async resolve => {
const index = DATA.$id.value;
let imageURL, musicURL;

// 画像ファイルの有無チェック
if (!DATA[common.image].value[0]) {
imageURL = null;
} else {
let imageFileKey = DATA[common.image].value[0].fileKey;
imageURL = await filedownload(imageFileKey);
}

// 音楽ファイルの有無チェック
if (!DATA[common.music].value[0]) {
musicURL = null;
} else {
let musicFileKey = DATA[common.music].value[0].fileKey;
musicURL = await filedownload(musicFileKey);
}

resolve({
index: index,
img: imageURL,
music: musicURL
});
});
};

window.mykintone = {};
window.mykintone.getRecords = getRecords;
window.mykintone.getImageMusicURL = getImageMusicURL;
})();


結構思うがままに書いていたので読みにくいかもです m(_ _)m


ポイント

結構大変でした。


  • 画像ファイルは <img>のsrcに埋め込めば表示される

  • 音楽ファイルは <audio>タグのsrcに埋め込めば、操作バーとして表示される

  • Vue.jsでリスト表示や再生ファイルの入れ替えを実現

  • カスタマイズビューに<style>タグ使えば、CSSも書ける

  • 音楽が終わったら次の曲を再生させている

Vue.js自体全然知らなかったので、ググりながら試してみた感じです

(Vue使う必要ある?って思うかもですが、、、これは僕の勉強のためです! 汗)


発展

以前、Qiitaに投稿したGoogleの画像検索API連携を使えば、

「歌手」「アルバム名」などを入力するフィールド追加で

自動で画像URLを取得 することもできそうです。

kintoneで画像検索API使ってみた

https://qiita.com/RyBB/items/b87a92815854ed5c74af


小ネタ

実はkintoneモバイル (モバイルアプリ)で再生すれば、

バックグラウンド再生 ができるんです!!

まさに音楽プレイヤー!


おわりに

Vue.jsの使い方がまだまだイマイチですね。もう少しちゃんと勉強せねば、と思いました

(何度、「もうjQueryで書こうかな」と揺らいだものか)

まぁそれは置いといて、

kintoneは業務で使うだけでなく、こんなお楽しみ?要素としても使えます。

複数人で同じ音楽ファイルを聞けるので、ストリーミング的な使い方もできそうですね

※ kintoneのデータ容量にはご注意ください

それでは!≧(+・` ཀ・´)≦