youtube login

This commit is contained in:
Gboy9155
2017-11-29 18:46:49 +01:00
parent cfb5c2eb91
commit d4e78cae2c
13 changed files with 1009 additions and 605 deletions

View File

@@ -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");

View File

@@ -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"]}}

View File

@@ -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<string, string> queryValues = new Dictionary<string, string>
{
{"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<FrameLayout>(Resource.Id.contentView);
frame.Visibility = ViewStates.Gone;
TabLayout tabs = FindViewById<TabLayout>(Resource.Id.tabs);
tabs.Visibility = ViewStates.Visible;
tabs.RemoveAllTabs();
@@ -243,6 +375,7 @@ namespace MusicApp
tabs.AddTab(tabs.NewTab().SetText("Folders"));
ViewPager pager = FindViewById<ViewPager>(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<FrameLayout>(Resource.Id.contentView);
frame.Visibility = ViewStates.Gone;
TabLayout tabs = FindViewById<TabLayout>(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<ViewPager>(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<TabLayout>(Resource.Id.tabs);

View File

@@ -91,9 +91,39 @@
<HintPath>..\packages\Google.Apis.YouTube.v3.1.30.0.1035\lib\netstandard1.3\Google.Apis.YouTube.v3.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.1.0\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Logging.1.1.1\lib\netstandard1.1\Microsoft.Extensions.Logging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.1.1.1\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Logging, Version=1.1.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.IdentityModel.Logging.1.1.3\lib\netstandard1.4\Microsoft.IdentityModel.Logging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.IdentityModel.Tokens, Version=5.1.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.IdentityModel.Tokens.5.1.3\lib\netstandard1.4\Microsoft.IdentityModel.Tokens.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="PCLCrypto, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d4421c8a4786956c, processorArchitecture=MSIL">
<HintPath>..\packages\PCLCrypto.2.0.147\lib\MonoAndroid23\PCLCrypto.dll</HintPath>
</Reference>
<Reference Include="PInvoke.BCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\packages\PInvoke.BCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.BCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Kernel32, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\packages\PInvoke.Kernel32.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Kernel32.dll</HintPath>
</Reference>
<Reference Include="PInvoke.NCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\packages\PInvoke.NCrypt.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.NCrypt.dll</HintPath>
</Reference>
<Reference Include="PInvoke.Windows.Core, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL">
<HintPath>..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll</HintPath>
</Reference>
<Reference Include="Plugin.CurrentActivity, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Plugin.CurrentActivity.1.0.1\lib\MonoAndroid10\Plugin.CurrentActivity.dll</HintPath>
</Reference>
@@ -119,11 +149,18 @@
<HintPath>..\packages\Square.Picasso.2.5.2.1\lib\MonoAndroid\Square.Picasso.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.IdentityModel.Tokens.Jwt, Version=5.1.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\System.IdentityModel.Tokens.Jwt.5.1.3\lib\netstandard1.4\System.IdentityModel.Tokens.Jwt.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression" />
<Reference Include="System.Json" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="Mono.Android" />
<Reference Include="Validation, Version=2.2.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL">
<HintPath>..\packages\Validation.2.2.8\lib\dotnet\Validation.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Animated.Vector.Drawable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.dll</HintPath>
</Reference>
@@ -139,6 +176,9 @@
<Reference Include="Xamarin.Android.Support.Core.Utils, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Core.Utils.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Core.Utils.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.CustomTabs, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.CustomTabs.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.CustomTabs.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Android.Support.Design, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Design.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Design.dll</HintPath>
</Reference>
@@ -166,6 +206,9 @@
<Reference Include="Xamarin.Android.Support.Vector.Drawable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Android.Support.Vector.Drawable.25.4.0.2\lib\MonoAndroid70\Xamarin.Android.Support.Vector.Drawable.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Auth, Version=1.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.Auth.1.5.0.3\lib\MonoAndroid10\Xamarin.Auth.dll</HintPath>
</Reference>
<Reference Include="Xamarin.GooglePlayServices.Auth, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.GooglePlayServices.Auth.42.1021.1\lib\MonoAndroid70\Xamarin.GooglePlayServices.Auth.dll</HintPath>
</Reference>
@@ -178,9 +221,6 @@
<Reference Include="Xamarin.GooglePlayServices.Basement, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.GooglePlayServices.Basement.42.1021.1\lib\MonoAndroid70\Xamarin.GooglePlayServices.Basement.dll</HintPath>
</Reference>
<Reference Include="Xamarin.GooglePlayServices.Identity, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.GooglePlayServices.Identity.42.1021.1\lib\MonoAndroid70\Xamarin.GooglePlayServices.Identity.dll</HintPath>
</Reference>
<Reference Include="Xamarin.GooglePlayServices.Tasks, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xamarin.GooglePlayServices.Tasks.42.1021.1\lib\MonoAndroid70\Xamarin.GooglePlayServices.Tasks.dll</HintPath>
</Reference>
@@ -202,6 +242,7 @@
<Compile Include="Resources\Portable Class\FolderBrowse.cs" />
<Compile Include="Resources\Portable Class\FolderTracks.cs" />
<Compile Include="Resources\Portable Class\MusicPlayer.cs" />
<Compile Include="Resources\Portable Class\OauthCallback.cs" />
<Compile Include="Resources\Portable Class\Player.cs" />
<Compile Include="Resources\Portable Class\Playlist.cs" />
<Compile Include="Resources\Portable Class\PlaylistTracks.cs" />
@@ -213,6 +254,7 @@
<Compile Include="Resources\Portable Class\YoutubeEngine.cs" />
<Compile Include="Resources\Portable Class\YtAdapter.cs" />
<Compile Include="Resources\Portable Class\YtFile.cs" />
<Compile Include="Resources\Portable Class\YtPlaylists.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources\values\Folder.cs" />
@@ -225,9 +267,7 @@
<None Include="app.config" />
<None Include="GettingStarted.Xamarin" />
<None Include="packages.config" />
<None Include="Resources\AboutResources.txt" />
<None Include="Properties\AndroidManifest.xml" />
<None Include="Assets\AboutAssets.txt" />
<AndroidResource Include="Resources\layout\MusicLayout.axml">
<SubType>Designer</SubType>
</AndroidResource>
@@ -240,6 +280,9 @@
<AndroidResource Include="Resources\layout\DownloadLayout.axml">
<SubType>Designer</SubType>
</AndroidResource>
<AndroidAsset Include="Assets\client_secret.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AndroidAsset>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\Main.axml">
@@ -425,9 +468,9 @@
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Basement.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Basement.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Basement.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Basement.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Tasks.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Tasks.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Tasks.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Tasks.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Base.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Base.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Base.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Identity.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Identity.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Identity.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Identity.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Auth.Base.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Auth.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Auth.Base.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Auth.Base.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.GooglePlayServices.Auth.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Auth.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.GooglePlayServices.Auth.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Auth.targets'))" />
<Error Condition="!Exists('..\packages\Xamarin.Android.Support.CustomTabs.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.CustomTabs.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Android.Support.CustomTabs.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.CustomTabs.targets'))" />
</Target>
<Import Project="..\packages\NETStandard.Library.2.0.1\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\packages\NETStandard.Library.2.0.1\build\netstandard2.0\NETStandard.Library.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.Compat.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Compat.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Compat.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Compat.targets')" />
@@ -447,9 +490,9 @@
<Import Project="..\packages\Xamarin.GooglePlayServices.Basement.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Basement.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Basement.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Basement.targets')" />
<Import Project="..\packages\Xamarin.GooglePlayServices.Tasks.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Tasks.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Tasks.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Tasks.targets')" />
<Import Project="..\packages\Xamarin.GooglePlayServices.Base.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Base.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Base.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Base.targets')" />
<Import Project="..\packages\Xamarin.GooglePlayServices.Identity.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Identity.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Identity.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Identity.targets')" />
<Import Project="..\packages\Xamarin.GooglePlayServices.Auth.Base.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Auth.Base.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Auth.Base.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Auth.Base.targets')" />
<Import Project="..\packages\Xamarin.GooglePlayServices.Auth.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Auth.targets" Condition="Exists('..\packages\Xamarin.GooglePlayServices.Auth.42.1021.1\build\MonoAndroid70\Xamarin.GooglePlayServices.Auth.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.CustomTabs.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.CustomTabs.targets" Condition="Exists('..\packages\Xamarin.Android.Support.CustomTabs.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.CustomTabs.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="MusicApp.MusicApp" android:versionCode="1" android:versionName="1.0" android:installLocation="preferExternal">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.musicapp.android" android:versionCode="1" android:versionName="1.0" android:installLocation="preferExternal">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="25" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />

View File

@@ -1,44 +0,0 @@
Images, layout descriptions, binary blobs and string dictionaries can be included
in your application as resource files. Various Android APIs are designed to
operate on the resource IDs instead of dealing with images, strings or binary blobs
directly.
For example, a sample Android app that contains a user interface layout (main.axml),
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
would keep its resources in the "Resources" directory of the application:
Resources/
drawable/
icon.png
layout/
main.axml
values/
strings.xml
In order to get the build system to recognize Android resources, set the build action to
"AndroidResource". The native Android APIs do not operate directly with filenames, but
instead operate on resource IDs. When you compile an Android application that uses resources,
the build system will package the resources for distribution and generate a class called "R"
(this is an Android convention) that contains the tokens for each one of the resources
included. For example, for the above Resources layout, this is what the R class would expose:
public class R {
public class drawable {
public const int icon = 0x123;
}
public class layout {
public const int main = 0x456;
}
public class strings {
public const int first_string = 0xabc;
public const int second_string = 0xbcd;
}
}
You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
to reference the layout/main.axml file, or R.strings.first_string to reference the first
string in the dictionary file values/strings.xml.

View File

@@ -0,0 +1,41 @@
using System;
using Android.App;
using Android.Content;
using Android.OS;
namespace MusicApp.Resources.Portable_Class
{
[Activity(Label = "OauthCallback")]
[
IntentFilter
(
actions: new[] { Intent.ActionView },
Categories = new[]
{
Intent.CategoryDefault,
Intent.CategoryBrowsable
},
DataSchemes = new[]
{
"com.musicapp.android"
},
DataPaths = new[]
{
"/oauth2redirect"
}
)
]
public class OauthCallback : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Android.Net.Uri IntentUri = Intent.Data;
Uri uri = new Uri(IntentUri.ToString());
MainActivity.auth?.OnPageLoading(uri);
Finish();
}
}
}

View File

@@ -11,11 +11,6 @@ using Android.Content.PM;
using Android.Support.Design.Widget;
using Android;
using Android.Net;
using System.Threading.Tasks;
using Java.Util;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
using MusicApp.Resources.values;
using static Android.Provider.MediaStore.Audio;
namespace MusicApp.Resources.Portable_Class
@@ -41,14 +36,6 @@ namespace MusicApp.Resources.Portable_Class
if(ListView.Adapter == null)
GetStoragePermission();
//if(GoogleAccount != null)
{
if (YoutubeEngine.youtubeService == null)
YoutubeEngine.CreateYoutube();
GetYoutubePlaylists();
}
}
public override void OnDestroy()
@@ -65,7 +52,7 @@ namespace MusicApp.Resources.Portable_Class
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = base.OnCreateView(inflater, container, savedInstanceState);
view.SetPadding(0, 100, 0, MainActivity.paddingBot);
view.SetPadding(0, 0, 0, MainActivity.paddingBot);
return view;
}
@@ -144,56 +131,6 @@ namespace MusicApp.Resources.Portable_Class
}
}
async void GetYoutubePlaylists()
{
while (YoutubeEngine.youtubeService == null)
await Task.Delay(100);
HashMap parameters = new HashMap();
parameters.Put("part", "snippet,contentDetails");
parameters.Put("mine", "true");
parameters.Put("maxResults", "25");
parameters.Put("onBehalfOfContentOwner", "");
parameters.Put("onBehalfOfContentOwnerChannel", "");
YouTubeService youtube = YoutubeEngine.youtubeService;
PlaylistsResource.ListRequest ytPlaylists = youtube.Playlists.List(parameters.Get("part").ToString());
if (parameters.ContainsKey("mine") && parameters.Get("mine").ToString() != "")
{
bool mine = (parameters.Get("mine").ToString() == "true") ? true : false;
ytPlaylists.Mine = mine;
}
if (parameters.ContainsKey("maxResults"))
{
ytPlaylists.MaxResults = long.Parse(parameters.Get("maxResults").ToString());
}
if (parameters.ContainsKey("onBehalfOfContentOwner") && parameters.Get("onBehalfOfContentOwner").ToString() != "")
{
ytPlaylists.OnBehalfOfContentOwner = parameters.Get("onBehalfOfContentOwner").ToString();
}
if (parameters.ContainsKey("onBehalfOfContentOwnerChannel") && parameters.Get("onBehalfOfContentOwnerChannel").ToString() != "")
{
ytPlaylists.OnBehalfOfContentOwnerChannel = parameters.Get("onBehalfOfContentOwnerChannel").ToString();
}
PlaylistListResponse response = await ytPlaylists.ExecuteAsync();
List<Song> ytList = new List<Song>();
for (int i = 0; i < response.Items.Count ; i++)
{
Google.Apis.YouTube.v3.Data.Playlist playlist = response.Items[i];
Song song = new Song(playlist.Snippet.Title, playlist.Snippet.ChannelTitle, playlist.Snippet.Thumbnails.Default__.Url, -1, -1, playlist.Id, true);
ytList.Add(song);
}
Adapter ytAdapter = new Adapter(Android.App.Application.Context, Resource.Layout.SongList, ytList);
}
private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
AppCompatActivity act = (AppCompatActivity)Activity;
@@ -291,8 +228,8 @@ namespace MusicApp.Resources.Portable_Class
void RemovePlaylist(int position, long playlistID)
{
ContentResolver resolver = Activity.ContentResolver;
Uri uri = MediaStore.Audio.Playlists.ExternalContentUri;
resolver.Delete(MediaStore.Audio.Playlists.ExternalContentUri, MediaStore.Audio.Playlists.InterfaceConsts.Id + "=?", new string[] { playlistID.ToString() });
Uri uri = Playlists.ExternalContentUri;
resolver.Delete(Playlists.ExternalContentUri, Playlists.InterfaceConsts.Id + "=?", new string[] { playlistID.ToString() });
playList.RemoveAt(position);
playlistId.RemoveAt(position);
ListAdapter = new ArrayAdapter(Android.App.Application.Context, Resource.Layout.PlaylistList, playList);

View File

@@ -24,7 +24,8 @@ namespace MusicApp.Resources.Portable_Class
public Adapter adapter;
public View emptyView;
public List<Song> result;
public long playlistId;
public long playlistId = 0;
public string ytID = "";
public bool isEmpty = false;
private List<Song> tracks = new List<Song>();
@@ -75,7 +76,16 @@ namespace MusicApp.Resources.Portable_Class
return instance;
}
public static Fragment NewInstance(string ytID)
{
instance = new PlaylistTracks { Arguments = new Bundle() };
instance.ytID = ytID;
return instance;
}
void PopulateList()
{
if(playlistId != 0)
{
Uri musicUri = MediaStore.Audio.Playlists.Members.GetContentUri("external", playlistId);
@@ -124,6 +134,7 @@ namespace MusicApp.Resources.Portable_Class
Activity.AddContentView(emptyView, View.LayoutParameters);
}
}
}
public void Search(string search)
{

View File

@@ -7,12 +7,10 @@ using Android.Support.Design.Widget;
using Google.Apis.YouTube.v3;
using Android.Gms.Common.Apis;
using System.Collections.Generic;
using Google.Apis.Services;
using Android.Preferences;
using YoutubeExplode;
using System.Linq;
using MusicApp.Resources.values;
using System.Threading.Tasks;
using Android.Support.V7.App;
namespace MusicApp.Resources.Portable_Class
@@ -27,7 +25,6 @@ namespace MusicApp.Resources.Portable_Class
private bool isEmpty = true;
private string[] actions = new string[] { "Play", "Play Next", "Play Last", "Download" };
public const string ApiKey = "AIzaSyBOQyZVnBAKjur0ztBuYPSopS725Qudgc4";
private string videoID;
public override void OnActivityCreated(Bundle savedInstanceState)
@@ -49,22 +46,8 @@ namespace MusicApp.Resources.Portable_Class
Activity.AddContentView(emptyView, View.LayoutParameters);
}
CreateYoutube();
}
public static async void CreateYoutube()
{
await Task.Run(() =>
{
if(youtubeService == null)
{
youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
ApiKey = ApiKey,
ApplicationName = "MusicApp"
});
}
});
MainActivity.instance.Login();
}
public override void OnDestroy()
@@ -95,6 +78,11 @@ namespace MusicApp.Resources.Portable_Class
if (search == null || search == "")
return;
if (MainActivity.instance.TokenHasExpire())
{
MainActivity.instance.Login();
}
SearchResource.ListRequest searchResult = youtubeService.Search.List("snippet");
searchResult.Fields = "items(id/videoId,snippet/title,snippet/thumbnails/default/url,snippet/channelTitle)";
searchResult.Q = search;

