From d4e78cae2c78c4dab81f500b2c1ce764da92329f Mon Sep 17 00:00:00 2001 From: Gboy9155 <32224410+Gboy9155@users.noreply.github.com> Date: Wed, 29 Nov 2017 18:46:49 +0100 Subject: [PATCH] youtube login --- MusicApp/Assets/AboutAssets.txt | 19 - MusicApp/Assets/client_secret.json | 1 + MusicApp/MainActivity.cs | 183 +++- MusicApp/MusicApp.csproj | 57 +- MusicApp/Properties/AndroidManifest.xml | 2 +- MusicApp/Resources/AboutResources.txt | 44 - .../Resources/Portable Class/OauthCallback.cs | 41 + MusicApp/Resources/Portable Class/Playlist.cs | 69 +- .../Portable Class/PlaylistTracks.cs | 89 +- .../Resources/Portable Class/YoutubeEngine.cs | 26 +- .../Resources/Portable Class/YtPlaylists.cs | 238 +++++ MusicApp/Resources/Resource.Designer.cs | 818 +++++++++--------- MusicApp/packages.config | 27 +- 13 files changed, 1009 insertions(+), 605 deletions(-) delete mode 100644 MusicApp/Assets/AboutAssets.txt create mode 100644 MusicApp/Assets/client_secret.json delete mode 100644 MusicApp/Resources/AboutResources.txt create mode 100644 MusicApp/Resources/Portable Class/OauthCallback.cs create mode 100644 MusicApp/Resources/Portable Class/YtPlaylists.cs diff --git a/MusicApp/Assets/AboutAssets.txt b/MusicApp/Assets/AboutAssets.txt deleted file mode 100644 index ee39886..0000000 --- a/MusicApp/Assets/AboutAssets.txt +++ /dev/null @@ -1,19 +0,0 @@ -Any raw assets you want to be deployed with your application can be placed in -this directory (and child directories) and given a Build Action of "AndroidAsset". - -These files will be deployed with you package and will be accessible using Android's -AssetManager, like this: - -public class ReadAsset : Activity -{ - protected override void OnCreate (Bundle bundle) - { - base.OnCreate (bundle); - - InputStream input = Assets.Open ("my_asset.txt"); - } -} - -Additionally, some Android functions will automatically load asset files: - -Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); \ No newline at end of file diff --git a/MusicApp/Assets/client_secret.json b/MusicApp/Assets/client_secret.json new file mode 100644 index 0000000..bfe4f30 --- /dev/null +++ b/MusicApp/Assets/client_secret.json @@ -0,0 +1 @@ +{"installed":{"client_id":"758089506779-7gofatbsl2fgh18cua38ovp805n38veb.apps.googleusercontent.com","project_id":"musicapp-185015","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}} \ No newline at end of file diff --git a/MusicApp/MainActivity.cs b/MusicApp/MainActivity.cs index 57c3bf1..38024e3 100644 --- a/MusicApp/MainActivity.cs +++ b/MusicApp/MainActivity.cs @@ -1,18 +1,24 @@ using Android.App; +using Android.Content; using Android.OS; -using Android.Support.V7.App; +using Android.Runtime; using Android.Support.Design.Widget; +using Android.Support.V4.View; +using Android.Support.V7.App; +using Android.Support.V7.Preferences; +using Android.Views; +using Android.Widget; +using Google.Apis.Auth.OAuth2; +using Google.Apis.Services; +using Google.Apis.YouTube.v3; using MusicApp.Resources.Fragments; using MusicApp.Resources.Portable_Class; -using Android.Views; -using Android.Support.V4.View; -using Android.Runtime; -using Android.Widget; -using Android.Content; using MusicApp.Resources.values; using Square.Picasso; using System; - +using System.Collections.Generic; +using System.Linq; +using Xamarin.Auth; using SearchView = Android.Support.V7.Widget.SearchView; namespace MusicApp @@ -29,6 +35,133 @@ namespace MusicApp private bool prepared = false; + #region Youtube + + public const string clientID = "758089506779-tstocfigqvjsog2mq5j295b1305igle0.apps.googleusercontent.com"; + public static YouTubeService youtubeService; + public static OAuth2Authenticator auth; + public static string refreshToken; + + public void Login() + { + AccountStore accountStore = AccountStore.Create(); + Account account = accountStore.FindAccountsForService("Google").FirstOrDefault(); + if (account != null) + { + if (!TokenHasExpire(account.Properties["refresh_token"])) + { + refreshToken = account.Properties["refresh_token"]; + + if (YoutubeEngine.youtubeService != null) + return; + + GoogleCredential credential = GoogleCredential.FromAccessToken(account.Properties["access_token"]); + YoutubeEngine.youtubeService = new YouTubeService(new BaseClientService.Initializer() + { + HttpClientInitializer = credential + }); + } + } + else + { + auth = new OAuth2Authenticator( + clientID, + string.Empty, + YouTubeService.Scope.Youtube, + new Uri("https://accounts.google.com/o/oauth2/v2/auth"), + new Uri("com.musicapp.android:/oauth2redirect"), + new Uri("https://www.googleapis.com/oauth2/v4/token"), + isUsingNativeUI: true); + + auth.Completed += (s, e) => + { + if (e.IsAuthenticated) + { + string tokenType = e.Account.Properties["token_type"]; + string accessToken = e.Account.Properties["access_token"]; + string refreshToken = e.Account.Properties["refresh_token"]; + string expiresIN = e.Account.Properties["expires_in"]; + MainActivity.refreshToken = refreshToken; + + DateTime expireDate = DateTime.UtcNow.AddSeconds(double.Parse(expiresIN)); + ISharedPreferences pref = PreferenceManager.GetDefaultSharedPreferences(this); + ISharedPreferencesEditor editor = pref.Edit(); + editor.PutString("expireDate", expireDate.ToString()); + editor.Apply(); + + GoogleCredential credential = GoogleCredential.FromAccessToken(accessToken); + + YoutubeEngine.youtubeService = new YouTubeService(new BaseClientService.Initializer() + { + HttpClientInitializer = credential, + ApplicationName = "MusicApp" + }); + + AccountStore.Create().Save(e.Account, "Google"); + } + else + { + Toast.MakeText(this, "Error in authentification.", ToastLength.Short).Show(); + } + }; + + StartActivity(auth.GetUI(this)); + } + } + + public bool TokenHasExpire(string refreshToken = null) + { + if (refreshToken == null) + refreshToken = MainActivity.refreshToken; + + ISharedPreferences pref = PreferenceManager.GetDefaultSharedPreferences(this); + string expireDate = pref.GetString("expireDate", null); + if (expireDate != null) + { + DateTime expiresDate = DateTime.Parse(expireDate); + + if (expiresDate > DateTime.UtcNow) + return false; + else + { + RequestNewToken(refreshToken); + return true; + } + } + return true; + } + + public async void RequestNewToken(string refreshToken) + { + Dictionary queryValues = new Dictionary + { + {"refresh_token", refreshToken }, + {"client_id", clientID }, + {"grant_type", "refresh_token" } + }; + await auth.RequestAccessTokenAsync(queryValues).ContinueWith(result => + { + string accessToken = result.Result["access_token"]; + string expiresIN = result.Result["expires_in"]; + + DateTime expireDate = DateTime.UtcNow.AddSeconds(double.Parse(expiresIN)); + ISharedPreferences pref = PreferenceManager.GetDefaultSharedPreferences(this); + ISharedPreferencesEditor editor = pref.Edit(); + editor.PutString("expireDate", expireDate.ToString()); + editor.Apply(); + + GoogleCredential credential = GoogleCredential.FromAccessToken(accessToken); + YoutubeEngine.youtubeService = new YouTubeService(new BaseClientService.Initializer() + { + HttpClientInitializer = credential, + ApplicationName = "MusicApp" + }); + }); + } + + #endregion + + public static int paddingBot { get @@ -99,7 +232,7 @@ namespace MusicApp SupportActionBar.SetDisplayHomeAsUpEnabled(false); SupportActionBar.Title = "MusicApp"; FolderTracks.instance = null; - SetTabs(1); + SetBrowseTabs(1); } } else if(item.ItemId == Resource.Id.search) @@ -209,7 +342,7 @@ namespace MusicApp break; case Resource.Id.browseLayout: - SetTabs(); + SetBrowseTabs(); break; case Resource.Id.downloadLayout: @@ -219,7 +352,7 @@ namespace MusicApp break; case Resource.Id.playlistLayout: - HideTabs(); + SetYtTabs(); HideSearch(); fragment = Playlist.NewInstance(); break; @@ -231,11 +364,10 @@ namespace MusicApp SupportFragmentManager.BeginTransaction().Replace(Resource.Id.contentView, fragment).Commit(); } - void SetTabs(int selectedTab = 0) + void SetBrowseTabs(int selectedTab = 0) { FrameLayout frame = FindViewById(Resource.Id.contentView); frame.Visibility = ViewStates.Gone; - TabLayout tabs = FindViewById(Resource.Id.tabs); tabs.Visibility = ViewStates.Visible; tabs.RemoveAllTabs(); @@ -243,6 +375,7 @@ namespace MusicApp tabs.AddTab(tabs.NewTab().SetText("Folders")); ViewPager pager = FindViewById(Resource.Id.pager); pager.SetPadding(0, 200, 0, 0); + pager.ClearOnPageChangeListeners(); pager.AddOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabs)); ViewPagerAdapter adapter = new ViewPagerAdapter(SupportFragmentManager); @@ -256,6 +389,32 @@ namespace MusicApp tabs.SetScrollPosition(selectedTab, 0f, true); } + void SetYtTabs(int selectedTab = 0) + { + FrameLayout frame = FindViewById(Resource.Id.contentView); + frame.Visibility = ViewStates.Gone; + + TabLayout tabs = FindViewById(Resource.Id.tabs); + tabs.Visibility = ViewStates.Visible; + tabs.RemoveAllTabs(); + tabs.AddTab(tabs.NewTab().SetText("Playlists")); + tabs.AddTab(tabs.NewTab().SetText("Youtube playlists")); + ViewPager pager = FindViewById(Resource.Id.pager); + pager.SetPadding(0, 200, 0, 0); + pager.ClearOnPageChangeListeners(); + pager.AddOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabs)); + ViewPagerAdapter adapter = new ViewPagerAdapter(SupportFragmentManager); + + adapter.AddFragment(Playlist.NewInstance(), "Playlists"); + adapter.AddFragment(YtPlaylist.NewInstance(), "Youtube playlists"); + + pager.Adapter = adapter; + tabs.SetupWithViewPager(pager); + + pager.CurrentItem = selectedTab; + tabs.SetScrollPosition(selectedTab, 0f, true); + } + public void HideTabs() { TabLayout tabs = FindViewById(Resource.Id.tabs); diff --git a/MusicApp/MusicApp.csproj b/MusicApp/MusicApp.csproj index 5ef3b08..529adde 100644 --- a/MusicApp/MusicApp.csproj +++ b/MusicApp/MusicApp.csproj @@ -91,9 +91,39 @@ ..\packages\Google.Apis.YouTube.v3.1.30.0.1035\lib\netstandard1.3\Google.Apis.YouTube.v3.dll + + ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.1.0\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Logging.1.1.1\lib\netstandard1.1\Microsoft.Extensions.Logging.dll + + + ..\packages\Microsoft.Extensions.Logging.Abstractions.1.1.1\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\packages\Microsoft.IdentityModel.Logging.1.1.3\lib\netstandard1.4\Microsoft.IdentityModel.Logging.dll + + + ..\packages\Microsoft.IdentityModel.Tokens.5.1.3\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.dll + ..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll + + ..\packages\PCLCrypto.2.0.147\lib\MonoAndroid23\PCLCrypto.dll + + + ..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll + + + ..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll + + + ..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll + + + ..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll + ..\packages\Plugin.CurrentActivity.1.0.1\lib\MonoAndroid10\Plugin.CurrentActivity.dll @@ -119,11 +149,18 @@ ..\packages\Square.Picasso.2.5.2.1\lib\MonoAndroid\Square.Picasso.dll + + ..\packages\System.IdentityModel.Tokens.Jwt.5.1.3\lib\netstandard1.4\System.IdentityModel.Tokens.Jwt.dll + + + + ..\packages\Validation.2.2.8\lib\dotnet\Validation.dll + ..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.dll @@ -139,6 +176,9 @@ ..\packages\Xamarin.Android.Support.Core.Utils.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Core.Utils.dll + + ..\packages\Xamarin.Android.Support.CustomTabs.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.CustomTabs.dll + ..\packages\Xamarin.Android.Support.Design.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Design.dll @@ -166,6 +206,9 @@ ..\packages\Xamarin.Android.Support.Vector.Drawable.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Vector.Drawable.dll + + ..\packages\Xamarin.Auth.1.5.0.3\lib\MonoAndroid10\Xamarin.Auth.dll + ..\packages\Xamarin.GooglePlayServices.Auth.42.1021.1\lib\MonoAndroid70\Xamarin.GooglePlayServices.Auth.dll @@ -178,9 +221,6 @@ ..\packages\Xamarin.GooglePlayServices.Basement.42.1021.1\lib\MonoAndroid70\Xamarin.GooglePlayServices.Basement.dll - - ..\packages\Xamarin.GooglePlayServices.Identity.42.1021.1\lib\MonoAndroid70\Xamarin.GooglePlayServices.Identity.dll - ..\packages\Xamarin.GooglePlayServices.Tasks.42.1021.1\lib\MonoAndroid70\Xamarin.GooglePlayServices.Tasks.dll @@ -202,6 +242,7 @@ + @@ -213,6 +254,7 @@ + @@ -225,9 +267,7 @@ - - Designer @@ -240,6 +280,9 @@ Designer + + Always + @@ -425,9 +468,9 @@ - + @@ -447,9 +490,9 @@ - +