diff --git a/app/build.gradle b/app/build.gradle index 9212db2..ac5af8a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,10 +4,10 @@ android { compileSdkVersion 28 defaultConfig { applicationId "net.schueller.peertube" - minSdkVersion 23 + minSdkVersion 21 targetSdkVersion 28 - versionCode 106 - versionName "1.0.6" + versionCode 1010 + versionName "1.0.10" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) @@ -44,11 +44,11 @@ android { // implementation 'org.webrtc:google-webrtc:1.0.+' // video player - implementation 'com.google.android.exoplayer:exoplayer-core:2.8.1' - implementation 'com.google.android.exoplayer:exoplayer-dash:2.8.1' - implementation 'com.google.android.exoplayer:exoplayer-ui:2.8.1' - implementation 'com.google.android.exoplayer:exoplayer-hls:2.8.1' - implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:2.8.1' + implementation 'com.google.android.exoplayer:exoplayer-core:2.9.2' + implementation 'com.google.android.exoplayer:exoplayer-dash:2.9.2' + implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.2' + implementation 'com.google.android.exoplayer:exoplayer-hls:2.9.2' + implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:2.9.2' // implementation 'com.devbrackets.android:exomedia:4.1.0' // testing diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c3e9107..d56e56e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,9 @@ <!-- required for torrent downloading --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <!-- required to play video in background via notification --> + <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> + <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000..c5854ac Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/net/schueller/peertube/activity/SettingsActivity.java b/app/src/main/java/net/schueller/peertube/activity/SettingsActivity.java index 33755b3..f4070fd 100644 --- a/app/src/main/java/net/schueller/peertube/activity/SettingsActivity.java +++ b/app/src/main/java/net/schueller/peertube/activity/SettingsActivity.java @@ -10,7 +10,10 @@ import android.preference.Preference; import android.support.v7.app.ActionBar; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; +import android.util.Patterns; import android.view.MenuItem; +import android.widget.Toast; + import net.schueller.peertube.R; import java.util.List; @@ -34,6 +37,12 @@ public class SettingsActivity extends AppCompatPreferenceActivity { private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = (preference, value) -> { String stringValue = value.toString(); + // check URL is valid + if (preference.getKey().equals("pref_api_base") && !Patterns.WEB_URL.matcher(stringValue).matches()) { + Toast.makeText(preference.getContext(), R.string.invalid_url, Toast.LENGTH_LONG).show(); + return false; + } + preference.setSummary(stringValue); return true; diff --git a/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java b/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java index d886539..b1cef54 100644 --- a/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java +++ b/app/src/main/java/net/schueller/peertube/activity/VideoPlayActivity.java @@ -206,14 +206,14 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere { // get video ID Intent intent = getIntent(); - String videoID = intent.getStringExtra(VideoListActivity.EXTRA_VIDEOID); - Log.v(TAG, "click: " + videoID); + String videoUuid = intent.getStringExtra(VideoListActivity.EXTRA_VIDEOID); + Log.v(TAG, "click: " + videoUuid); // get video details from api String apiBaseURL = APIUrlHelper.getUrlWithVersion(this); GetVideoDataService service = RetrofitInstance.getRetrofitInstance(apiBaseURL).create(GetVideoDataService.class); - Call<Video> call = service.getVideoData(videoID); + Call<Video> call = service.getVideoData(videoUuid); call.enqueue(new Callback<Video>() { @Override @@ -355,8 +355,10 @@ public class VideoPlayActivity extends AppCompatActivity implements VideoRendere @Override protected void onStop() { super.onStop(); - unbindService(mConnection); - mBound = false; + if (mBound) { + unbindService(mConnection); + mBound = false; + } Log.v(TAG, "onStop()..."); } diff --git a/app/src/main/java/net/schueller/peertube/service/VideoPlayerService.java b/app/src/main/java/net/schueller/peertube/service/VideoPlayerService.java index 85f3286..2f42dd1 100644 --- a/app/src/main/java/net/schueller/peertube/service/VideoPlayerService.java +++ b/app/src/main/java/net/schueller/peertube/service/VideoPlayerService.java @@ -1,19 +1,20 @@ package net.schueller.peertube.service; - import android.app.Notification; import android.app.PendingIntent; import android.app.Service; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.graphics.Bitmap; +import android.media.AudioManager; import android.net.Uri; import android.os.Binder; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; - import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; @@ -23,16 +24,15 @@ import com.google.android.exoplayer2.ui.PlayerNotificationManager; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.util.Util; -import com.squareup.picasso.Picasso; import net.schueller.peertube.R; import net.schueller.peertube.activity.VideoPlayActivity; import net.schueller.peertube.helper.MetaDataHelper; import net.schueller.peertube.model.Video; -import java.io.IOException; - -import retrofit2.http.FormUrlEncoded; +import static android.media.session.PlaybackState.ACTION_PAUSE; +import static android.media.session.PlaybackState.ACTION_PLAY; +import static net.schueller.peertube.activity.VideoListActivity.EXTRA_VIDEOID; public class VideoPlayerService extends Service { @@ -48,14 +48,32 @@ public class VideoPlayerService extends Service { private PlayerNotificationManager playerNotificationManager; + private IntentFilter becomeNoisyIntentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); + private BecomingNoisyReceiver myNoisyAudioStreamReceiver = new BecomingNoisyReceiver(); + @Override public void onCreate() { super.onCreate(); - Log.v("VideoPlayerService", "onCreate..."); - player = ExoPlayerFactory.newSimpleInstance(getApplicationContext(), new DefaultTrackSelector()); + // Stop player if audio device changes, e.g. headphones unplugged + player.addListener(new Player.EventListener() { + @Override + public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { + + if (playbackState == ACTION_PAUSE) { // this means that pause is available, hence the audio is playing + Log.v("VideoPlayerService", "ACTION_PLAY: " + playbackState); + registerReceiver(myNoisyAudioStreamReceiver, becomeNoisyIntentFilter); + } + + if (playbackState == ACTION_PLAY) { // this means that play is available, hence the audio is paused or stopped + Log.v("VideoPlayerService", "ACTION_PAUSE: " + playbackState); + unregisterReceiver(myNoisyAudioStreamReceiver); + } + } + } ); + } public class LocalBinder extends Binder { @@ -139,11 +157,11 @@ public class VideoPlayerService extends Service { @Override public PendingIntent createCurrentContentIntent(Player player) { Intent intent = new Intent(context, VideoPlayActivity.class); + intent.putExtra(EXTRA_VIDEOID, currentVideo.getUuid()); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } - @Nullable @Override public String getCurrentContentText(Player player) { return MetaDataHelper.getMetaString( @@ -163,6 +181,9 @@ public class VideoPlayerService extends Service { playerNotificationManager.setSmallIcon(R.drawable.ic_peertube_bw); + // don't show skip buttons in notification + playerNotificationManager.setUseNavigationActions(false); + playerNotificationManager.setNotificationListener( new PlayerNotificationManager.NotificationListener() { @Override @@ -184,4 +205,14 @@ public class VideoPlayerService extends Service { } + // pause playback on audio output change + private class BecomingNoisyReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) { + player.setPlayWhenReady(false); + } + } + } + } diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21d..0000000 --- a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - android:width="108dp" - android:height="108dp" - android:viewportHeight="108" - android:viewportWidth="108"> - <path - android:fillType="evenOdd" - android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z" - android:strokeColor="#00000000" - android:strokeWidth="1"> - <aapt:attr name="android:fillColor"> - <gradient - android:endX="78.5885" - android:endY="90.9159" - android:startX="48.7653" - android:startY="61.0927" - android:type="linear"> - <item - android:color="#44000000" - android:offset="0.0" /> - <item - android:color="#00000000" - android:offset="1.0" /> - </gradient> - </aapt:attr> - </path> - <path - android:fillColor="#FFFFFF" - android:fillType="nonZero" - android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z" - android:strokeColor="#00000000" - android:strokeWidth="1" /> -</vector> diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..3fd521c --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,19 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="45.299145" + android:viewportHeight="45.299145"> + <group android:translateX="17.731401" + android:translateY="11.649572"> + <path + android:pathData="m0.0336,0.34v10.667l8,-5.333" + android:fillColor="#211f20"/> + <path + android:pathData="m0.0336,11.007v10.667l8,-5.333" + android:fillColor="#737373"/> + <path + android:pathData="m8.0336,5.673v10.667l8,-5.333" + android:fillColor="#f1680d"/> + + </group> +</vector> diff --git a/app/src/main/res/drawable/ic_peertube.xml b/app/src/main/res/drawable/ic_peertube.xml index b30ec62..107ecf0 100644 --- a/app/src/main/res/drawable/ic_peertube.xml +++ b/app/src/main/res/drawable/ic_peertube.xml @@ -1,7 +1,7 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="16dp" + android:width="22dp" android:height="22dp" - android:viewportWidth="16" + android:viewportWidth="22" android:viewportHeight="22"> <path android:pathData="m0.0336,0.34v10.667l8,-5.333" @@ -12,7 +12,5 @@ <path android:pathData="m8.0336,5.673v10.667l8,-5.333" android:fillColor="#f1680d"/> - <path - android:pathData="M8.0336,16.34L8.0336,5.673L0.0336,11.007Z" - android:fillColor="#000000"/> + </vector> diff --git a/app/src/main/res/drawable/ic_peertube_bw.xml b/app/src/main/res/drawable/ic_peertube_bw.xml index a0a1ebf..1f00282 100644 --- a/app/src/main/res/drawable/ic_peertube_bw.xml +++ b/app/src/main/res/drawable/ic_peertube_bw.xml @@ -1,7 +1,7 @@ <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="16dp" + android:width="22dp" android:height="22dp" - android:viewportWidth="16" + android:viewportWidth="22" android:viewportHeight="22"> <path android:pathData="m0.0336,0.34v10.667l8,-5.333" diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_background"/> + <foreground android:drawable="@drawable/ic_launcher_foreground"/> +</adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@color/ic_launcher_background"/> + <foreground android:drawable="@drawable/ic_launcher_foreground"/> +</adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index f9ff534..92bb815 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..f55161a Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index dae7075..fdae48a 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..df966be Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index af5dc22..91e24ee 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..584574d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 0d106d5..9ad932e 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..58aede0 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 8136b00..d8c2900 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..fe04e0a Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 1e49e40..0756155 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1,3 +1,4 @@ +<!-- File "app/src/main/res/values/strings.xml" --> <resources> <string name="app_name">PeerTube</string> @@ -15,7 +16,7 @@ <string name="error_invalid_password">كلمة السر قصيرة جدًا</string> <string name="error_incorrect_password">كلمة السر خاطئة</string> <string name="error_field_required">هذا الحقل مطلوب</string> - <string name="permission_rationale">"تصريحات النفاذ إلى قائمة مراسليك مطلوبة لتمكين الملئ التلقائي."</string> + <string name="permission_rationale">"تصريح الوصول إلى جهات الإتصال مطلوب لتمكين الملئ التلقائي."</string> <!-- Action bar --> <string name="action_bar_title_search">البحث</string> @@ -23,7 +24,7 @@ <!-- Bottom navigation bar --> <string name="bottom_nav_title_home">الرئيسية</string> - <string name="bottom_nav_title_trending">المشهورة</string> + <string name="bottom_nav_title_trending">المتصدرة</string> <string name="bottom_nav_title_subscriptions">الإشتراكات</string> <string name="bottom_nav_title_account">الحساب</string> @@ -35,13 +36,29 @@ <!-- Strings related to Video meta data --> - <string name="meta_data_seperator">\\u0020-\\u0020</string> - <string name="meta_data_views">\\u0020مشاهدات</string> - <string name="meta_data_owner_seperator">\\@</string> - + <string name="meta_data_seperator">\u0020-\u0020</string> + <string name="meta_data_views">\u0020مشاهدات</string> + <string name="meta_data_owner_seperator">\@</string> <string name="video_row_video_thumbnail">الصورة المصغرة للفيديو</string> <string name="video_row_account_avatar">الصورة الرمزية للحساب</string> + <string name="pref_title_show_nsfw">عرض NSFW</string> + <string name="pref_description_show_nsfw">عند التفعيل سيتم عرض محتويات NSFW</string> + <string name="title_activity_url_video_play">UrlVideoPlayActivity</string> + <string name="pref_title_torrent_player">مشغل فديو التورنت</string> + <string name="pref_description_torrent_player">تشغيل الفيديو عبر بث التورنت . يتطلب هذا أذونات التخزين. (ألفا ، غير مستقر!)</string> + <string name="pref_title_license">الرخصة</string> + <string name="pref_description_license"><b >GNU Affero General Public License v3.0</b>\n + \n + إن أذونات هذا الترخيص الأقوى للحقوق المتروكة مشروطة بإتاحة الشفرة المصدرية الكاملة للأعمال والتعديلات المرخصة ، والتي تشتمل على أعمال أكبر باستخدام عمل مرخص ، تحت نفس الترخيص. يجب الحفاظ على حقوق النشر وإشعارات الترخيص. يقدم المساهمون منحة صريحة لحقوق البراءة. عند استخدام إصدار معدل لتوفير خدمة عبر شبكة ، يجب توفير شفرة المصدر الكاملة للإصدار المعدل.</string> + <string name="pref_title_version">الإصدار</string> + <string name="search_hint">مشاركة PeerTube</string> + <string name="title_activity_search">بحث</string> + <string name="no_data_available">لاتوجد نتائج</string> + <string name="descr_overflow_button">المزيد</string> + <string name="menu_share">مشاركة</string> + <string name="playback_channel_name">PeerTube</string> + </resources> diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <color name="ic_launcher_background">#FFFFFF</color> +</resources> \ 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 944603f..9d59830 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -59,6 +59,7 @@ <string name="descr_overflow_button">More</string> <string name="menu_share">Share</string> <string name="playback_channel_name">PeerTube</string> + <string name="invalid_url">Invalid Url!</string> <string name="pref_token_access">pref_token_access</string> <string name="pref_token_refresh">pref_token_refresh</string> <string name="pref_token_expiration">pref_token_expiration</string>