View File

@@ -0,0 +1,238 @@
using Android.Content;
using Android.OS;
using Android.Views;
using Android.Widget;
using Android.Support.V7.App;
using Android.Support.V4.App;
using System.Collections.Generic;
using Android.Provider;
using Android.Database;
using Android.Content.PM;
using Android.Support.Design.Widget;
using Android;
using Android.Net;
using System.Threading.Tasks;
using Java.Util;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
using MusicApp.Resources.values;
using Java.IO;
using Google.Apis.Auth.OAuth2;
using System.IO;
using Google.Apis.Auth.OAuth2.Flows;
using System.Collections;
using System.Threading;
using Google.Apis.Util.Store;
namespace MusicApp.Resources.Portable_Class
{
public class YtPlaylist : ListFragment
{
public static YtPlaylist instance;
public Adapter adapter;
public View emptyView;
public static Credentials credentials;
private List<Song> playlists = new List<Song>();
private string[] actions = new string[] { "Random play", "Rename", "Delete" };
private bool isEmpty = false;
public override void OnActivityCreated(Bundle savedInstanceState)
{
base.OnActivityCreated(savedInstanceState);
emptyView = LayoutInflater.Inflate(Resource.Layout.NoPlaylist, null);
ListView.EmptyView = emptyView;
if (YoutubeEngine.youtubeService == null)
MainActivity.instance.Login();
GetYoutubePlaylists();
}
public override void OnDestroy()
{
if (isEmpty)
{
ViewGroup rootView = Activity.FindViewById<ViewGroup>(Android.Resource.Id.Content);
rootView.RemoveView(emptyView);
}
base.OnDestroy();
instance = null;
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = base.OnCreateView(inflater, container, savedInstanceState);
view.SetPadding(0, 100, 0, MainActivity.paddingBot);
return view;
}
public static Fragment NewInstance()
{
instance = new YtPlaylist { Arguments = new Bundle() };
return instance;
}
async void GetYoutubePlaylists()
{
while (YoutubeEngine.youtubeService == null)
await Task.Delay(100);
System.Console.WriteLine("getting playlists");
HashMap parameters = new HashMap();
parameters.Put("part", "snippet,contentDetails");
parameters.Put("mine", "true");
parameters.Put("maxResults", "25");
parameters.Put("onBehalfOfContentOwner", "");
parameters.Put("onBehalfOfContentOwnerChannel", "");
YouTubeService youtube = YoutubeEngine.youtubeService;
PlaylistsResource.ListRequest ytPlaylists = youtube.Playlists.List(parameters.Get("part").ToString());
if (parameters.ContainsKey("mine") && parameters.Get("mine").ToString() != "")
{
bool mine = (parameters.Get("mine").ToString() == "true") ? true : false;
ytPlaylists.Mine = mine;
}
if (parameters.ContainsKey("maxResults"))
{
ytPlaylists.MaxResults = long.Parse(parameters.Get("maxResults").ToString());
}
if (parameters.ContainsKey("onBehalfOfContentOwner") && parameters.Get("onBehalfOfContentOwner").ToString() != "")
{
ytPlaylists.OnBehalfOfContentOwner = parameters.Get("onBehalfOfContentOwner").ToString();
}
if (parameters.ContainsKey("onBehalfOfContentOwnerChannel") && parameters.Get("onBehalfOfContentOwnerChannel").ToString() != "")
{
ytPlaylists.OnBehalfOfContentOwnerChannel = parameters.Get("onBehalfOfContentOwnerChannel").ToString();
}
PlaylistListResponse response = await ytPlaylists.ExecuteAsync();
playlists = new List<Song>();
for (int i = 0; i < response.Items.Count; i++)
{
Google.Apis.YouTube.v3.Data.Playlist playlist = response.Items[i];
Song song = new Song(playlist.Snippet.Title, playlist.Snippet.ChannelTitle, playlist.Snippet.Thumbnails.Default__.Url, -1, -1, playlist.Id, true);
playlists.Add(song);
}
Adapter ytAdapter = new Adapter(Android.App.Application.Context, Resource.Layout.SongList, playlists);
}
private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
AppCompatActivity act = (AppCompatActivity)Activity;
act.SupportActionBar.SetHomeButtonEnabled(true);
act.SupportActionBar.SetDisplayHomeAsUpEnabled(true);
act.SupportActionBar.Title = playlists[e.Position].GetName();
FragmentTransaction transaction = FragmentManager.BeginTransaction();
transaction.Replace(Resource.Id.contentView, PlaylistTracks.NewInstance(playlists[e.Position].GetPath()));
transaction.AddToBackStack(null);
transaction.Commit();
}
private void ListView_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e)
{
//AlertDialog.Builder builder = new AlertDialog.Builder(Activity, Resource.Style.AppCompatAlertDialogStyle);
//builder.SetTitle("Pick an action");
//builder.SetItems(actions, (senderAlert, args) =>
//{
// switch (args.Which)
// {
// case 0:
// RandomPlay(playlists[e.Position].GetPath());
// break;
// case 1:
// Rename(e.Position, playlistId[e.Position]);
// break;
// case 2:
// RemovePlaylist(e.Position, playlistId[e.Position]);
// break;
// default:
// break;
// }
//});
//builder.Show();
}
void RandomPlay(long playlistID)
{
List<string> tracksPath = new List<string>();
Uri musicUri = MediaStore.Audio.Playlists.Members.GetContentUri("external", playlistID);
CursorLoader cursorLoader = new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, null);
ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
if (musicCursor != null && musicCursor.MoveToFirst())
{
int pathID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
do
{
string path = musicCursor.GetString(pathID);
tracksPath.Add(path);
}
while (musicCursor.MoveToNext());
musicCursor.Close();
}
Intent intent = new Intent(Android.App.Application.Context, typeof(MusicPlayer));
intent.PutStringArrayListExtra("files", tracksPath);
intent.SetAction("RandomPlay");
Activity.StartService(intent);
}
void Rename(int position, long playlistID)
{
AlertDialog.Builder builder = new AlertDialog.Builder(Activity, Resource.Style.AppCompatAlertDialogStyle);
builder.SetTitle("Playlist name");
View view = LayoutInflater.Inflate(Resource.Layout.CreatePlaylistDialog, null);
builder.SetView(view);
builder.SetNegativeButton("Cancel", (senderAlert, args) => { });
builder.SetPositiveButton("Rename", (senderAlert, args) =>
{
RenamePlaylist(position, view.FindViewById<EditText>(Resource.Id.playlistName).Text, playlistID);
});
builder.Show();
}
void RenamePlaylist(int position, string name, long playlistID)
{
//ContentResolver resolver = Activity.ContentResolver;
//Uri uri = MediaStore.Audio.Playlists.ExternalContentUri;
//ContentValues value = new ContentValues();
//value.Put(MediaStore.Audio.Playlists.InterfaceConsts.Name, name);
//resolver.Update(MediaStore.Audio.Playlists.ExternalContentUri, value, MediaStore.Audio.Playlists.InterfaceConsts.Id + "=?", new string[] { playlistID.ToString() });
//playList[position] = name;
//ListAdapter = new ArrayAdapter(Android.App.Application.Context, Resource.Layout.PlaylistList, playList);
//if (ListAdapter.Count == 0)
//{
// isEmpty = true;
// Activity.AddContentView(emptyView, View.LayoutParameters);
//}
}
void RemovePlaylist(int position, long playlistID)
{
//ContentResolver resolver = Activity.ContentResolver;
//Uri uri = MediaStore.Audio.Playlists.ExternalContentUri;
//resolver.Delete(MediaStore.Audio.Playlists.ExternalContentUri, MediaStore.Audio.Playlists.InterfaceConsts.Id + "=?", new string[] { playlistID.ToString() });
//playList.RemoveAt(position);
//playlistId.RemoveAt(position);
//ListAdapter = new ArrayAdapter(Android.App.Application.Context, Resource.Layout.PlaylistList, playList);
//if (ListAdapter.Count == 0)
//{
// isEmpty = true;
// Activity.AddContentView(emptyView, View.LayoutParameters);
//}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,10 +5,20 @@
<package id="Google.Apis.Core" version="1.30.0" targetFramework="monoandroid70" />
<package id="Google.Apis.YouTube.v3" version="1.30.0.1035" targetFramework="monoandroid70" />
<package id="Microsoft.CSharp" version="4.4.0" targetFramework="monoandroid70" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.1.0" targetFramework="monoandroid71" />
<package id="Microsoft.Extensions.Logging" version="1.1.1" targetFramework="monoandroid71" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="1.1.1" targetFramework="monoandroid71" />
<package id="Microsoft.IdentityModel.Logging" version="1.1.3" targetFramework="monoandroid71" />
<package id="Microsoft.IdentityModel.Tokens" version="5.1.3" targetFramework="monoandroid71" />
<package id="Microsoft.NETCore.Platforms" version="2.0.0" targetFramework="monoandroid70" />
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="monoandroid70" />
<package id="NETStandard.Library" version="2.0.1" targetFramework="monoandroid70" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="monoandroid70" />
<package id="PCLCrypto" version="2.0.147" targetFramework="monoandroid71" />
<package id="PInvoke.BCrypt" version="0.3.2" targetFramework="monoandroid71" />
<package id="PInvoke.Kernel32" version="0.3.2" targetFramework="monoandroid71" />
<package id="PInvoke.NCrypt" version="0.3.2" targetFramework="monoandroid71" />
<package id="PInvoke.Windows.Core" version="0.3.2" targetFramework="monoandroid71" />
<package id="Plugin.CurrentActivity" version="1.0.1" targetFramework="monoandroid70" />
<package id="Plugin.MediaManager" version="0.4.5" targetFramework="monoandroid70" />
<package id="Plugin.Permissions" version="2.1.0" targetFramework="monoandroid70" />
@@ -18,6 +28,7 @@
<package id="System.AppContext" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Collections" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.ComponentModel" version="4.3.0" targetFramework="monoandroid71" />
<package id="System.ComponentModel.TypeConverter" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Console" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="monoandroid70" />
@@ -26,6 +37,7 @@
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Globalization" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Globalization.Calendars" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.IdentityModel.Tokens.Jwt" version="5.1.3" targetFramework="monoandroid71" />
<package id="System.IO" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="monoandroid70" />
@@ -51,6 +63,7 @@
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Runtime.Serialization.Formatters" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Runtime.Serialization.Primitives" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Security.Claims" version="4.3.0" targetFramework="monoandroid71" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="monoandroid70" />
@@ -64,6 +77,7 @@
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="monoandroid70" />
<package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="monoandroid70" />
<package id="Validation" version="2.2.8" targetFramework="monoandroid71" />
<package id="Xam.Plugins.Android.ExoPlayer" version="2.5.3" targetFramework="monoandroid70" />
<package id="Xam.Plugins.Android.ExoPlayer.Core" version="2.5.3" targetFramework="monoandroid70" />
<package id="Xam.Plugins.Android.ExoPlayer.Dash" version="2.5.3" targetFramework="monoandroid70" />
@@ -75,6 +89,7 @@
<package id="Xamarin.Android.Support.Compat" version="25.4.0.2" targetFramework="monoandroid70" />
<package id="Xamarin.Android.Support.Core.UI" version="25.4.0.2" targetFramework="monoandroid70" />
<package id="Xamarin.Android.Support.Core.Utils" version="25.4.0.2" targetFramework="monoandroid70" />
<package id="Xamarin.Android.Support.CustomTabs" version="25.4.0.2" targetFramework="monoandroid71" />
<package id="Xamarin.Android.Support.Design" version="25.4.0.2" targetFramework="monoandroid70" />
<package id="Xamarin.Android.Support.Fragment" version="25.4.0.2" targetFramework="monoandroid70" />
<package id="Xamarin.Android.Support.Media.Compat" version="25.4.0.2" targetFramework="monoandroid70" />
@@ -84,12 +99,12 @@
<package id="Xamarin.Android.Support.v7.Preference" version="25.4.0.2" targetFramework="monoandroid70" />
<package id="Xamarin.Android.Support.v7.RecyclerView" version="25.4.0.2" targetFramework="monoandroid70" />
<package id="Xamarin.Android.Support.Vector.Drawable" version="25.4.0.2" targetFramework="monoandroid70" />
<package id="Xamarin.Auth" version="1.5.0.3" targetFramework="monoandroid71" />
<package id="Xamarin.Build.Download" version="0.4.2" targetFramework="monoandroid70" />
<package id="Xamarin.GooglePlayServices.Auth" version="42.1021.1" targetFramework="monoandroid70" />
<package id="Xamarin.GooglePlayServices.Auth.Base" version="42.1021.1" targetFramework="monoandroid70" />
<package id="Xamarin.GooglePlayServices.Base" version="42.1021.1" targetFramework="monoandroid70" />
<package id="Xamarin.GooglePlayServices.Basement" version="42.1021.1" targetFramework="monoandroid70" />
<package id="Xamarin.GooglePlayServices.Identity" version="42.1021.1" targetFramework="monoandroid70" />
<package id="Xamarin.GooglePlayServices.Tasks" version="42.1021.1" targetFramework="monoandroid70" />
<package id="Xamarin.GooglePlayServices.Auth" version="42.1021.1" targetFramework="monoandroid71" />
<package id="Xamarin.GooglePlayServices.Auth.Base" version="42.1021.1" targetFramework="monoandroid71" />
<package id="Xamarin.GooglePlayServices.Base" version="42.1021.1" targetFramework="monoandroid71" />
<package id="Xamarin.GooglePlayServices.Basement" version="42.1021.1" targetFramework="monoandroid71" />
<package id="Xamarin.GooglePlayServices.Tasks" version="42.1021.1" targetFramework="monoandroid71" />
<package id="YoutubeExplode" version="3.2.5" targetFramework="monoandroid70" />
</packages>