From 4a86b792d43a77b77a591216efda77e93ecb353d Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Tue, 29 Sep 2015 23:42:47 -0400 Subject: [PATCH] Remove google play services from DSub --- metadata/github.daneren2005.dsub.txt | 7 + ...move-Google-Play-Services-dependency.patch | 633 ++++++++++++++++++ 2 files changed, 640 insertions(+) create mode 100644 metadata/github.daneren2005.dsub/0001-Remove-Google-Play-Services-dependency.patch diff --git a/metadata/github.daneren2005.dsub.txt b/metadata/github.daneren2005.dsub.txt index 3b4d22c50f..b61f110f28 100644 --- a/metadata/github.daneren2005.dsub.txt +++ b/metadata/github.daneren2005.dsub.txt @@ -137,6 +137,13 @@ Build:4.8.6,134 disable=uses google play services commit=4.8.6 +Build:5.0.3,158 + commit=5.0.3 + subdir=app + submodules=yes + patch=0001-Remove-Google-Play-Services-dependency.patch + gradle=yes + Auto Update Mode:None Update Check Mode:Tags Current Version:5.0.3 diff --git a/metadata/github.daneren2005.dsub/0001-Remove-Google-Play-Services-dependency.patch b/metadata/github.daneren2005.dsub/0001-Remove-Google-Play-Services-dependency.patch new file mode 100644 index 0000000000..3638c4e3e9 --- /dev/null +++ b/metadata/github.daneren2005.dsub/0001-Remove-Google-Play-Services-dependency.patch @@ -0,0 +1,633 @@ +From 4bfbd4fed7801948679977e0dcb02973d941f315 Mon Sep 17 00:00:00 2001 +From: moparisthebest +Date: Tue, 29 Sep 2015 23:18:41 -0400 +Subject: [PATCH] Remove Google Play Services dependency + +This disables the ability to do Casting, though it supports DLNA/UPnP so who cares?... +--- + app/build.gradle | 1 - + app/src/main/AndroidManifest.xml | 3 - + .../dsub/service/ChromeCastController.java | 522 --------------------- + .../daneren2005/dsub/util/MediaRouteManager.java | 10 +- + .../daneren2005/dsub/util/compat/CastCompat.java | 13 +- + 5 files changed, 3 insertions(+), 546 deletions(-) + delete mode 100644 app/src/main/java/github/daneren2005/dsub/service/ChromeCastController.java + +diff --git a/app/build.gradle b/app/build.gradle +index 98571c6..bf8b440 100644 +--- a/app/build.gradle ++++ b/app/build.gradle +@@ -39,7 +39,6 @@ dependencies { + compile 'com.android.support:mediarouter-v7:22.2.+' + compile 'com.android.support:recyclerview-v7:22.2.+' + compile 'com.android.support:design:22.2.+' +- compile 'com.google.android.gms:play-services-cast:7.0.0' + compile 'com.sothree.slidinguppanel:library:3.0.0' + compile 'de.hdodenhof:circleimageview:1.2.1' + compile group: 'org.fourthline.cling', name: 'cling-core', version:'2.0.1' +diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml +index 2c756a4..5fe096f 100644 +--- a/app/src/main/AndroidManifest.xml ++++ b/app/src/main/AndroidManifest.xml +@@ -238,9 +238,6 @@ + + +- + + + +diff --git a/app/src/main/java/github/daneren2005/dsub/service/ChromeCastController.java b/app/src/main/java/github/daneren2005/dsub/service/ChromeCastController.java +deleted file mode 100644 +index a729ed4..0000000 +--- a/app/src/main/java/github/daneren2005/dsub/service/ChromeCastController.java ++++ /dev/null +@@ -1,522 +0,0 @@ +-/* +- This file is part of Subsonic. +- Subsonic is free software: you can redistribute it and/or modify +- it under the terms of the GNU General Public License as published by +- the Free Software Foundation, either version 3 of the License, or +- (at your option) any later version. +- Subsonic is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- GNU General Public License for more details. +- You should have received a copy of the GNU General Public License +- along with Subsonic. If not, see . +- Copyright 2014 (C) Scott Jackson +-*/ +- +-package github.daneren2005.dsub.service; +- +-import android.content.SharedPreferences; +-import android.net.Uri; +-import android.os.Bundle; +-import android.util.Log; +- +-import com.google.android.gms.cast.ApplicationMetadata; +-import com.google.android.gms.cast.Cast; +-import com.google.android.gms.cast.CastDevice; +-import com.google.android.gms.cast.MediaInfo; +-import com.google.android.gms.cast.MediaMetadata; +-import com.google.android.gms.cast.MediaStatus; +-import com.google.android.gms.cast.RemoteMediaPlayer; +-import com.google.android.gms.common.ConnectionResult; +-import com.google.android.gms.common.api.GoogleApiClient; +-import com.google.android.gms.common.api.ResultCallback; +-import com.google.android.gms.common.api.Status; +-import com.google.android.gms.common.images.WebImage; +- +-import java.io.File; +-import java.io.IOException; +- +-import github.daneren2005.dsub.R; +-import github.daneren2005.dsub.domain.MusicDirectory; +-import github.daneren2005.dsub.domain.PlayerState; +-import github.daneren2005.dsub.domain.RemoteControlState; +-import github.daneren2005.dsub.util.Constants; +-import github.daneren2005.dsub.util.FileUtil; +-import github.daneren2005.dsub.util.Util; +-import github.daneren2005.dsub.util.compat.CastCompat; +-import github.daneren2005.serverproxy.FileProxy; +-import github.daneren2005.serverproxy.ServerProxy; +-import github.daneren2005.serverproxy.WebProxy; +- +-/** +- * Created by owner on 2/9/14. +- */ +-public class ChromeCastController extends RemoteController { +- private static final String TAG = ChromeCastController.class.getSimpleName(); +- +- private CastDevice castDevice; +- private GoogleApiClient apiClient; +- +- private boolean applicationStarted = false; +- private boolean waitingForReconnect = false; +- private boolean error = false; +- private boolean ignoreNextPaused = false; +- private String sessionId; +- +- private ServerProxy proxy; +- private String rootLocation; +- private RemoteMediaPlayer mediaPlayer; +- private double gain = 0.5; +- +- public ChromeCastController(DownloadService downloadService, CastDevice castDevice) { +- this.downloadService = downloadService; +- this.castDevice = castDevice; +- +- SharedPreferences prefs = Util.getPreferences(downloadService); +- rootLocation = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null); +- } +- +- @Override +- public void create(boolean playing, int seconds) { +- downloadService.setPlayerState(PlayerState.PREPARING); +- +- ConnectionCallbacks connectionCallbacks = new ConnectionCallbacks(playing, seconds); +- ConnectionFailedListener connectionFailedListener = new ConnectionFailedListener(); +- Cast.Listener castClientListener = new Cast.Listener() { +- @Override +- public void onApplicationStatusChanged() { +- if (apiClient != null && apiClient.isConnected()) { +- Log.i(TAG, "onApplicationStatusChanged: " + Cast.CastApi.getApplicationStatus(apiClient)); +- } +- } +- +- @Override +- public void onVolumeChanged() { +- if (apiClient != null && applicationStarted) { +- try { +- gain = Cast.CastApi.getVolume(apiClient); +- } catch (Exception e) { +- Log.w(TAG, "Failed to get volume"); +- } +- } +- } +- +- @Override +- public void onApplicationDisconnected(int errorCode) { +- shutdownInternal(); +- } +- +- }; +- +- Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions.builder(castDevice, castClientListener).setVerboseLoggingEnabled(true); +- apiClient = new GoogleApiClient.Builder(downloadService).useDefaultAccount() +- .addApi(Cast.API, apiOptionsBuilder.build()) +- .addConnectionCallbacks(connectionCallbacks) +- .addOnConnectionFailedListener(connectionFailedListener) +- .build(); +- +- apiClient.connect(); +- } +- +- @Override +- public void start() { +- if(error) { +- error = false; +- Log.w(TAG, "Attempting to restart song"); +- startSong(downloadService.getCurrentPlaying(), true, 0); +- return; +- } +- +- try { +- mediaPlayer.play(apiClient); +- } catch(Exception e) { +- Log.e(TAG, "Failed to start"); +- } +- } +- +- @Override +- public void stop() { +- try { +- mediaPlayer.pause(apiClient); +- } catch(Exception e) { +- Log.e(TAG, "Failed to pause"); +- } +- } +- +- @Override +- public void shutdown() { +- try { +- if(mediaPlayer != null && !error) { +- mediaPlayer.stop(apiClient); +- } +- } catch(Exception e) { +- Log.e(TAG, "Failed to stop mediaPlayer", e); +- } +- +- try { +- if(apiClient != null) { +- Cast.CastApi.stopApplication(apiClient); +- Cast.CastApi.removeMessageReceivedCallbacks(apiClient, mediaPlayer.getNamespace()); +- mediaPlayer = null; +- applicationStarted = false; +- } +- } catch(Exception e) { +- Log.e(TAG, "Failed to shutdown application", e); +- } +- +- if(apiClient != null && apiClient.isConnected()) { +- apiClient.disconnect(); +- } +- apiClient = null; +- +- if(proxy != null) { +- proxy.stop(); +- proxy = null; +- } +- } +- +- private void shutdownInternal() { +- // This will call this.shutdown() indirectly +- downloadService.setRemoteEnabled(RemoteControlState.LOCAL, null); +- } +- +- @Override +- public void updatePlaylist() { +- if(downloadService.getCurrentPlaying() == null) { +- startSong(null, false, 0); +- } +- } +- +- @Override +- public void changePosition(int seconds) { +- try { +- mediaPlayer.seek(apiClient, seconds * 1000L); +- } catch(Exception e) { +- Log.e(TAG, "FAiled to seek to " + seconds); +- } +- } +- +- @Override +- public void changeTrack(int index, DownloadFile song) { +- startSong(song, true, 0); +- } +- +- @Override +- public void setVolume(int volume) { +- gain = volume / 10.0; +- +- try { +- Cast.CastApi.setVolume(apiClient, gain); +- } catch(Exception e) { +- Log.e(TAG, "Failed to the volume"); +- } +- } +- @Override +- public void updateVolume(boolean up) { +- double delta = up ? 0.1 : -0.1; +- gain += delta; +- gain = Math.max(gain, 0.0); +- gain = Math.min(gain, 1.0); +- +- try { +- Cast.CastApi.setVolume(apiClient, gain); +- } catch(Exception e) { +- Log.e(TAG, "Failed to the volume"); +- } +- } +- @Override +- public double getVolume() { +- return Cast.CastApi.getVolume(apiClient); +- } +- +- @Override +- public int getRemotePosition() { +- if(mediaPlayer != null) { +- return (int) (mediaPlayer.getApproximateStreamPosition() / 1000L); +- } else { +- return 0; +- } +- } +- +- @Override +- public int getRemoteDuration() { +- if(mediaPlayer != null) { +- return (int) (mediaPlayer.getStreamDuration() / 1000L); +- } else { +- return 0; +- } +- } +- +- void startSong(DownloadFile currentPlaying, boolean autoStart, int position) { +- if(currentPlaying == null) { +- try { +- if (mediaPlayer != null && !error) { +- mediaPlayer.stop(apiClient); +- } +- } catch(Exception e) { +- // Just means it didn't need to be stopped +- } +- downloadService.setPlayerState(PlayerState.IDLE); +- return; +- } +- downloadService.setPlayerState(PlayerState.PREPARING); +- MusicDirectory.Entry song = currentPlaying.getSong(); +- +- try { +- MusicService musicService = MusicServiceFactory.getMusicService(downloadService); +- String url; +- // Offline, use file proxy +- if(Util.isOffline(downloadService) || song.getId().indexOf(rootLocation) != -1) { +- if(proxy == null) { +- proxy = new FileProxy(downloadService); +- proxy.start(); +- } +- +- // Offline song +- if(song.getId().indexOf(rootLocation) != -1) { +- url = proxy.getPublicAddress(song.getId()); +- } else { +- // Playing online song in offline mode +- url = proxy.getPublicAddress(currentPlaying.getCompleteFile().getPath()); +- } +- } else { +- // Check if we want a proxy going still +- if(Util.isCastProxy(downloadService)) { +- if(proxy instanceof FileProxy) { +- proxy.stop(); +- proxy = null; +- } +- +- if(proxy == null) { +- proxy = createWebProxy(); +- proxy.start(); +- } +- } else if(proxy != null) { +- proxy.stop(); +- proxy = null; +- } +- +- if(song.isVideo()) { +- url = musicService.getHlsUrl(song.getId(), currentPlaying.getBitRate(), downloadService); +- } else { +- url = musicService.getMusicUrl(downloadService, song, currentPlaying.getBitRate()); +- } +- +- // If proxy is going, it is a WebProxy +- if(proxy != null) { +- url = proxy.getPublicAddress(url); +- } +- } +- +- // Setup song/video information +- MediaMetadata meta = new MediaMetadata(song.isVideo() ? MediaMetadata.MEDIA_TYPE_MOVIE : MediaMetadata.MEDIA_TYPE_MUSIC_TRACK); +- meta.putString(MediaMetadata.KEY_TITLE, song.getTitle()); +- if(song.getTrack() != null) { +- meta.putInt(MediaMetadata.KEY_TRACK_NUMBER, song.getTrack()); +- } +- if(!song.isVideo()) { +- meta.putString(MediaMetadata.KEY_ARTIST, song.getArtist()); +- meta.putString(MediaMetadata.KEY_ALBUM_ARTIST, song.getArtist()); +- meta.putString(MediaMetadata.KEY_ALBUM_TITLE, song.getAlbum()); +- +- String coverArt = ""; +- if(proxy == null || proxy instanceof WebProxy) { +- coverArt = musicService.getCoverArtUrl(downloadService, song); +- +- // If proxy is going, it is a web proxy +- if(proxy != null) { +- coverArt = proxy.getPublicAddress(coverArt); +- } +- +- meta.addImage(new WebImage(Uri.parse(coverArt))); +- } else { +- File coverArtFile = FileUtil.getAlbumArtFile(downloadService, song); +- if(coverArtFile != null && coverArtFile.exists()) { +- coverArt = proxy.getPublicAddress(coverArtFile.getPath()); +- meta.addImage(new WebImage(Uri.parse(coverArt))); +- } +- } +- } +- +- String contentType; +- if(song.isVideo()) { +- contentType = "application/x-mpegURL"; +- } +- else if(song.getTranscodedContentType() != null) { +- contentType = song.getTranscodedContentType(); +- } else if(song.getContentType() != null) { +- contentType = song.getContentType(); +- } else { +- contentType = "audio/mpeg"; +- } +- +- // Load it into a MediaInfo wrapper +- MediaInfo mediaInfo = new MediaInfo.Builder(url) +- .setContentType(contentType) +- .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) +- .setMetadata(meta) +- .build(); +- +- if(autoStart) { +- ignoreNextPaused = true; +- } +- +- mediaPlayer.load(apiClient, mediaInfo, autoStart, position * 1000L).setResultCallback(new ResultCallback() { +- @Override +- public void onResult(RemoteMediaPlayer.MediaChannelResult result) { +- if (result.getStatus().isSuccess()) { +- // Handled in other handler +- } else { +- Log.e(TAG, "Failed to load: " + result.getStatus().toString()); +- failedLoad(); +- } +- } +- }); +- } catch (IllegalStateException e) { +- Log.e(TAG, "Problem occurred with media during loading", e); +- failedLoad(); +- } catch (Exception e) { +- Log.e(TAG, "Problem opening media during loading", e); +- failedLoad(); +- } +- } +- +- private void failedLoad() { +- Util.toast(downloadService, downloadService.getResources().getString(R.string.download_failed_to_load)); +- downloadService.setPlayerState(PlayerState.STOPPED); +- error = true; +- } +- +- +- private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks { +- private boolean isPlaying; +- private int position; +- private ResultCallback resultCallback; +- +- ConnectionCallbacks(boolean isPlaying, int position) { +- this.isPlaying = isPlaying; +- this.position = position; +- +- resultCallback = new ResultCallback() { +- @Override +- public void onResult(Cast.ApplicationConnectionResult result) { +- Status status = result.getStatus(); +- if (status.isSuccess()) { +- ApplicationMetadata applicationMetadata = result.getApplicationMetadata(); +- sessionId = result.getSessionId(); +- String applicationStatus = result.getApplicationStatus(); +- boolean wasLaunched = result.getWasLaunched(); +- +- applicationStarted = true; +- setupChannel(); +- } else { +- shutdownInternal(); +- } +- } +- }; +- } +- +- @Override +- public void onConnected(Bundle connectionHint) { +- if (waitingForReconnect) { +- Log.i(TAG, "Reconnecting"); +- reconnectApplication(); +- } else { +- launchApplication(); +- } +- } +- +- @Override +- public void onConnectionSuspended(int cause) { +- Log.w(TAG, "Connection suspended"); +- isPlaying = downloadService.getPlayerState() == PlayerState.STARTED; +- position = getRemotePosition(); +- waitingForReconnect = true; +- } +- +- void launchApplication() { +- try { +- Cast.CastApi.launchApplication(apiClient, CastCompat.APPLICATION_ID, false).setResultCallback(resultCallback); +- } catch (Exception e) { +- Log.e(TAG, "Failed to launch application", e); +- } +- } +- void reconnectApplication() { +- try { +- Cast.CastApi.joinApplication(apiClient, CastCompat.APPLICATION_ID, sessionId).setResultCallback(resultCallback); +- } catch (Exception e) { +- Log.e(TAG, "Failed to reconnect application", e); +- } +- } +- void setupChannel() { +- if(!waitingForReconnect) { +- mediaPlayer = new RemoteMediaPlayer(); +- mediaPlayer.setOnStatusUpdatedListener(new RemoteMediaPlayer.OnStatusUpdatedListener() { +- @Override +- public void onStatusUpdated() { +- MediaStatus mediaStatus = mediaPlayer.getMediaStatus(); +- if (mediaStatus == null) { +- return; +- } +- +- switch (mediaStatus.getPlayerState()) { +- case MediaStatus.PLAYER_STATE_PLAYING: +- if (ignoreNextPaused) { +- ignoreNextPaused = false; +- } +- downloadService.setPlayerState(PlayerState.STARTED); +- break; +- case MediaStatus.PLAYER_STATE_PAUSED: +- if (!ignoreNextPaused) { +- downloadService.setPlayerState(PlayerState.PAUSED); +- } +- break; +- case MediaStatus.PLAYER_STATE_BUFFERING: +- downloadService.setPlayerState(PlayerState.PREPARING); +- break; +- case MediaStatus.PLAYER_STATE_IDLE: +- if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_FINISHED) { +- downloadService.setPlayerState(PlayerState.COMPLETED); +- downloadService.postPlayCleanup(); +- downloadService.onSongCompleted(); +- } else if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_INTERRUPTED) { +- if (downloadService.getPlayerState() != PlayerState.PREPARING) { +- downloadService.setPlayerState(PlayerState.PREPARING); +- } +- } else if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_ERROR) { +- Log.e(TAG, "Idle due to unknown error"); +- downloadService.setPlayerState(PlayerState.COMPLETED); +- downloadService.next(); +- } else { +- Log.w(TAG, "Idle reason: " + mediaStatus.getIdleReason()); +- downloadService.setPlayerState(PlayerState.IDLE); +- } +- break; +- } +- } +- }); +- } +- +- try { +- Cast.CastApi.setMessageReceivedCallbacks(apiClient, mediaPlayer.getNamespace(), mediaPlayer); +- } catch (IOException e) { +- Log.e(TAG, "Exception while creating channel", e); +- } +- +- if(!waitingForReconnect) { +- DownloadFile currentPlaying = downloadService.getCurrentPlaying(); +- startSong(currentPlaying, isPlaying, position); +- } +- if(waitingForReconnect) { +- waitingForReconnect = false; +- } +- } +- } +- +- private class ConnectionFailedListener implements GoogleApiClient.OnConnectionFailedListener { +- @Override +- public void onConnectionFailed(ConnectionResult result) { +- shutdownInternal(); +- } +- } +-} +diff --git a/app/src/main/java/github/daneren2005/dsub/util/MediaRouteManager.java b/app/src/main/java/github/daneren2005/dsub/util/MediaRouteManager.java +index 9aa54c4..e8ab87a 100644 +--- a/app/src/main/java/github/daneren2005/dsub/util/MediaRouteManager.java ++++ b/app/src/main/java/github/daneren2005/dsub/util/MediaRouteManager.java +@@ -21,9 +21,6 @@ import android.support.v7.media.MediaRouteSelector; + import android.support.v7.media.MediaRouter; + import android.util.Log; + +-import com.google.android.gms.common.ConnectionResult; +-import com.google.android.gms.common.GooglePlayServicesUtil; +- + import java.util.ArrayList; + import java.util.List; + +@@ -62,12 +59,7 @@ public class MediaRouteManager extends MediaRouter.Callback { + this.downloadService = downloadService; + router = MediaRouter.getInstance(downloadService); + +- // Check if play services is available +- int result = GooglePlayServicesUtil.isGooglePlayServicesAvailable(downloadService); +- if(result != ConnectionResult.SUCCESS){ +- Log.w(TAG, "No play services, failed with result: " + result); +- castAvailable = false; +- } ++ castAvailable = false; + + addProviders(); + buildSelector(); +diff --git a/app/src/main/java/github/daneren2005/dsub/util/compat/CastCompat.java b/app/src/main/java/github/daneren2005/dsub/util/compat/CastCompat.java +index ab64bca..5dac82c 100644 +--- a/app/src/main/java/github/daneren2005/dsub/util/compat/CastCompat.java ++++ b/app/src/main/java/github/daneren2005/dsub/util/compat/CastCompat.java +@@ -17,10 +17,6 @@ package github.daneren2005.dsub.util.compat; + + import android.support.v7.media.MediaRouter; + +-import com.google.android.gms.cast.CastDevice; +-import com.google.android.gms.cast.CastMediaControlIntent; +- +-import github.daneren2005.dsub.service.ChromeCastController; + import github.daneren2005.dsub.service.DownloadService; + import github.daneren2005.dsub.service.RemoteController; + +@@ -43,15 +39,10 @@ public final class CastCompat { + } + + public static RemoteController getController(DownloadService downloadService, MediaRouter.RouteInfo info) { +- CastDevice device = CastDevice.getFromBundle(info.getExtras()); +- if(device != null) { +- return new ChromeCastController(downloadService, device); +- } else { +- return null; +- } ++ return null; + } + + public static String getCastControlCategory() { +- return CastMediaControlIntent.categoryForCast(APPLICATION_ID); ++ return null; + } + } +-- +1.9.2 +