Last.FM APIとVK.COM APIを統合してプレーヤーのコンテンツを更新する例

みなさんこんにちは!



ほとんどの人はソーシャルネットワークVkontakteLast.fmに精通していると思います この記事では、両方のサービスのAPI間の統合の小さな例を見ていきます。 より正確には、last.fmからお気に入りのトラックのリストを受け取り、VKでバイナリコンテンツを探してHDDに保存します。

この記事は、専門家よりも初心者にとって興味深いものですが、技術的なトレーニングが必要です。 テストプロジェクトはJavaを使用して実装されます。



読者がその由来に興味がある場合は、Catへようこそ。







免責事項



私たちのひどい時代に、企業が10億行のコードでお互いを訴えようとしているとき。 「1対2」という問題が発生した場合、次のように言わなければなりません。

この記事のフレームワークでのソフトウェアの実装には、純粋に教育的な衝動があり、商業的な動機を追求していません。



イントロ



私は長い間引きずり出さない。 目標を定義します。

  1. last.fmでお気に入りのトラックのリストを取得します
  2. vk.comサーバーでトラックを見つける
  3. プレーヤーにトラックをダウンロードする




しかし、最初に、両方のサービスのAPIにアクセスする必要があります。

たとえば、 これなど、Habréに関する記事はすでにありました。 すべてを詳しく説明するわけではないので、すぐにリンクします。

APIキーlast.fm

Vk.com APIキー

次に、仕様( last.fmvk.com )を慎重に検討し、必要なものを正確に決定します。

実際には、 audio.searchおよびuser.getLovedTracksメソッドが必要です。



テストリクエスト



アプリケーションが既に作成された後、作業対象を確認する必要があります。

last.fmでは、すべてが簡単です。 ブラウザの行で通常のhtmlリクエストを行います:

http:// ws.audioscrobbler.com/2.0/?method=user.getlovedtracks&user= USER &api_key = API_KEY

すべてのパラメーターが正しく入力されていれば、xml'kuを見ることができます。ここでは、トラックの名前と作成者に加えて、追加情報を確認できます。

vk.comの場合、access_tokenパラメーターがないと音声記録にアクセスできないという事実を除いて、すべてがほぼ同じです。

リクエストを行います:

http:// api.vk.com/oauth/authorize?client_id= ID &redirect_uri = http://api.vk.com/blank.html&scope= audio &display = page&response_type = token

その結果、リダイレクトは次の形式のリンクに送信されます。

http:// api.vk.com/blank.html#access_token= XYZ &expires_in = 86400&user_id = ID

XYZが必要です。

次の形式のリクエスト:

https:// api.vk.com/method/audio.search.xml?q=AC/DC%20-%20Highway%20to%20Hell&access_token= XYZは、バイナリ音楽ファイルの物理アドレスを確認できるxmlを提供する必要があります。

すべてが「成功」した場合、先に進むことができます。



ソフトウェア実装



現在の設定が保存されるConfiguration.propertiesファイルを取得します。

last_fm_api=

last_fm_user=

last_fm_ws_address=http://ws.audioscrobbler.com/2.0/

vk_com_access_token=

vk_com_ws_address=https://api.vk.com/method/






