From 43fbecd3810bc3f487c966155e47e45e25de1075 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 26 Jun 2017 00:49:05 +0200 Subject: [PATCH 1/8] added google cast support --- app/build.gradle | 13 ++- app/src/main/AndroidManifest.xml | 6 ++ .../radiodroid2/ActivityMain.java | 91 +++++++++++++++++-- .../radiodroid2/CastOptionsProvider.java | 24 +++++ .../programmierecke/radiodroid2/Utils.java | 33 ++++++- app/src/main/res/layout/layout_main.xml | 8 ++ app/src/main/res/menu/menu_main.xml | 6 ++ app/src/main/res/values/strings.xml | 3 + 8 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/net/programmierecke/radiodroid2/CastOptionsProvider.java diff --git a/app/build.gradle b/app/build.gradle index 89655e7f6..8ced54c51 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ android { } defaultConfig { applicationId "net.programmierecke.radiodroid2" - minSdkVersion 9 + minSdkVersion 14 targetSdkVersion 23 versionCode 42 @@ -27,10 +27,13 @@ android { } dependencies { - compile 'com.android.support:support-v4:25.3.1' - compile 'com.android.support:appcompat-v7:25.3.1' - compile 'com.android.support:design:25.3.1' - compile 'com.android.support:preference-v7:25.3.1' + compile 'com.android.support:support-v4:25.2.0' + compile 'com.android.support:appcompat-v7:25.2.0' + compile 'com.android.support:design:25.2.0' + compile 'com.android.support:preference-v7:25.2.0' + compile 'com.android.support:mediarouter-v7:25.2.0' compile 'com.google.code.gson:gson:2.7' compile 'com.google.android.exoplayer:exoplayer:r2.3.1' + compile 'com.google.android.gms:play-services-cast:11.0.1' + compile 'com.google.android.gms:play-services-cast-framework:11.0.1' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a2d4062d5..13436527a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -45,5 +45,11 @@ + + + \ No newline at end of file diff --git a/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java b/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java index f6c337fcd..f57cb03e9 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java @@ -3,6 +3,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; import android.support.design.widget.NavigationView; import android.support.v4.app.Fragment; @@ -21,6 +22,17 @@ import android.view.MenuItem; import android.widget.Toast; +import com.google.android.gms.cast.MediaInfo; +import com.google.android.gms.cast.MediaMetadata; +import com.google.android.gms.cast.framework.CastButtonFactory; +import com.google.android.gms.cast.framework.CastContext; +import com.google.android.gms.cast.framework.CastSession; +import com.google.android.gms.cast.framework.Session; +import com.google.android.gms.cast.framework.SessionManager; +import com.google.android.gms.cast.framework.SessionManagerListener; +import com.google.android.gms.cast.framework.media.RemoteMediaClient; +import com.google.android.gms.common.images.WebImage; + import net.programmierecke.radiodroid2.interfaces.IFragmentRefreshable; import net.programmierecke.radiodroid2.interfaces.IFragmentSearchable; @@ -45,13 +57,67 @@ public class ActivityMain extends AppCompatActivity implements SearchView.OnQuer MenuItem menuItemRefresh; private SharedPreferences sharedPref; + private CastContext mCastContext; + private MenuItem mediaRouteMenuItem; + private SessionManager mSessionManager; - @Override + private final SessionManagerListener mSessionManagerListener = + new SessionManagerListenerImpl(); + private class SessionManagerListenerImpl implements SessionManagerListener { + @Override + public void onSessionStarting(Session session) { + + } + + @Override + public void onSessionStarted(Session session, String sessionId) { + invalidateOptionsMenu(); + Utils.mCastSession = mSessionManager.getCurrentCastSession(); + } + + @Override + public void onSessionStartFailed(Session session, int i) { + + } + + @Override + public void onSessionEnding(Session session) { + } + + @Override + public void onSessionResumed(Session session, boolean wasSuspended) { + invalidateOptionsMenu(); + Utils.mCastSession = mSessionManager.getCurrentCastSession(); + } + + @Override + public void onSessionResumeFailed(Session session, int i) { + Utils.mCastSession = null; + } + + @Override + public void onSessionSuspended(Session session, int i) { + Utils.mCastSession = null; + } + + @Override + public void onSessionEnded(Session session, int error) { + Utils.mCastSession = null; + } + + @Override + public void onSessionResuming(Session session, String s) { + + } + } + + + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_main); - try { + try { File dir = new File(getFilesDir().getAbsolutePath()); if (dir.isDirectory()) { String[] children = dir.list(); @@ -159,7 +225,10 @@ public boolean onNavigationItemSelected(MenuItem menuItem) { ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout, R.string.app_name,R.string.app_name); mDrawerLayout.addDrawerListener(mDrawerToggle); mDrawerToggle.syncState(); - } + + mCastContext = CastContext.getSharedInstance(this); + mSessionManager = mCastContext.getSessionManager(); + } @Override public void onRequestPermissionsResult(int requestCode, @@ -191,10 +260,13 @@ public void onDestroy() { @Override protected void onPause() { super.onPause(); - } + mSessionManager.removeSessionManagerListener(mSessionManagerListener); + Utils.mCastSession = null; + } @Override public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); @@ -212,7 +284,11 @@ public boolean onCreateOptionsMenu(Menu menu) { menuItemRefresh.setVisible(false); } - return true; + mediaRouteMenuItem = CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), + menu, + R.id.media_route_menu_item); + + return true; } @Override @@ -255,7 +331,10 @@ protected void onResume() { mFragmentTransaction = mFragmentManager.beginTransaction(); mFragmentTransaction.replace(R.id.containerView,first).commit(); - } + + Utils.mCastSession = mSessionManager.getCurrentCastSession(); + mSessionManager.addSessionManagerListener(mSessionManagerListener); + } public void Search(String query){ if (fragSearchable != null) { diff --git a/app/src/main/java/net/programmierecke/radiodroid2/CastOptionsProvider.java b/app/src/main/java/net/programmierecke/radiodroid2/CastOptionsProvider.java new file mode 100644 index 000000000..ab07d0bf5 --- /dev/null +++ b/app/src/main/java/net/programmierecke/radiodroid2/CastOptionsProvider.java @@ -0,0 +1,24 @@ +package net.programmierecke.radiodroid2; + +import android.content.Context; + +import com.google.android.gms.cast.framework.CastOptions; +import com.google.android.gms.cast.framework.OptionsProvider; +import com.google.android.gms.cast.framework.SessionProvider; + +import java.util.List; + +public class CastOptionsProvider implements OptionsProvider { + + @Override + public CastOptions getCastOptions(Context context) { + return new CastOptions.Builder() + .setReceiverApplicationId(context.getString(R.string.app_id)) + .build(); + } + + @Override + public List getAdditionalSessionProviders(Context context) { + return null; + } +} diff --git a/app/src/main/java/net/programmierecke/radiodroid2/Utils.java b/app/src/main/java/net/programmierecke/radiodroid2/Utils.java index 8074fd4b0..60bd367d9 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/Utils.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/Utils.java @@ -16,6 +16,12 @@ import android.util.Log; import android.widget.Toast; +import com.google.android.gms.cast.MediaInfo; +import com.google.android.gms.cast.MediaMetadata; +import com.google.android.gms.cast.framework.CastSession; +import com.google.android.gms.cast.framework.media.RemoteMediaClient; +import com.google.android.gms.common.images.WebImage; + import net.programmierecke.radiodroid2.data.DataRadioStation; import org.json.JSONArray; @@ -37,7 +43,9 @@ import java.util.Map; public class Utils { - public static String getCacheFile(Context ctx, String theURI) { + public static CastSession mCastSession; + + public static String getCacheFile(Context ctx, String theURI) { StringBuffer chaine = new StringBuffer(""); try{ String aFileName = theURI.toLowerCase().replace("http://",""); @@ -180,7 +188,9 @@ protected void onPostExecute(String result) { itsProgressLoading.dismiss(); if (result != null) { - if (external){ + if (mCastSession != null){ + PlayRemote(station.Name, result, station.IconUrl); + }else if (external){ Intent share = new Intent(Intent.ACTION_VIEW); share.setDataAndType(Uri.parse(result), "audio/*"); context.startActivity(share); @@ -196,6 +206,25 @@ protected void onPostExecute(String result) { }.execute(); } + private static void PlayRemote(String title, String url, String iconurl){ + MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MUSIC_TRACK); + + movieMetadata.putString(MediaMetadata.KEY_TITLE, title); + //movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, "MySubTitle"); + movieMetadata.addImage(new WebImage(Uri.parse(iconurl))); + //movieMetadata.addImage(new WebImage(Uri.parse(mSelectedMedia.getImage(1)))); + + + MediaInfo mediaInfo = new MediaInfo.Builder(url) + .setStreamType(MediaInfo.STREAM_TYPE_LIVE) + .setContentType("audio/ogg") + .setMetadata(movieMetadata) + //.setStreamDuration(mSelectedMedia.getDuration() * 1000) + .build(); + RemoteMediaClient remoteMediaClient = Utils.mCastSession.getRemoteMediaClient(); + remoteMediaClient.load(mediaInfo, true); + } + // Storage Permissions public static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { diff --git a/app/src/main/res/layout/layout_main.xml b/app/src/main/res/layout/layout_main.xml index 3fa60247b..207843ee6 100644 --- a/app/src/main/res/layout/layout_main.xml +++ b/app/src/main/res/layout/layout_main.xml @@ -19,6 +19,14 @@ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 168076fa3..9712c48d6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -90,6 +90,9 @@ Delete More + GoogleCast + 5A97BAE4 + S M From 962c82dbf9d8fcf4afaf384f4dd18fea32c8d671 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 26 Jun 2017 21:57:19 +0200 Subject: [PATCH 2/8] basic mpd support --- .../radiodroid2/MPDClient.java | 85 +++++++++++++++++++ .../programmierecke/radiodroid2/Utils.java | 5 +- app/src/main/res/values/strings.xml | 4 + app/src/main/res/xml/preferences.xml | 11 +++ 4 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java diff --git a/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java b/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java new file mode 100644 index 000000000..7408a8ef0 --- /dev/null +++ b/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java @@ -0,0 +1,85 @@ +package net.programmierecke.radiodroid2; + +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.AsyncTask; +import android.support.v7.preference.PreferenceManager; +import android.util.Log; +import android.widget.Toast; + +import net.programmierecke.radiodroid2.data.DataRadioStation; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.Socket; + +public class MPDClient { + public static int StringToInt(String str, int defaultValue){ + try{ + return Integer.parseInt(str); + } + catch (Exception e){ + } + return defaultValue; + } + public static void Play(final String url, final Context context) { + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); + final String mpd_hostname = sharedPref.getString("mpd_hostname", null); + final int mpd_port = StringToInt(sharedPref.getString("mpd_port", "6600"), 6600); + + new AsyncTask() { + @Override + protected Boolean doInBackground(Void... params) { + return PlayRemoteMPD(mpd_hostname, mpd_port, url); + } + + @Override + protected void onPostExecute(Boolean result) { + super.onPostExecute(result); + } + }.execute(); + } + + private static Boolean PlayRemoteMPD(String mpd_hostname, int mpd_port, String url){ + Boolean result = false; + try { + Log.i("MPD", "Start"); + Socket s = new Socket(mpd_hostname, mpd_port); + BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream())); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); + String info = reader.readLine(); + Log.i("MPD", info); + if (info.startsWith("OK")){ + String cmd = "addid "+url; + writer.write(cmd); + writer.newLine(); + writer.flush(); + + info = reader.readLine(); + Log.i("MPD", info); + if (info.startsWith("Id:")){ + int songid = Integer.parseInt(info.substring(3).trim()); + cmd = "playid "+songid; + writer.write(cmd); + writer.newLine(); + writer.flush(); + Log.i("MPD", "OK"); + result = true; + } + } + reader.close(); + writer.close(); + s.close(); + } catch (Exception e) { + Log.e("MPD",e.toString()); + } + return result; + } +} diff --git a/app/src/main/java/net/programmierecke/radiodroid2/Utils.java b/app/src/main/java/net/programmierecke/radiodroid2/Utils.java index 60bd367d9..d44341459 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/Utils.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/Utils.java @@ -12,7 +12,6 @@ import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.preference.PreferenceManager; -import android.util.Base64; import android.util.Log; import android.widget.Toast; @@ -24,7 +23,6 @@ import net.programmierecke.radiodroid2.data.DataRadioStation; -import org.json.JSONArray; import org.json.JSONObject; import java.io.BufferedReader; @@ -37,8 +35,6 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; -import java.util.Dictionary; -import java.util.Enumeration; import java.util.Locale; import java.util.Map; @@ -187,6 +183,7 @@ protected String doInBackground(Void... params) { protected void onPostExecute(String result) { itsProgressLoading.dismiss(); + MPDClient.Play(result, context); if (result != null) { if (mCastSession != null){ PlayRemote(station.Name, result, station.IconUrl); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9712c48d6..65368400b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -93,6 +93,10 @@ GoogleCast 5A97BAE4 + Music Player Daemon + Hostname + Port + S M diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 37f24df9f..90907358d 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -58,4 +58,15 @@ android:title="@string/settings_alarm_sleep_timer" /> + + + + + \ No newline at end of file From 8685c987167e38f3fa1c148cd6f60d9a3c99081b Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 27 Jun 2017 23:31:21 +0200 Subject: [PATCH 3/8] nicer mpd support --- .../radiodroid2/ActivityMain.java | 41 ++++- .../radiodroid2/MPDClient.java | 144 +++++++++++++++++- .../programmierecke/radiodroid2/Utils.java | 23 ++- app/src/main/res/drawable/mpd_nok.png | Bin 0 -> 4000 bytes app/src/main/res/drawable/mpd_ok.png | Bin 0 -> 3740 bytes app/src/main/res/menu/menu_main.xml | 27 +++- app/src/main/res/values/strings.xml | 3 + 7 files changed, 209 insertions(+), 29 deletions(-) create mode 100644 app/src/main/res/drawable/mpd_nok.png create mode 100644 app/src/main/res/drawable/mpd_ok.png diff --git a/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java b/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java index f57cb03e9..ea686e847 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java @@ -3,8 +3,8 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.support.design.widget.NavigationView; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; @@ -22,16 +22,11 @@ import android.view.MenuItem; import android.widget.Toast; -import com.google.android.gms.cast.MediaInfo; -import com.google.android.gms.cast.MediaMetadata; import com.google.android.gms.cast.framework.CastButtonFactory; import com.google.android.gms.cast.framework.CastContext; -import com.google.android.gms.cast.framework.CastSession; import com.google.android.gms.cast.framework.Session; import com.google.android.gms.cast.framework.SessionManager; import com.google.android.gms.cast.framework.SessionManagerListener; -import com.google.android.gms.cast.framework.media.RemoteMediaClient; -import com.google.android.gms.common.images.WebImage; import net.programmierecke.radiodroid2.interfaces.IFragmentRefreshable; import net.programmierecke.radiodroid2.interfaces.IFragmentSearchable; @@ -40,7 +35,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -public class ActivityMain extends AppCompatActivity implements SearchView.OnQueryTextListener { +public class ActivityMain extends AppCompatActivity implements SearchView.OnQueryTextListener, IMPDClientStatusChange { private SearchView mSearchView; private static final String TAG = "RadioDroid"; @@ -63,6 +58,21 @@ public class ActivityMain extends AppCompatActivity implements SearchView.OnQuer private final SessionManagerListener mSessionManagerListener = new SessionManagerListenerImpl(); + private MenuItem menuItemMPDOK; + private MenuItem menuItemMPDNok; + + @Override + public void changed() { + Handler mainHandler = new Handler(getMainLooper()); + Runnable myRunnable = new Runnable() { + @Override + public void run() { + invalidateOptionsMenu(); + } + }; + mainHandler.post(myRunnable); + } + private class SessionManagerListenerImpl implements SessionManagerListener { @Override public void onSessionStarting(Session session) { @@ -228,6 +238,8 @@ public boolean onNavigationItemSelected(MenuItem menuItem) { mCastContext = CastContext.getSharedInstance(this); mSessionManager = mCastContext.getSessionManager(); + + MPDClient.StartDiscovery(this, this); } @Override @@ -255,6 +267,7 @@ public void onRequestPermissionsResult(int requestCode, public void onDestroy() { super.onDestroy(); PlayerServiceUtil.unBind(this); + MPDClient.StopDiscovery(); } @Override @@ -262,6 +275,7 @@ protected void onPause() { super.onPause(); mSessionManager.removeSessionManagerListener(mSessionManagerListener); Utils.mCastSession = null; + MPDClient.StopDiscovery(); } @Override @@ -275,6 +289,8 @@ public boolean onCreateOptionsMenu(Menu menu) { mSearchView.setOnQueryTextListener(this); menuItemRefresh = menu.findItem(R.id.action_refresh); + menuItemMPDNok = menu.findItem(R.id.action_mpd_nok); + menuItemMPDOK = menu.findItem(R.id.action_mpd_ok); if (fragSearchable == null) { menuItemSearch.setVisible(false); @@ -284,6 +300,9 @@ public boolean onCreateOptionsMenu(Menu menu) { menuItemRefresh.setVisible(false); } + menuItemMPDOK.setVisible(MPDClient.Discovered() && MPDClient.Connected()); + menuItemMPDNok.setVisible(MPDClient.Discovered() && !MPDClient.Connected()); + mediaRouteMenuItem = CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), menu, R.id.media_route_menu_item); @@ -302,6 +321,12 @@ public boolean onOptionsItemSelected(MenuItem item) { fragRefreshable.Refresh(); } return true; + case R.id.action_mpd_nok: + MPDClient.Connect(this); + return true; + case R.id.action_mpd_ok: + MPDClient.Disconnect(this, this); + return true; } return super.onOptionsItemSelected(item); } @@ -334,6 +359,8 @@ protected void onResume() { Utils.mCastSession = mSessionManager.getCurrentCastSession(); mSessionManager.addSessionManagerListener(mSessionManagerListener); + + MPDClient.StartDiscovery(this, this); } public void Search(String query){ diff --git a/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java b/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java index 7408a8ef0..d6d1add0d 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java @@ -1,26 +1,25 @@ package net.programmierecke.radiodroid2; -import android.app.ProgressDialog; import android.content.Context; -import android.content.Intent; import android.content.SharedPreferences; -import android.net.Uri; import android.os.AsyncTask; import android.support.v7.preference.PreferenceManager; import android.util.Log; -import android.widget.Toast; - -import net.programmierecke.radiodroid2.data.DataRadioStation; import java.io.BufferedReader; import java.io.BufferedWriter; -import java.io.IOException; import java.io.InputStreamReader; -import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; +interface IMPDClientStatusChange{ + void changed(); +} + public class MPDClient { + static final String TAG = "MPD"; + private static boolean connected; + public static int StringToInt(String str, int defaultValue){ try{ return Integer.parseInt(str); @@ -29,6 +28,18 @@ public static int StringToInt(String str, int defaultValue){ } return defaultValue; } + + public static void Connect(IMPDClientStatusChange listener){ + connected = true; + listener.changed(); + } + + public static void Disconnect(Context context, IMPDClientStatusChange listener){ + connected = false; + listener.changed(); + Stop(context); + } + public static void Play(final String url, final Context context) { SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); final String mpd_hostname = sharedPref.getString("mpd_hostname", null); @@ -47,6 +58,119 @@ protected void onPostExecute(Boolean result) { }.execute(); } + static boolean discovered = false; + static Thread t = null; + static boolean discoveryActive = false; + + public static boolean Discovered(){ + return discovered; + } + + public static void StartDiscovery(final Context context, final IMPDClientStatusChange listener){ + final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); + + if (t == null) { + discoveryActive = true; + t = new Thread(new Runnable() { + @Override + public void run() { + while(discoveryActive){ + try { + final String mpd_hostname = sharedPref.getString("mpd_hostname", "").trim(); + final int mpd_port = StringToInt(sharedPref.getString("mpd_port", "6600"), 6600); + + if (mpd_hostname != ""){ + SetDiscoveredStatus(CheckConnection(mpd_hostname, mpd_port), listener); + } + // check every 5 seconds + Thread.sleep(5*1000); + } catch (Exception e) { + SetDiscoveredStatus(false, listener); + } + } + SetDiscoveredStatus(false, listener); + t = null; + } + }); + t.start(); + } + } + + private static void SetDiscoveredStatus(boolean status, IMPDClientStatusChange listener){ + if (status != discovered){ + discovered = status; + listener.changed(); + } + } + + private static boolean CheckConnection(String mpd_hostname, int mpd_port) { + Boolean result = false; + + try { + Log.i(TAG, "Check connection..."); + Socket s = new Socket(mpd_hostname, mpd_port); + BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream())); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); + String info = reader.readLine(); + Log.i(TAG, info); + if (info.startsWith("OK")){ + result = true; + } + reader.close(); + writer.close(); + s.close(); + } catch (Exception e) { + Log.e(TAG,e.toString()); + } + Log.i(TAG, "Connection status:"+result); + return result; + } + + + public static void Stop(Context context) { + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context); + final String mpd_hostname = sharedPref.getString("mpd_hostname", "").trim(); + final int mpd_port = StringToInt(sharedPref.getString("mpd_port", "6600"), 6600); + new Thread(new Runnable() { + @Override + public void run() { + StopInternal(mpd_hostname, mpd_port); + } + }).start(); + } + + private static boolean StopInternal(String mpd_hostname, int mpd_port) { + Boolean result = false; + + try { + Log.i(TAG, "Check connection..."); + Socket s = new Socket(mpd_hostname, mpd_port); + BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream())); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); + String info = reader.readLine(); + Log.i(TAG, info); + if (info.startsWith("OK")) { + String cmd = "stop"; + writer.write(cmd); + writer.newLine(); + writer.flush(); + result = true; + } + reader.close(); + writer.close(); + s.close(); + } catch (Exception e) { + Log.e(TAG,e.toString()); + } + Log.i(TAG, "Connection status:"+result); + return result; + } + + public static void StopDiscovery(){ + discoveryActive = false; + discovered = false; + } + private static Boolean PlayRemoteMPD(String mpd_hostname, int mpd_port, String url){ Boolean result = false; try { @@ -82,4 +206,8 @@ private static Boolean PlayRemoteMPD(String mpd_hostname, int mpd_port, String u } return result; } + + public static boolean Connected() { + return connected; + } } diff --git a/app/src/main/java/net/programmierecke/radiodroid2/Utils.java b/app/src/main/java/net/programmierecke/radiodroid2/Utils.java index d44341459..7d35f3b67 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/Utils.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/Utils.java @@ -183,16 +183,25 @@ protected String doInBackground(Void... params) { protected void onPostExecute(String result) { itsProgressLoading.dismiss(); - MPDClient.Play(result, context); if (result != null) { + boolean externalActive = false; + if (MPDClient.Connected() && MPDClient.Discovered()){ + MPDClient.Play(result, context); + externalActive = true; + } if (mCastSession != null){ PlayRemote(station.Name, result, station.IconUrl); - }else if (external){ - Intent share = new Intent(Intent.ACTION_VIEW); - share.setDataAndType(Uri.parse(result), "audio/*"); - context.startActivity(share); - }else { - PlayerServiceUtil.play(result, station.Name, station.ID, true); + externalActive = true; + } + + if (!externalActive){ + if (external){ + Intent share = new Intent(Intent.ACTION_VIEW); + share.setDataAndType(Uri.parse(result), "audio/*"); + context.startActivity(share); + }else { + PlayerServiceUtil.play(result, station.Name, station.ID, true); + } } } else { Toast toast = Toast.makeText(context.getApplicationContext(), context.getResources().getText(R.string.error_station_load), Toast.LENGTH_SHORT); diff --git a/app/src/main/res/drawable/mpd_nok.png b/app/src/main/res/drawable/mpd_nok.png new file mode 100644 index 0000000000000000000000000000000000000000..25c9e6e49c7b14bbde2bd999328a12c66a2b6702 GIT binary patch literal 4000 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 BK0N>c literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/mpd_ok.png b/app/src/main/res/drawable/mpd_ok.png new file mode 100644 index 0000000000000000000000000000000000000000..e2b0a44bb5b24feb69035e3a03ae23f39bee8527 GIT binary patch literal 3740 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index d8c40efa2..54b0dbb41 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -1,17 +1,17 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 65368400b..ef3597eeb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -96,6 +96,9 @@ Music Player Daemon Hostname Port + MPD not connected + MPD connected + Refresh S From b2082ddd5f6cbe364105eaa22cb5b98b21a72520 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 27 Jun 2017 23:34:35 +0200 Subject: [PATCH 4/8] version to 0.33 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8ced54c51..e26aad910 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { minSdkVersion 14 targetSdkVersion 23 - versionCode 42 - versionName "0.32" + versionCode 43 + versionName "0.33" } buildTypes { release { From 2a4548795f4374e5603cbfbd55c1b9406a61ed83 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 28 Jun 2017 00:15:23 +0200 Subject: [PATCH 5/8] fixed search, mpd status --- app/build.gradle | 4 ++-- .../radiodroid2/ActivityMain.java | 2 ++ .../radiodroid2/MPDClient.java | 1 + app/src/main/res/menu/menu_main.xml | 20 +++++++++---------- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e26aad910..6809fe98f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { minSdkVersion 14 targetSdkVersion 23 - versionCode 43 - versionName "0.33" + versionCode 44 + versionName "0.34" } buildTypes { release { diff --git a/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java b/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java index ea686e847..1f4e36e6a 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/ActivityMain.java @@ -272,6 +272,7 @@ public void onDestroy() { @Override protected void onPause() { + Log.i(TAG,"PAUSED"); super.onPause(); mSessionManager.removeSessionManagerListener(mSessionManagerListener); Utils.mCastSession = null; @@ -360,6 +361,7 @@ protected void onResume() { Utils.mCastSession = mSessionManager.getCurrentCastSession(); mSessionManager.addSessionManagerListener(mSessionManagerListener); + Log.i(TAG,"RESUMED"); MPDClient.StartDiscovery(this, this); } diff --git a/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java b/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java index d6d1add0d..06b09423d 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/MPDClient.java @@ -169,6 +169,7 @@ private static boolean StopInternal(String mpd_hostname, int mpd_port) { public static void StopDiscovery(){ discoveryActive = false; discovered = false; + t = null; } private static Boolean PlayRemoteMPD(String mpd_hostname, int mpd_port, String url){ diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index 54b0dbb41..d711ca713 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -2,17 +2,24 @@ + + + app:showAsAction="always" /> + app:showAsAction="always" /> - - + app:showAsAction="always" /> \ No newline at end of file From 806f34c4f16266bd0a1694d83fdb2eaa00a4e680 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 4 Jul 2017 00:50:25 +0200 Subject: [PATCH 6/8] faster reconnect, recreate player on reconnect --- .../radiodroid2/PlayerService.java | 154 ++++++++++-------- .../radiodroid2/StreamProxy.java | 41 +++-- .../interfaces/IStreamProxyEventReceiver.java | 1 + 3 files changed, 104 insertions(+), 92 deletions(-) diff --git a/app/src/main/java/net/programmierecke/radiodroid2/PlayerService.java b/app/src/main/java/net/programmierecke/radiodroid2/PlayerService.java index 3875b98bd..d652142d0 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/PlayerService.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/PlayerService.java @@ -80,6 +80,7 @@ public class PlayerService extends Service implements IStreamProxyEventReceiver private WifiManager.WifiLock wifiLock; private boolean isHls = false; boolean useExo = false; + private boolean isAlarm = false; enum PlayStatus{ Idle, @@ -384,6 +385,7 @@ public void onAudioFocusChange(int focusChange) { public void ReplayCurrent(final boolean isAlarm) { liveInfo = null; streamInfo = null; + this.isAlarm = isAlarm; SetPlayStatus(PlayStatus.Idle); if (wakeLock == null) { @@ -417,88 +419,21 @@ public void ReplayCurrent(final boolean isAlarm) { useExo = false; } - new Thread(new Runnable() { + /*new Thread(new Runnable() { @Override public void run() { if (proxy != null){ Log.i(TAG,"stop old proxy"); proxy.stop(); proxy = null; - } + }*/ SetPlayStatus(PlayStatus.CreateProxy); proxy = new StreamProxy(PlayerService.this, itsStationURL, PlayerService.this); - String proxyConnection = proxy.getLocalAdress(); - Log.v(TAG, "Stream url:" + proxyConnection); - SetPlayStatus(PlayStatus.ClearOld); - - if (useExo){ - if (player != null){ - player.stop(); - } - - Looper.prepare(); - - if (player == null){ - // 1. Create a default TrackSelector - //Handler mainHandler = new Handler(); - DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); - TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); - TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); - - // 2. Create a default LoadControl - LoadControl loadControl = new DefaultLoadControl(); - - // 3. Create the player - player = ExoPlayerFactory.newSimpleInstance(itsContext, trackSelector, loadControl); - player.setAudioStreamType(isAlarm ? AudioManager.STREAM_ALARM : AudioManager.STREAM_MUSIC); - } - // Produces DataSource instances through which media data is loaded. - DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(itsContext, Util.getUserAgent(itsContext, "yourApplicationName"), null); - // Produces Extractor instances for parsing the media data. - ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory(); - // This is the MediaSource representing the media to be played. - MediaSource videoSource = null; - videoSource = new ExtractorMediaSource(Uri.parse(proxyConnection), dataSourceFactory, extractorsFactory, null, null); - player.prepare(videoSource); - player.setPlayWhenReady(true); - - SetPlayStatus(PlayStatus.Playing); - - Looper.loop(); - }else - { - if (itsMediaPlayer == null) { - itsMediaPlayer = new MediaPlayer(); - } - if (itsMediaPlayer.isPlaying()) { - itsMediaPlayer.stop(); - itsMediaPlayer.reset(); - } - try { - SetPlayStatus(PlayStatus.PrepareStream); - itsMediaPlayer.setAudioStreamType(isAlarm ? AudioManager.STREAM_ALARM : AudioManager.STREAM_MUSIC); - itsMediaPlayer.setDataSource(proxyConnection); - itsMediaPlayer.prepare(); - SetPlayStatus(PlayStatus.PrePlaying); - itsMediaPlayer.start(); - SetPlayStatus(PlayStatus.Playing); - } catch (IllegalArgumentException e) { - Log.e(TAG, "" + e); - ToastOnUi(R.string.error_stream_url); - Stop(); - } catch (IOException e) { - Log.e(TAG, "" + e); - ToastOnUi(R.string.error_caching_stream); - Stop(); - } catch (Exception e) { - Log.e(TAG, "" + e); - ToastOnUi(R.string.error_play_stream); - Stop(); - } - } + /* } }).start(); + */ } void ToastOnUi(final int messageId){ @@ -581,6 +516,83 @@ public void foundLiveStreamInfo(Map liveInfo) { UpdateNotification(); } + @Override + public void streamCreated(final String proxyConnection) { + new Thread(new Runnable() { + @Override + public void run() { + Log.v(TAG, "Stream url:" + proxyConnection); + SetPlayStatus(PlayStatus.ClearOld); + + if (useExo){ + if (player != null){ + player.stop(); + } + + Looper.prepare(); + + if (player == null){ + // 1. Create a default TrackSelector + //Handler mainHandler = new Handler(); + DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); + TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); + TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); + + // 2. Create a default LoadControl + LoadControl loadControl = new DefaultLoadControl(); + + // 3. Create the player + player = ExoPlayerFactory.newSimpleInstance(itsContext, trackSelector, loadControl); + player.setAudioStreamType(isAlarm ? AudioManager.STREAM_ALARM : AudioManager.STREAM_MUSIC); + } + // Produces DataSource instances through which media data is loaded. + DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(itsContext, Util.getUserAgent(itsContext, "yourApplicationName"), null); + // Produces Extractor instances for parsing the media data. + ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory(); + // This is the MediaSource representing the media to be played. + MediaSource videoSource = null; + videoSource = new ExtractorMediaSource(Uri.parse(proxyConnection), dataSourceFactory, extractorsFactory, null, null); + player.prepare(videoSource); + player.setPlayWhenReady(true); + + SetPlayStatus(PlayStatus.Playing); + + Looper.loop(); + }else + { + if (itsMediaPlayer == null) { + itsMediaPlayer = new MediaPlayer(); + } + if (itsMediaPlayer.isPlaying()) { + itsMediaPlayer.stop(); + itsMediaPlayer.reset(); + } + try { + SetPlayStatus(PlayStatus.PrepareStream); + itsMediaPlayer.setAudioStreamType(isAlarm ? AudioManager.STREAM_ALARM : AudioManager.STREAM_MUSIC); + itsMediaPlayer.setDataSource(proxyConnection); + itsMediaPlayer.prepare(); + SetPlayStatus(PlayStatus.PrePlaying); + itsMediaPlayer.start(); + SetPlayStatus(PlayStatus.Playing); + } catch (IllegalArgumentException e) { + Log.e(TAG, "" + e); + ToastOnUi(R.string.error_stream_url); + Stop(); + } catch (IOException e) { + Log.e(TAG, "" + e); + ToastOnUi(R.string.error_caching_stream); + Stop(); + } catch (Exception e) { + Log.e(TAG, "" + e); + ToastOnUi(R.string.error_play_stream); + Stop(); + } + } + } + }).start(); + } + @Override public void streamStopped() { Stop(); diff --git a/app/src/main/java/net/programmierecke/radiodroid2/StreamProxy.java b/app/src/main/java/net/programmierecke/radiodroid2/StreamProxy.java index 14d36a42a..59f767545 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/StreamProxy.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/StreamProxy.java @@ -49,6 +49,7 @@ public StreamProxy(Context context, String uri, IStreamProxyEventReceiver callba private void createProxy() { Log.i(TAG,"thread started"); + /* ServerSocket proxyServer = null; try { proxyServer = new ServerSocket(0, 1, InetAddress.getLocalHost()); @@ -57,34 +58,22 @@ private void createProxy() { } catch (IOException e) { Log.e(TAG,"createProxy() create server socket: "+e); } + */ - if (proxyServer != null) { - final ServerSocket finalProxyServer = proxyServer; + //if (proxyServer != null) { +// final ServerSocket finalProxyServer = proxyServer; new Thread(new Runnable() { @Override public void run() { try { - Log.i(TAG, "waiting.."); - socketProxy = finalProxyServer.accept(); - finalProxyServer.close(); - doConnectToStream(); - Log.i(TAG, "createProxy() ended"); - } catch (IOException e) { + } catch (Exception e) { Log.e(TAG, "" + e); } } }).start(); - - while (localAdress == null) { - try { - Log.i(TAG, "starting serversock..."); - Thread.sleep(100); - } catch (Exception e) { - } - } - } + //} } InputStream in; @@ -272,19 +261,29 @@ private void hlsStream(URL path, int size, InputStream inM3U) throws Exception{ private void doConnectToStream() { try{ - final int MaxRetries = 30; + final int MaxRetries = 100; int retry = MaxRetries; while (!isStopped && retry > 0) { try { // connect to stream - Log.i(TAG,"doConnectToStream:"+uri); + Log.i(TAG,"doConnectToStream (try="+retry+"):"+uri); URL u = new URL(uri); URLConnection connection = u.openConnection(); - connection.setConnectTimeout(5000); - connection.setReadTimeout(10000); + connection.setConnectTimeout(2000); + connection.setReadTimeout(2000); connection.setRequestProperty("Icy-MetaData", "1"); connection.connect(); + Log.i(TAG, "create serversocket.."); + ServerSocket proxyServer = null; + proxyServer = new ServerSocket(0, 1, InetAddress.getLocalHost()); + int port = proxyServer.getLocalPort(); + localAdress = String.format(Locale.US,"http://localhost:%d",port); + Log.i(TAG, "waiting.."); + callback.streamCreated(localAdress); + socketProxy = proxyServer.accept(); + proxyServer.close(); + // send ok message to local mediaplayer out = socketProxy.getOutputStream(); out.write(("HTTP/1.0 200 OK\r\n" + diff --git a/app/src/main/java/net/programmierecke/radiodroid2/interfaces/IStreamProxyEventReceiver.java b/app/src/main/java/net/programmierecke/radiodroid2/interfaces/IStreamProxyEventReceiver.java index aee42c1c2..8330d708d 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/interfaces/IStreamProxyEventReceiver.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/interfaces/IStreamProxyEventReceiver.java @@ -7,5 +7,6 @@ public interface IStreamProxyEventReceiver { void foundShoutcastStream(ShoutcastInfo bitrate, boolean isHls); void foundLiveStreamInfo(Map liveInfo); + void streamCreated(String proxyConnection); void streamStopped(); } From f7fa6e8e64799d3ae857d9d8645a11a2e5a3bac8 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 4 Jul 2017 00:51:07 +0200 Subject: [PATCH 7/8] version to 0.35 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6809fe98f..e5aa29317 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { minSdkVersion 14 targetSdkVersion 23 - versionCode 44 - versionName "0.34" + versionCode 45 + versionName "0.35" } buildTypes { release { From 639e27db0bfc4d8a6701bc4d1cf59c65f150b129 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 4 Jul 2017 20:25:36 +0200 Subject: [PATCH 8/8] fixed play stop bug, version 0.36 --- app/build.gradle | 4 ++-- .../java/net/programmierecke/radiodroid2/PlayerService.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e5aa29317..df03a0c71 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { minSdkVersion 14 targetSdkVersion 23 - versionCode 45 - versionName "0.35" + versionCode 46 + versionName "0.36" } buildTypes { release { diff --git a/app/src/main/java/net/programmierecke/radiodroid2/PlayerService.java b/app/src/main/java/net/programmierecke/radiodroid2/PlayerService.java index d652142d0..2d6641599 100644 --- a/app/src/main/java/net/programmierecke/radiodroid2/PlayerService.java +++ b/app/src/main/java/net/programmierecke/radiodroid2/PlayerService.java @@ -421,12 +421,12 @@ public void ReplayCurrent(final boolean isAlarm) { /*new Thread(new Runnable() { @Override - public void run() { + public void run() {*/ if (proxy != null){ Log.i(TAG,"stop old proxy"); proxy.stop(); proxy = null; - }*/ + } SetPlayStatus(PlayStatus.CreateProxy); proxy = new StreamProxy(PlayerService.this, itsStationURL, PlayerService.this);