mirror of
https://github.com/zoriya/Opus.git
synced 2025-12-06 06:26:15 +00:00
reworking player to use exoplayer and making youtube play
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26730.12
|
||||
VisualStudioVersion = 15.0.27004.2006
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MusicApp", "MusicApp\MusicApp.csproj", "{35E54AD4-5E2B-4DCD-9C20-F715D682A22B}"
|
||||
EndProject
|
||||
|
||||
@@ -111,8 +111,6 @@ namespace MusicApp
|
||||
|
||||
searchView.QueryTextSubmit += (s, e) =>
|
||||
{
|
||||
if (DownloadList.instance != null)
|
||||
DownloadList.instance.Search(e.Query);
|
||||
if (YoutubeEngine.instance != null)
|
||||
YoutubeEngine.instance.Search(e.Query);
|
||||
|
||||
|
||||
@@ -56,6 +56,24 @@
|
||||
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="ExoPlayer, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xam.Plugins.Android.ExoPlayer.2.5.3\lib\MonoAndroid\ExoPlayer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ExoPlayer.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xam.Plugins.Android.ExoPlayer.Core.2.5.3\lib\MonoAndroid\ExoPlayer.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ExoPlayer.Dash, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xam.Plugins.Android.ExoPlayer.Dash.2.5.3\lib\MonoAndroid\ExoPlayer.Dash.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ExoPlayer.Hls, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xam.Plugins.Android.ExoPlayer.Hls.2.5.3\lib\MonoAndroid\ExoPlayer.Hls.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ExoPlayer.SmoothStreaming, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xam.Plugins.Android.ExoPlayer.SmoothStreaming.2.5.3\lib\MonoAndroid\ExoPlayer.SmoothStreaming.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ExoPlayer.UI, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Xam.Plugins.Android.ExoPlayer.UI.2.5.3\lib\MonoAndroid\ExoPlayer.UI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Google.Apis, Version=1.30.0.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Google.Apis.1.30.0\lib\netstandard1.3\Google.Apis.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -68,8 +86,8 @@
|
||||
<Reference Include="Google.Apis.Core, Version=1.30.0.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Google.Apis.Core.1.30.0\lib\netstandard1.3\Google.Apis.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Google.Apis.YouTube.v3, Version=1.30.0.1006, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Google.Apis.YouTube.v3.1.30.0.1006\lib\netstandard1.3\Google.Apis.YouTube.v3.dll</HintPath>
|
||||
<Reference Include="Google.Apis.YouTube.v3, Version=1.30.0.1035, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
|
||||
<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="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
@@ -168,9 +186,6 @@
|
||||
<Reference Include="YoutubeExplode, Version=3.2.5.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\YoutubeExplode.3.2.5\lib\netstandard1.1\YoutubeExplode.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="YoutubeSearch, Version=0.1.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\YoutubeSearch.dll.1.1\lib\YoutubeSearch.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
@@ -197,7 +212,6 @@
|
||||
<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\YTitemToSong.cs" />
|
||||
<Compile Include="Resources\Resource.Designer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Resources\values\Folder.cs" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?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">
|
||||
<uses-sdk android:minSdkVersion="20" android:targetSdkVersion="24" />
|
||||
<uses-sdk android:minSdkVersion="20" android:targetSdkVersion="25" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
@@ -1,114 +1,113 @@
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Android.Support.V4.App;
|
||||
using System.Collections.Generic;
|
||||
using Android.Support.Design.Widget;
|
||||
using YoutubeSearch;
|
||||
using MusicApp.Resources.values;
|
||||
using Android.Support.V7.Preferences;
|
||||
using Android.Util;
|
||||
//using Android.Content;
|
||||
//using Android.OS;
|
||||
//using Android.Views;
|
||||
//using Android.Widget;
|
||||
//using Android.Support.V4.App;
|
||||
//using System.Collections.Generic;
|
||||
//using Android.Support.Design.Widget;
|
||||
//using MusicApp.Resources.values;
|
||||
//using Android.Support.V7.Preferences;
|
||||
//using Android.Util;
|
||||
|
||||
namespace MusicApp.Resources.Portable_Class
|
||||
{
|
||||
public class DownloadList : ListFragment
|
||||
{
|
||||
public static DownloadList instance;
|
||||
//namespace MusicApp.Resources.Portable_Class
|
||||
//{
|
||||
// public class DownloadList : ListFragment
|
||||
// {
|
||||
// public static DownloadList instance;
|
||||
|
||||
private View emptyView;
|
||||
private bool isEmpty = true;
|
||||
private List<Song> list = new List<Song>();
|
||||
// private View emptyView;
|
||||
// private bool isEmpty = true;
|
||||
// private List<Song> list = new List<Song>();
|
||||
|
||||
|
||||
public override void OnActivityCreated(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnActivityCreated(savedInstanceState);
|
||||
emptyView = LayoutInflater.Inflate(Resource.Layout.DownloadLayout, null);
|
||||
ListView.EmptyView = emptyView;
|
||||
ListView.ItemClick += ListView_ItemClick;
|
||||
ListView.ItemLongClick += ListView_ItemLongClick; ;
|
||||
ListAdapter = null;
|
||||
Activity.AddContentView(emptyView, View.LayoutParameters);
|
||||
}
|
||||
// public override void OnActivityCreated(Bundle savedInstanceState)
|
||||
// {
|
||||
// base.OnActivityCreated(savedInstanceState);
|
||||
// emptyView = LayoutInflater.Inflate(Resource.Layout.DownloadLayout, null);
|
||||
// ListView.EmptyView = emptyView;
|
||||
// ListView.ItemClick += ListView_ItemClick;
|
||||
// ListView.ItemLongClick += ListView_ItemLongClick;
|
||||
// ListAdapter = null;
|
||||
// Activity.AddContentView(emptyView, View.LayoutParameters);
|
||||
// }
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
if (isEmpty)
|
||||
{
|
||||
ViewGroup rootView = Activity.FindViewById<ViewGroup>(Android.Resource.Id.Content);
|
||||
rootView.RemoveView(emptyView);
|
||||
}
|
||||
base.OnDestroy();
|
||||
instance = null;
|
||||
}
|
||||
// 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 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 DownloadList { Arguments = new Bundle() };
|
||||
return instance;
|
||||
}
|
||||
// public static Fragment NewInstance()
|
||||
// {
|
||||
// instance = new DownloadList { Arguments = new Bundle() };
|
||||
// return instance;
|
||||
// }
|
||||
|
||||
public void Search(string search)
|
||||
{
|
||||
if(search == null || search == "")
|
||||
{
|
||||
if(!isEmpty)
|
||||
Activity.AddContentView(emptyView, View.LayoutParameters);
|
||||
return;
|
||||
}
|
||||
if (!isEmpty)
|
||||
{
|
||||
ViewGroup rootView = Activity.FindViewById<ViewGroup>(Android.Resource.Id.Content);
|
||||
rootView.RemoveView(emptyView);
|
||||
isEmpty = false;
|
||||
}
|
||||
// public void Search(string search)
|
||||
// {
|
||||
// if(search == null || search == "")
|
||||
// {
|
||||
// if(!isEmpty)
|
||||
// Activity.AddContentView(emptyView, View.LayoutParameters);
|
||||
// return;
|
||||
// }
|
||||
// if (!isEmpty)
|
||||
// {
|
||||
// ViewGroup rootView = Activity.FindViewById<ViewGroup>(Android.Resource.Id.Content);
|
||||
// rootView.RemoveView(emptyView);
|
||||
// isEmpty = false;
|
||||
// }
|
||||
|
||||
list.Clear();
|
||||
var items = new VideoSearch();
|
||||
// list.Clear();
|
||||
// var items = new VideoSearch();
|
||||
|
||||
foreach(var item in items.SearchQuery(search, 1))
|
||||
{
|
||||
new YTitemToSong(item, out Song song);
|
||||
list.Add(song);
|
||||
}
|
||||
// foreach(var item in items.SearchQuery(search, 1))
|
||||
// {
|
||||
// new YTitemToSong(item, out Song song);
|
||||
// list.Add(song);
|
||||
// }
|
||||
|
||||
ListAdapter = new Adapter(Android.App.Application.Context, Resource.Layout.SongList, list);
|
||||
}
|
||||
// ListAdapter = new Adapter(Android.App.Application.Context, Resource.Layout.SongList, list);
|
||||
// }
|
||||
|
||||
private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
|
||||
{
|
||||
// private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
|
||||
// {
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
private void ListView_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e)
|
||||
{
|
||||
ISharedPreferences prefManager = PreferenceManager.GetDefaultSharedPreferences(Android.App.Application.Context);
|
||||
if(prefManager.GetString("downloadPath", null) != null)
|
||||
{
|
||||
Toast.MakeText(Android.App.Application.Context, "Downloading...", ToastLength.Short).Show();
|
||||
Context context = Android.App.Application.Context;
|
||||
Intent intent = new Intent(context, typeof(Downloader));
|
||||
intent.PutExtra("file", list[e.Position].GetPath());
|
||||
intent.PutExtra("path", prefManager.GetString("downloadPath", null));
|
||||
intent.PutExtra("name", list[e.Position].GetName());
|
||||
context.StartService(intent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Make(View, "Download Path Not Set.", Snackbar.LengthShort).SetAction("Set Path", (v) =>
|
||||
{
|
||||
Intent intent = new Intent(Android.App.Application.Context, typeof(Preferences));
|
||||
StartActivity(intent);
|
||||
}).Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// private void ListView_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e)
|
||||
// {
|
||||
// ISharedPreferences prefManager = PreferenceManager.GetDefaultSharedPreferences(Android.App.Application.Context);
|
||||
// if(prefManager.GetString("downloadPath", null) != null)
|
||||
// {
|
||||
// Toast.MakeText(Android.App.Application.Context, "Downloading...", ToastLength.Short).Show();
|
||||
// Context context = Android.App.Application.Context;
|
||||
// Intent intent = new Intent(context, typeof(Downloader));
|
||||
// intent.PutExtra("file", list[e.Position].GetPath());
|
||||
// intent.PutExtra("path", prefManager.GetString("downloadPath", null));
|
||||
// intent.PutExtra("name", list[e.Position].GetName());
|
||||
// context.StartService(intent);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Snackbar.Make(View, "Download Path Not Set.", Snackbar.LengthShort).SetAction("Set Path", (v) =>
|
||||
// {
|
||||
// Intent intent = new Intent(Android.App.Application.Context, typeof(Preferences));
|
||||
// StartActivity(intent);
|
||||
// }).Show();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -41,21 +41,19 @@ namespace MusicApp.Resources.Portable_Class
|
||||
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
|
||||
{
|
||||
Console.WriteLine("Downloader service started");
|
||||
string uri = intent.GetStringExtra("file");
|
||||
string videoID = intent.GetStringExtra("videoID");
|
||||
string path = intent.GetStringExtra("path");
|
||||
string name = intent.GetStringExtra("name");
|
||||
DownloadAudio(uri, path, name);
|
||||
DownloadAudio(videoID, path, name);
|
||||
return StartCommandResult.Sticky;
|
||||
}
|
||||
|
||||
private async void DownloadAudio(string uri, string path, string name)
|
||||
private async void DownloadAudio(string videoID, string path, string name)
|
||||
{
|
||||
CreateNotification("Downloading: ", name);
|
||||
string videoID = uri.Remove(0, uri.IndexOf("=") + 1);
|
||||
|
||||
var client = new YoutubeClient();
|
||||
var videoInfo = await client.GetVideoInfoAsync(videoID);
|
||||
|
||||
var streamInfo = videoInfo.AudioStreams.OrderBy(s => s.Bitrate).Last();
|
||||
|
||||
string fileExtension = streamInfo.Container.GetFileExtension();
|
||||
|
||||
@@ -16,13 +16,18 @@ using Square.Picasso;
|
||||
|
||||
using Uri = Android.Net.Uri;
|
||||
using Android.Widget;
|
||||
using Com.Google.Android.Exoplayer2;
|
||||
using Com.Google.Android.Exoplayer2.Trackselection;
|
||||
using Com.Google.Android.Exoplayer2.Upstream;
|
||||
using Com.Google.Android.Exoplayer2.Source;
|
||||
using Com.Google.Android.Exoplayer2.Extractor;
|
||||
|
||||
namespace MusicApp.Resources.Portable_Class
|
||||
{
|
||||
[Service]
|
||||
public class MusicPlayer : Service, AudioManager.IOnAudioFocusChangeListener
|
||||
public class MusicPlayer : Service, IPlayerEventListener, AudioManager.IOnAudioFocusChangeListener
|
||||
{
|
||||
public static MediaPlayer player;
|
||||
public static SimpleExoPlayer player;
|
||||
public static List<Song> queue = new List<Song>();
|
||||
public MediaSessionCompat mediaSession;
|
||||
public AudioManager audioManager;
|
||||
@@ -55,7 +60,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
break;
|
||||
|
||||
case "Pause":
|
||||
if (player.IsPlaying)
|
||||
if(isRunning)
|
||||
Pause();
|
||||
else
|
||||
Resume();
|
||||
@@ -82,18 +87,9 @@ namespace MusicApp.Resources.Portable_Class
|
||||
SwitchQueue(file);
|
||||
break;
|
||||
case "Stop":
|
||||
if (player.IsPlaying)
|
||||
if(isRunning)
|
||||
Stop();
|
||||
break;
|
||||
case "YTPlay":
|
||||
string[] song = intent.GetStringArrayListExtra("song").ToArray();
|
||||
Console.WriteLine(song.Length);
|
||||
Console.WriteLine(song[0]);
|
||||
Console.WriteLine(song[1]);
|
||||
Console.WriteLine(song[2]);
|
||||
|
||||
PlayFromYT(file, song[0], song[1], song[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (intent.Action != null)
|
||||
@@ -109,90 +105,47 @@ namespace MusicApp.Resources.Portable_Class
|
||||
{
|
||||
audioManager = (AudioManager)Application.Context.GetSystemService(AudioService);
|
||||
notificationManager = (NotificationManager)Application.Context.GetSystemService(NotificationService);
|
||||
|
||||
player = new MediaPlayer();
|
||||
InitializePlayer();
|
||||
DefaultBandwidthMeter bandwithMeter = new DefaultBandwidthMeter();
|
||||
AdaptiveTrackSelection.Factory trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwithMeter);
|
||||
TrackSelector trackSelector = new DefaultTrackSelector(trackSelectionFactory);
|
||||
player = ExoPlayerFactory.NewSimpleInstance(Application.Context, trackSelector);
|
||||
player.PlayWhenReady = true;
|
||||
player.AddListener(this);
|
||||
}
|
||||
|
||||
private void InitializePlayer()
|
||||
{
|
||||
player.SetAudioStreamType(Stream.Music);
|
||||
player.SetWakeMode(Application.Context, WakeLockFlags.Partial);
|
||||
|
||||
player.Prepared += (sender, args) => player.Start();
|
||||
player.Completion += (sender, args) => PlayNext();
|
||||
player.Error += (sender, args) =>
|
||||
{
|
||||
Console.WriteLine("Error in playback resetting: " + args.What);
|
||||
Stop();
|
||||
};
|
||||
}
|
||||
|
||||
public async void Play(string filePath)
|
||||
public void Play(string filePath)
|
||||
{
|
||||
isRunning = true;
|
||||
if (player == null)
|
||||
InitializeService();
|
||||
|
||||
if (mediaSession != null)
|
||||
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(Application.Context, "MusicApp");
|
||||
IExtractorsFactory extractorFactory = new DefaultExtractorsFactory();
|
||||
Handler handler = new Handler();
|
||||
IMediaSource mediaSource = new ExtractorMediaSource(Uri.Parse(filePath), dataSourceFactory, extractorFactory, handler, null);
|
||||
var audioFocus = audioManager.RequestAudioFocus(this, Stream.Music, AudioFocus.Gain);
|
||||
if (audioFocus != AudioFocusRequest.Granted)
|
||||
{
|
||||
player.Reset();
|
||||
InitializePlayer();
|
||||
await player.SetDataSourceAsync(Application.Context, Uri.Parse(filePath));
|
||||
player.PrepareAsync();
|
||||
GetTrackSong(filePath, out Song song);
|
||||
CreateNotification(song.GetName(), song.GetArtist(), song.GetAlbumArt());
|
||||
queue.Clear();
|
||||
AddToQueue(filePath);
|
||||
Console.WriteLine("Can't Get Audio Focus");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
mediaSession = new MediaSessionCompat(Application.Context, "MusicApp");
|
||||
mediaSession.SetFlags(MediaSessionCompat.FlagHandlesMediaButtons | MediaSessionCompat.FlagHandlesTransportControls);
|
||||
PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder().SetActions(PlaybackStateCompat.ActionPlay | PlaybackStateCompat.ActionPause);
|
||||
mediaSession.SetPlaybackState(builder.Build());
|
||||
player.Prepare(mediaSource, true, true);
|
||||
|
||||
await player.SetDataSourceAsync(Application.Context, Android.Net.Uri.Parse(filePath));
|
||||
var audioFocus = audioManager.RequestAudioFocus(this, Stream.Music, AudioFocus.Gain);
|
||||
if (audioFocus != AudioFocusRequest.Granted)
|
||||
{
|
||||
Console.WriteLine("Can't Get Audio Focus");
|
||||
return;
|
||||
}
|
||||
player.PrepareAsync();
|
||||
GetTrackSong(filePath, out Song song);
|
||||
CreateNotification(song.GetName(), song.GetArtist(), song.GetAlbumArt());
|
||||
queue.Clear();
|
||||
AddToQueue(filePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async void PlayFromYT(string url, string title, string artist, string imageURL)
|
||||
{
|
||||
Console.WriteLine("URL: " + url);
|
||||
InitializeService();
|
||||
await player.SetDataSourceAsync(Application.Context, Uri.Parse(url));
|
||||
player.PrepareAsync();
|
||||
//isRunning = true;
|
||||
//if (player == null)
|
||||
// InitializeService();
|
||||
GetTrackSong(filePath, out Song song);
|
||||
CreateNotification(song.GetName(), song.GetArtist(), song.GetAlbumArt());
|
||||
queue.Clear();
|
||||
AddToQueue(song);
|
||||
|
||||
//if (mediaSession != null)
|
||||
//{
|
||||
// player.Reset();
|
||||
// InitializePlayer();
|
||||
// await player.SetDataSourceAsync(Application.Context, Uri.Parse(url));
|
||||
// await player.SetDataSourceAsync(Application.Context, Uri.Parse(filePath));
|
||||
// player.PrepareAsync();
|
||||
// CreateNotification(title, artist, 0, imageURL);
|
||||
|
||||
// GetTrackSong(filePath, out Song song);
|
||||
// CreateNotification(song.GetName(), song.GetArtist(), song.GetAlbumArt());
|
||||
// queue.Clear();
|
||||
// Song item = new Song(title, artist, imageURL, -1, 1, url);
|
||||
// queue.Add(item);
|
||||
// AddToQueue(filePath);
|
||||
// return;
|
||||
//}
|
||||
//try
|
||||
@@ -202,7 +155,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
// PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder().SetActions(PlaybackStateCompat.ActionPlay | PlaybackStateCompat.ActionPause);
|
||||
// mediaSession.SetPlaybackState(builder.Build());
|
||||
|
||||
// await player.SetDataSourceAsync(Application.Context, Uri.Parse(url));
|
||||
// await player.SetDataSourceAsync(Application.Context, Android.Net.Uri.Parse(filePath));
|
||||
// var audioFocus = audioManager.RequestAudioFocus(this, Stream.Music, AudioFocus.Gain);
|
||||
// if (audioFocus != AudioFocusRequest.Granted)
|
||||
// {
|
||||
@@ -210,10 +163,10 @@ namespace MusicApp.Resources.Portable_Class
|
||||
// return;
|
||||
// }
|
||||
// player.PrepareAsync();
|
||||
// CreateNotification(title, artist, 0, imageURL);
|
||||
// GetTrackSong(filePath, out Song song);
|
||||
// CreateNotification(song.GetName(), song.GetArtist(), song.GetAlbumArt());
|
||||
// queue.Clear();
|
||||
// Song item = new Song(title, artist, imageURL, -1, 1, url);
|
||||
// queue.Add(item);
|
||||
// AddToQueue(filePath);
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
@@ -239,7 +192,14 @@ namespace MusicApp.Resources.Portable_Class
|
||||
public void AddToQueue(string filePath)
|
||||
{
|
||||
GetTrackSong(filePath, out Song song);
|
||||
Console.WriteLine("AddToQueue path: " + song.GetPath() + " Before get track song: " + filePath);
|
||||
if (CurrentID() == -1)
|
||||
queue.Add(song);
|
||||
else
|
||||
queue.Insert(CurrentID() + 1, song);
|
||||
}
|
||||
|
||||
public void AddToQueue(Song song)
|
||||
{
|
||||
if (CurrentID() == -1)
|
||||
queue.Add(song);
|
||||
else
|
||||
@@ -275,17 +235,11 @@ namespace MusicApp.Resources.Portable_Class
|
||||
SwitchQueue(filePath);
|
||||
}
|
||||
|
||||
async void SwitchQueue(string filePath)
|
||||
void SwitchQueue(string filePath)
|
||||
{
|
||||
isRunning = true;
|
||||
Play(filePath);
|
||||
|
||||
if(player != null)
|
||||
player.Reset();
|
||||
InitializePlayer();
|
||||
await player.SetDataSourceAsync(Application.Context, Uri.Parse(filePath));
|
||||
player.PrepareAsync();
|
||||
GetTrackSong(filePath, out Song song);
|
||||
CreateNotification(song.GetName(), song.GetArtist(), song.GetAlbumArt());
|
||||
|
||||
if (Player.instance != null)
|
||||
Player.instance.RefreshPlayer();
|
||||
@@ -315,8 +269,8 @@ namespace MusicApp.Resources.Portable_Class
|
||||
|
||||
public static void SetSeekBar(SeekBar bar)
|
||||
{
|
||||
bar.Max = player.Duration;
|
||||
bar.Progress = player.CurrentPosition;
|
||||
bar.Max = (int) player.Duration;
|
||||
bar.Progress = (int) player.CurrentPosition;
|
||||
bar.ProgressChanged += (sender, e) =>
|
||||
{
|
||||
if (player != null && e.FromUser)
|
||||
@@ -328,7 +282,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
{
|
||||
get
|
||||
{
|
||||
return player.Duration;
|
||||
return (int) player.Duration;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +290,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
{
|
||||
get
|
||||
{
|
||||
return player.CurrentPosition;
|
||||
return (int) player.CurrentPosition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,6 +303,10 @@ namespace MusicApp.Resources.Portable_Class
|
||||
long id = 0;
|
||||
string path = filePath;
|
||||
|
||||
if (false /*Check if it's a youtube video*/)
|
||||
{
|
||||
//return information about a youtube video
|
||||
}
|
||||
|
||||
Uri musicUri = MediaStore.Audio.Media.ExternalContentUri;
|
||||
|
||||
@@ -406,7 +364,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
{
|
||||
icon = Picasso.With(Application.Context).Load(iconURI).Error(Resource.Drawable.MusicIcon).Placeholder(Resource.Drawable.MusicIcon).NetworkPolicy(NetworkPolicy.Offline).Resize(400, 400).CenterCrop().Get();
|
||||
}
|
||||
catch (Exception)
|
||||
catch (System.Exception)
|
||||
{
|
||||
icon = Picasso.With(Application.Context).Load(Resource.Drawable.MusicIcon).Get();
|
||||
}
|
||||
@@ -452,7 +410,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
if(player != null && player.IsPlaying)
|
||||
if(player != null && isRunning)
|
||||
{
|
||||
Intent tmpPauseIntent = new Intent(Application.Context, typeof(MusicPlayer));
|
||||
tmpPauseIntent.SetAction("Pause");
|
||||
@@ -461,7 +419,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
notification.Actions[1] = new Notification.Action(Resource.Drawable.ic_play_arrow_black_24dp, "Play", pauseIntent);
|
||||
notificationManager.Notify(notificationID, notification);
|
||||
|
||||
player.Pause();
|
||||
player.PlayWhenReady = false;
|
||||
StopForeground(false);
|
||||
|
||||
RelativeLayout smallPlayer = MainActivity.instance.FindViewById<RelativeLayout>(Resource.Id.smallPlayer);
|
||||
@@ -476,7 +434,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
|
||||
public void Resume()
|
||||
{
|
||||
if(player != null && !player.IsPlaying)
|
||||
if(player != null && !isRunning)
|
||||
{
|
||||
Intent tmpPauseIntent = new Intent(Application.Context, typeof(MusicPlayer));
|
||||
tmpPauseIntent.SetAction("Pause");
|
||||
@@ -484,7 +442,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
|
||||
notification.Actions[1] = new Notification.Action(Resource.Drawable.ic_pause_black_24dp, "Pause", pauseIntent);
|
||||
|
||||
player.Start();
|
||||
player.PlayWhenReady = true;
|
||||
StartForeground(notificationID, notification);
|
||||
|
||||
RelativeLayout smallPlayer = MainActivity.instance.FindViewById<RelativeLayout>(Resource.Id.smallPlayer);
|
||||
@@ -503,9 +461,9 @@ namespace MusicApp.Resources.Portable_Class
|
||||
MainActivity.instance.HideSmallPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
if (player.IsPlaying)
|
||||
if (isRunning)
|
||||
player.Stop();
|
||||
player.Reset();
|
||||
player.Release();
|
||||
StopForeground(true);
|
||||
}
|
||||
}
|
||||
@@ -516,12 +474,12 @@ namespace MusicApp.Resources.Portable_Class
|
||||
{
|
||||
case AudioFocus.Gain:
|
||||
if (player == null)
|
||||
InitializePlayer();
|
||||
InitializeService();
|
||||
|
||||
if (!player.IsPlaying)
|
||||
player.Start();
|
||||
if (!isRunning)
|
||||
player.PlayWhenReady = true;
|
||||
|
||||
player.SetVolume(1, 1);
|
||||
player.Volume = 1;
|
||||
break;
|
||||
|
||||
case AudioFocus.Loss:
|
||||
@@ -533,8 +491,8 @@ namespace MusicApp.Resources.Portable_Class
|
||||
break;
|
||||
|
||||
case AudioFocus.LossTransientCanDuck:
|
||||
if (player.IsPlaying)
|
||||
player.SetVolume(.2f, .2f);
|
||||
if (isRunning)
|
||||
player.Volume = 0.2f;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -551,5 +509,45 @@ namespace MusicApp.Resources.Portable_Class
|
||||
if (player != null)
|
||||
player.Release();
|
||||
}
|
||||
|
||||
public void OnLoadingChanged(bool p0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnPlaybackParametersChanged(PlaybackParameters p0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnPlayerError(ExoPlaybackException args)
|
||||
{
|
||||
Console.WriteLine("Error in playback resetting: " + args.Cause);
|
||||
}
|
||||
|
||||
public void OnPlayerStateChanged(bool p0, int p1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnPositionDiscontinuity()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnRepeatModeChanged(int p0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnTimelineChanged(Timeline p0, Java.Lang.Object p1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnTracksChanged(TrackGroupArray p0, TrackSelectionArray p1)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using MusicApp.Resources.values;
|
||||
using YoutubeSearch;
|
||||
|
||||
namespace MusicApp.Resources.Portable_Class
|
||||
{
|
||||
public class YTitemToSong
|
||||
{
|
||||
public YTitemToSong(VideoInformation item, out Song song)
|
||||
{
|
||||
string title = item.Title;
|
||||
string artist = item.Author;
|
||||
string album = item.Thumbnail;
|
||||
long albumArt = -1;
|
||||
long id = 1;
|
||||
string path = item.Url;
|
||||
|
||||
song = new Song(title, artist, album, albumArt, id, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,10 @@ using Android.Gms.Auth.Api;
|
||||
using System.Collections.Generic;
|
||||
using Google.Apis.Services;
|
||||
using Android.Accounts;
|
||||
using Android.Preferences;
|
||||
using System;
|
||||
using YoutubeExplode;
|
||||
using System.Linq;
|
||||
|
||||
namespace MusicApp.Resources.Portable_Class
|
||||
{
|
||||
@@ -27,6 +31,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
|
||||
private string ApiKey = "AIzaSyBOQyZVnBAKjur0ztBuYPSopS725Qudgc4";
|
||||
private YouTubeService youtubeService;
|
||||
private string videoID;
|
||||
//private string oAuthKey;
|
||||
//private GoogleApiClient googleClient;
|
||||
//private const int signPickerID = 9001;
|
||||
@@ -47,6 +52,8 @@ namespace MusicApp.Resources.Portable_Class
|
||||
ListView.EmptyView = emptyView;
|
||||
Activity.AddContentView(emptyView, View.LayoutParameters);
|
||||
ListAdapter = null;
|
||||
ListView.ItemClick += ListView_ItemClick;
|
||||
ListView.ItemLongClick += ListView_ItemLongClick;
|
||||
|
||||
if (youtubeService == null)
|
||||
{
|
||||
@@ -152,48 +159,48 @@ namespace MusicApp.Resources.Portable_Class
|
||||
#endregion
|
||||
|
||||
#region Permissions
|
||||
void GetPermissions(string[] permissions)
|
||||
{
|
||||
bool hasPermissions = CheckPermissions(permissions);
|
||||
//void GetPermissions(string[] permissions)
|
||||
//{
|
||||
// bool hasPermissions = CheckPermissions(permissions);
|
||||
|
||||
if (!hasPermissions)
|
||||
RequestPermissions(permissions, 0);
|
||||
//else
|
||||
// PopulateList();
|
||||
}
|
||||
// if (!hasPermissions)
|
||||
// RequestPermissions(permissions, 0);
|
||||
// //else
|
||||
// // PopulateList();
|
||||
//}
|
||||
|
||||
bool CheckPermissions(string[] permissions)
|
||||
{
|
||||
bool hasPermissions = true;
|
||||
foreach (string permission in permissions)
|
||||
{
|
||||
if (Android.Support.V4.Content.ContextCompat.CheckSelfPermission(Android.App.Application.Context, permission) != (int)Permission.Granted)
|
||||
{
|
||||
hasPermissions = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hasPermissions;
|
||||
}
|
||||
//bool CheckPermissions(string[] permissions)
|
||||
//{
|
||||
// bool hasPermissions = true;
|
||||
// foreach (string permission in permissions)
|
||||
// {
|
||||
// if (Android.Support.V4.Content.ContextCompat.CheckSelfPermission(Android.App.Application.Context, permission) != (int)Permission.Granted)
|
||||
// {
|
||||
// hasPermissions = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// return hasPermissions;
|
||||
//}
|
||||
|
||||
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
|
||||
{
|
||||
switch (requestCode)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (grantResults[0] == Permission.Granted)
|
||||
{
|
||||
PopulateList();
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Make(View, "Permission denied, can't list search on youtube.", Snackbar.LengthShort).Show();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
|
||||
//{
|
||||
// switch (requestCode)
|
||||
// {
|
||||
// case 0:
|
||||
// {
|
||||
// if (grantResults[0] == Permission.Granted)
|
||||
// {
|
||||
// PopulateList();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Snackbar.Make(View, "Permission denied, can't list search on youtube.", Snackbar.LengthShort).Show();
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
#endregion
|
||||
|
||||
public async void Search(string search)
|
||||
@@ -220,9 +227,39 @@ namespace MusicApp.Resources.Portable_Class
|
||||
ListAdapter = new YtAdapter(Android.App.Application.Context, Resource.Layout.YtList, result);
|
||||
}
|
||||
|
||||
void PopulateList()
|
||||
private async void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
|
||||
{
|
||||
videoID = result[e.Position].Id;
|
||||
var client = new YoutubeClient();
|
||||
var videoInfo = await client.GetVideoInfoAsync(videoID);
|
||||
var streamInfo = videoInfo.AudioStreams.OrderBy(s => s.Bitrate).Last();
|
||||
|
||||
Intent intent = new Intent(Android.App.Application.Context, typeof(MusicPlayer));
|
||||
intent.PutExtra("file", streamInfo.Url);
|
||||
Android.App.Application.Context.StartService(intent);
|
||||
}
|
||||
|
||||
private void ListView_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e)
|
||||
{
|
||||
ISharedPreferences prefManager = PreferenceManager.GetDefaultSharedPreferences(Android.App.Application.Context);
|
||||
if (prefManager.GetString("downloadPath", null) != null)
|
||||
{
|
||||
Toast.MakeText(Android.App.Application.Context, "Downloading...", ToastLength.Short).Show();
|
||||
Context context = Android.App.Application.Context;
|
||||
Intent intent = new Intent(context, typeof(Downloader));
|
||||
intent.PutExtra("videoID", result[e.Position].Id);
|
||||
intent.PutExtra("path", prefManager.GetString("downloadPath", null));
|
||||
intent.PutExtra("name", result[e.Position].Title);
|
||||
context.StartService(intent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Make(View, "Download Path Not Set.", Snackbar.LengthShort).SetAction("Set Path", (v) =>
|
||||
{
|
||||
Intent intent = new Intent(Android.App.Application.Context, typeof(Preferences));
|
||||
StartActivity(intent);
|
||||
}).Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace MusicApp.Resources.Portable_Class
|
||||
Artist = { Text = ytList[position].channelTitle },
|
||||
};
|
||||
|
||||
Picasso.With(Application.Context).Load(ytList[position].thumbnailUrl).Placeholder(Resource.Drawable.MusicIcon).Resize(400, 400).CenterCrop().Into(holder.AlbumArt);
|
||||
Picasso.With(Application.Context).Load(ytList[position].thumbnailUrl).Placeholder(Resource.Drawable.MusicIcon).Into(holder.AlbumArt);
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
1652
MusicApp/Resources/Resource.Designer.cs
generated
1652
MusicApp/Resources/Resource.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
<package id="Google.Apis" version="1.30.0" targetFramework="monoandroid70" />
|
||||
<package id="Google.Apis.Auth" version="1.30.0" targetFramework="monoandroid70" />
|
||||
<package id="Google.Apis.Core" version="1.30.0" targetFramework="monoandroid70" />
|
||||
<package id="Google.Apis.YouTube.v3" version="1.30.0.1006" 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.NETCore.Platforms" version="2.0.0" targetFramework="monoandroid70" />
|
||||
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="monoandroid70" />
|
||||
@@ -64,6 +64,12 @@
|
||||
<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="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" />
|
||||
<package id="Xam.Plugins.Android.ExoPlayer.Hls" version="2.5.3" targetFramework="monoandroid70" />
|
||||
<package id="Xam.Plugins.Android.ExoPlayer.SmoothStreaming" version="2.5.3" targetFramework="monoandroid70" />
|
||||
<package id="Xam.Plugins.Android.ExoPlayer.UI" version="2.5.3" targetFramework="monoandroid70" />
|
||||
<package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="25.4.0.2" targetFramework="monoandroid70" />
|
||||
<package id="Xamarin.Android.Support.Annotations" version="25.4.0.2" targetFramework="monoandroid70" />
|
||||
<package id="Xamarin.Android.Support.Compat" version="25.4.0.2" targetFramework="monoandroid70" />
|
||||
@@ -86,5 +92,4 @@
|
||||
<package id="Xamarin.GooglePlayServices.Identity" version="42.1021.1" targetFramework="monoandroid70" />
|
||||
<package id="Xamarin.GooglePlayServices.Tasks" version="42.1021.1" targetFramework="monoandroid70" />
|
||||
<package id="YoutubeExplode" version="3.2.5" targetFramework="monoandroid70" />
|
||||
<package id="YoutubeSearch.dll" version="1.1" targetFramework="monoandroid70" />
|
||||
</packages>
|
||||
48
YouTubeApi/Additions/AboutAdditions.txt
Normal file
48
YouTubeApi/Additions/AboutAdditions.txt
Normal file
@@ -0,0 +1,48 @@
|
||||
Additions allow you to add arbitrary C# to the generated classes
|
||||
before they are compiled. This can be helpful for providing convenience
|
||||
methods or adding pure C# classes.
|
||||
|
||||
== Adding Methods to Generated Classes ==
|
||||
|
||||
Let's say the library being bound has a Rectangle class with a constructor
|
||||
that takes an x and y position, and a width and length size. It will look like
|
||||
this:
|
||||
|
||||
public partial class Rectangle
|
||||
{
|
||||
public Rectangle (int x, int y, int width, int height)
|
||||
{
|
||||
// JNI bindings
|
||||
}
|
||||
}
|
||||
|
||||
Imagine we want to add a constructor to this class that takes a Point and
|
||||
Size structure instead of 4 ints. We can add a new file called Rectangle.cs
|
||||
with a partial class containing our new method:
|
||||
|
||||
public partial class Rectangle
|
||||
{
|
||||
public Rectangle (Point location, Size size) :
|
||||
this (location.X, location.Y, size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
At compile time, the additions class will be added to the generated class
|
||||
and the final assembly will a Rectangle class with both constructors.
|
||||
|
||||
|
||||
== Adding C# Classes ==
|
||||
|
||||
Another thing that can be done is adding fully C# managed classes to the
|
||||
generated library. In the above example, let's assume that there isn't a
|
||||
Point class available in Java or our library. The one we create doesn't need
|
||||
to interact with Java, so we'll create it like a normal class in C#.
|
||||
|
||||
By adding a Point.cs file with this class, it will end up in the binding library:
|
||||
|
||||
public class Point
|
||||
{
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
}
|
||||
37
YouTubeApi/Jars/AboutJars.txt
Normal file
37
YouTubeApi/Jars/AboutJars.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
This directory is for Android .jars.
|
||||
|
||||
There are 3 types of jars that are supported:
|
||||
|
||||
== Input Jar and Embedded Jar ==
|
||||
|
||||
This is the jar that bindings should be generated for.
|
||||
|
||||
For example, if you were binding the Google Maps library, this would
|
||||
be Google's "maps.jar".
|
||||
|
||||
The difference between EmbeddedJar and InputJar is, EmbeddedJar is to be
|
||||
embedded in the resulting dll as EmbeddedResource, while InputJar is not.
|
||||
There are couple of reasons you wouldn't like to embed the target jar
|
||||
in your dll (the ones that could be internally loaded by <uses-library>
|
||||
feature e.g. maps.jar, or you cannot embed jars that are under some
|
||||
proprietary license).
|
||||
|
||||
Set the build action for these jars in the properties page to "InputJar".
|
||||
|
||||
|
||||
== Reference Jar and Embedded Reference Jar ==
|
||||
|
||||
These are jars that are referenced by the input jar. C# bindings will
|
||||
not be created for these jars. These jars will be used to resolve
|
||||
types used by the input jar.
|
||||
|
||||
NOTE: Do not add "android.jar" as a reference jar. It will be added automatically
|
||||
based on the Target Framework selected.
|
||||
|
||||
Set the build action for these jars in the properties page to "ReferenceJar".
|
||||
|
||||
"EmbeddedJar" works like "ReferenceJar", but like "EmbeddedJar", it is
|
||||
embedded in your dll. But at application build time, they are not included
|
||||
in the final apk, like ReferenceJar files.
|
||||
|
||||
|
||||
BIN
YouTubeApi/Jars/YouTubeAndroidPlayerApi.jar
Normal file
BIN
YouTubeApi/Jars/YouTubeAndroidPlayerApi.jar
Normal file
Binary file not shown.
23
YouTubeApi/Properties/AssemblyInfo.cs
Normal file
23
YouTubeApi/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Android.App;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
[assembly: AssemblyTitle ("YouTubeApi")]
|
||||
[assembly: AssemblyDescription ("")]
|
||||
[assembly: AssemblyConfiguration ("")]
|
||||
[assembly: AssemblyCompany ("")]
|
||||
[assembly: AssemblyProduct ("")]
|
||||
[assembly: AssemblyCopyright ("Nish")]
|
||||
[assembly: AssemblyTrademark ("")]
|
||||
[assembly: AssemblyCulture ("")]
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
[assembly: AssemblyVersion ("1.0.0")]
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
18
YouTubeApi/Transforms/EnumFields.xml
Normal file
18
YouTubeApi/Transforms/EnumFields.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<enum-field-mappings>
|
||||
<!--
|
||||
This example converts the constants Fragment_id, Fragment_name,
|
||||
and Fragment_tag from android.support.v4.app.FragmentActivity.FragmentTag
|
||||
to an enum called Android.Support.V4.App.FragmentTagType with values
|
||||
Id, Name, and Tag.
|
||||
|
||||
<mapping clr-enum-type="Android.Support.V4.App.FragmentTagType" jni-class="android/support/v4/app/FragmentActivity$FragmentTag">
|
||||
<field clr-name="Id" jni-name="Fragment_id" value="1" />
|
||||
<field clr-name="Name" jni-name="Fragment_name" value="0" />
|
||||
<field clr-name="Tag" jni-name="Fragment_tag" value="2" />
|
||||
</type>
|
||||
|
||||
Notes:
|
||||
- An optional "bitfield" attribute marks the enum type with [Flags].
|
||||
- For Java interfaces, use "jni-interface" attribute instead of "jni-class" attribute.
|
||||
-->
|
||||
</enum-field-mappings>
|
||||
18
YouTubeApi/Transforms/EnumMethods.xml
Normal file
18
YouTubeApi/Transforms/EnumMethods.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<enum-method-mappings>
|
||||
<!--
|
||||
This example changes the Java method:
|
||||
android.support.v4.app.Fragment.SavedState.writeToParcel (int flags)
|
||||
to be:
|
||||
android.support.v4.app.Fragment.SavedState.writeToParcel (Android.OS.ParcelableWriteFlags flags)
|
||||
when bound in C#.
|
||||
|
||||
<mapping jni-class="android/support/v4/app/Fragment.SavedState">
|
||||
<method jni-name="writeToParcel" parameter="flags" clr-enum-type="Android.OS.ParcelableWriteFlags" />
|
||||
</mapping>
|
||||
|
||||
Notes:
|
||||
- For Java interfaces, use "jni-interface" attribute instead of "jni-class" attribute.
|
||||
- To change the type of the return value, use "return" as the parameter name.
|
||||
- The parameter names will be p0, p1, ... unless you provide JavaDoc file in the project.
|
||||
-->
|
||||
</enum-method-mappings>
|
||||
13
YouTubeApi/Transforms/Metadata.xml
Normal file
13
YouTubeApi/Transforms/Metadata.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<metadata>
|
||||
<!--
|
||||
This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
|
||||
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
|
||||
|
||||
This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
|
||||
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
|
||||
-->
|
||||
<attr path="/api/package[@name='com.google.android.youtube.player']" name="managedName">Google.YouTube.Player</attr>
|
||||
|
||||
<remove-node path="/api/package[@name='com.google.android.youtube.player']/class[@name='YouTubePlayerView']/method[@name='onConfigurationChanged' and count(parameter)=1 and parameter[1][@type='android.content.res.Configuration']]" />
|
||||
<remove-node path="/api/package[@name='com.google.android.youtube.player']/class[@name='YouTubeThumbnailView']/method[@name='finalize' and count(parameter)=0]" />
|
||||
</metadata>
|
||||
61
YouTubeApi/YouTubeApi.csproj
Normal file
61
YouTubeApi/YouTubeApi.csproj
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{A4CA43B8-7140-4483-96BA-6AFC8E935470}</ProjectGuid>
|
||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>YouTubeApi</RootNamespace>
|
||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||
<AssemblyName>YouTubeApi</AssemblyName>
|
||||
<TargetFrameworkVersion>v6.0</TargetFrameworkVersion>
|
||||
<ReleaseVersion>1.2.1</ReleaseVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;__MOBILE__;__ANDROID__;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<DefineConstants>__MOBILE__;__ANDROID__;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Mono.Android" />
|
||||
<Reference Include="Mono.Android.Support.v4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Additions\AboutAdditions.txt" />
|
||||
<None Include="Jars\AboutJars.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<TransformFile Include="Transforms\EnumFields.xml" />
|
||||
<TransformFile Include="Transforms\EnumMethods.xml" />
|
||||
<TransformFile Include="Transforms\Metadata.xml" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Novell\Xamarin.Android.Bindings.targets" />
|
||||
<ItemGroup>
|
||||
<EmbeddedJar Include="Jars\YouTubeAndroidPlayerApi.jar" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user