簡単にするために、GUIを煩わせることにしました。 データは、この種のビンのPOJOコレクションに便利に保存されます。

 public class LovedTrackBean { public LovedTrackBean(String trackName, String trackArtist) { this.trackName = trackName; this.trackArtist = trackArtist; } //GETTERS & SETTERS public String toString() { return trackArtist + " - " + trackName; } private String trackName = null; private String trackArtist = null; private String trackURL = null; }
      
      





次に、last.fm APIを使用して、お気に入りのトラックのリストを取得する必要があります。

このようなもの:

 public class TrackLover { public TrackLover() { StringBuffer buff = new StringBuffer(); buff.append(PropertyLoader.getProperties().get(PropertyLoader.LAST_FM_WS_ADDRESS)); buff.append("?method="); buff.append(LAST_FM_API_METHOD); buff.append("&user="); buff.append(PropertyLoader.getProperties().get(PropertyLoader.LAST_FM_USER)); buff.append("&api_key="); buff.append(PropertyLoader.getProperties().get(PropertyLoader.LAST_FM_API)); connectToUrl = buff.toString(); } public List<LovedTrackBean> getLovedTracks() throws IOException, ParserConfigurationException, SAXException { if(lovedTracks == null) { URL url = new URL(connectToUrl); URLConnection conn = url.openConnection(); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document doc = docBuilder.parse(conn.getInputStream()); doc.getDocumentElement().normalize(); NodeList listOfLovedTracks = doc.getElementsByTagName("track"); int tracksTotal = listOfLovedTracks.getLength(); lovedTracks = new ArrayList<LovedTrackBean>(tracksTotal); //... //  //... System.out.println("######### AFTER LAST.FM RESPONSE #########"); for(LovedTrackBean track: lovedTracks) { System.out.println(track.toString()); } return lovedTracks; } else { lovedTracks = new ArrayList<LovedTrackBean>(1); lovedTracks.add(new LovedTrackBean("Wish you were here", "Pink Floyd")); return lovedTracks; } } private String connectToUrl = null; private List<LovedTrackBean> lovedTracks = null; public static final String LAST_FM_API_METHOD = "user.getlovedtracks"; }
      
      





このコードは、お気に入りのトラックを含むコレクションを返す必要があります。

次の目的地はvk.comです。

「Author-Composition」のペアでオーディオ録音を取得してみましょう。 簡単にするために、最初のものを取ります。

 public class TrackURLFinder { public TrackURLFinder(LovedTrackBean lovedTrack) { this.lovedTrack = lovedTrack; StringBuffer buff = new StringBuffer(); buff.append(PropertyLoader.getProperties().get(PropertyLoader.VK_COM_WS_ADDRESS)); buff.append(VK_COM_API_METHOD); buff.append("?q="); buff.append(lovedTrack.toString()); buff.append("&"); buff.append("access_token="); buff.append(PropertyLoader.getProperties().get(PropertyLoader.VK_COM_ACCESS_TOKEN)); connectToUrl = buff.toString(); connectToUrl = connectToUrl.replaceAll(" ", "%20"); System.out.println(connectToUrl); } public void addUrlToLovedTrack() throws SAXException, IOException, ParserConfigurationException { if(lovedTrack != null) { URL url = new URL(connectToUrl); URLConnection conn = url.openConnection(); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document doc = docBuilder.parse(conn.getInputStream()); doc.getDocumentElement().normalize(); NodeList audioList = doc.getElementsByTagName("audio"); Node currentNode = audioList.item(0); Element currentElement = (Element) currentNode; NodeList urlList = currentElement.getElementsByTagName("url"); Element urlElement = (Element) urlList.item(0); NodeList urlFormattedList = urlElement.getChildNodes(); String urlAddressOfTheMP3File = urlFormattedList.item(0).getNodeValue().trim(); lovedTrack.setTrackURL(urlAddressOfTheMP3File); System.out.println(urlAddressOfTheMP3File); } } private String connectToUrl = null; private LovedTrackBean lovedTrack = null; public static final String VK_COM_API_METHOD = "audio.search.xml"; }
      
      





そして最後に、コンテンツを取得します。

 public class MP3MusicContentDownloader { public MP3MusicContentDownloader(String urlAddress, String fileName) throws MalformedURLException { this.fileName = fileName; url = new URL(urlAddress); } public void download() throws IOException { conn = url.openConnection(); System.out.println("Started downloading of " + fileName); String contentType = conn.getContentType(); int contentLength = conn.getContentLength(); if (contentType.startsWith("text/") || contentLength == -1) { throw new IOException("This is not a binary file."); } File folder = new File(DEFAULT_DIRECTORY_NAME); if (!folder.exists() || !folder.isDirectory()) { folder.mkdir(); } File binaryFile = new File(DEFAULT_DIRECTORY_NAME + File.separator + fileName); if (!binaryFile.exists()) { BufferedInputStream in = new BufferedInputStream(conn.getInputStream()); byte[] data = new byte[contentLength]; int bytesRead = 0; int offset = 0; while (offset < contentLength) { bytesRead = in.read(data, offset, data.length - offset); if (bytesRead == -1) break; offset += bytesRead; } in.close(); if (offset != contentLength) { throw new IOException("Only read " + offset + " bytes; Expected " + contentLength + " bytes"); } FileOutputStream out = new FileOutputStream(binaryFile); out.write(data); out.flush(); out.close(); } else { return; } } private String fileName = null; private URL url = null; private URLConnection conn = null; private static final String DEFAULT_DIRECTORY_NAME = "music"; }
      
      





以上です。 打ち上げは難しくないと思います。



トドス



ちなみに、これは自己学習の目的で行われた単なるテストケースであるため、多くのバグ/欠点が含まれていることはほぼ確実です。 それにもかかわらず、私のトラックの例はうまくいきました。 具体的には、この場合、マルチスレッドの実装、たとえば、選択したすべての曲のフルスキャン(現在最初の50曲が収集されています)、またはたとえば、access_token'ovの有効性のチェック(突然、期限切れ)を実装できます。 はい、たくさんあります。 しかし、あなたがすでに理解している場合、記事のポイントはそれではありませんでした:)



これらの行に到達するために忍耐を持っているすべての人に感謝します!



All Articles