Skip to content

Commit

Permalink
Android: Fixed grid view layout to fill the album art exactly 2 colum…
Browse files Browse the repository at this point in the history
…ns to fit any device. It works now but as expected it creates a giant memory leak which will be fixed later. The wrong album art is also shown most of the time. Tried to setup an AlarmManager to update the widget more frequently but haven't found the right recipe yet.

Related to issue #406.
  • Loading branch information
ycastonguay committed Jul 22, 2013
1 parent e0a4f51 commit e3a81c7
Show file tree
Hide file tree
Showing 14 changed files with 676 additions and 432 deletions.
Expand Up @@ -25,6 +25,7 @@
using Android.Widget;
using MPfm.Android.Classes.Fragments;
using MPfm.MVP.Models;
using org.sessionsapp.android;

namespace MPfm.Android.Classes.Adapters
{
Expand Down Expand Up @@ -67,25 +68,43 @@ public override int Count
public override View GetView(int position, View convertView, ViewGroup parent)
{
//Console.WriteLine(">>>>>>>>> MobileLibraryBrowserGridAdapter - GetView - position: {0}", position);
var mainActivity = (MainActivity)_context;
var item = _items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = _context.LayoutInflater.Inflate(Resource.Layout.AlbumCell, null);

var artistName = view.FindViewById<TextView>(Resource.Id.albumCell_artistName);
var albumTitle = view.FindViewById<TextView>(Resource.Id.albumCell_albumTitle);
var image = view.FindViewById<ImageView>(Resource.Id.albumCell_image);

artistName.Text = _items[position].Title;
albumTitle.Text = _items[position].Subtitle;
image.SetBackgroundColor(Color.White);

Task.Factory.StartNew(() => {
// WTF Android #549381: GetView position 0 gets called extremely often for no reason. Another job well done, Google. Why can't you optimize your code!?!?
//Console.WriteLine(">>>>>>>>> MobileLibraryBrowserGridAdapter - Loading album art - position: {0} artistName: {1} albumTitle: {2}", position, _items[position].Query.ArtistName, _items[position].Query.AlbumTitle);
// Check if bitmap is in cache before requesting album art (Android likes to request GetView extremely often for no good reason)
//_fragment.OnRequestAlbumArt(_items[position].Query.ArtistName, _items[position].Query.AlbumTitle);
Console.WriteLine(">>>>>>>>> MobileLibraryBrowserGridAdapter - Loading album art - position: {0} artistName: {1} albumTitle: {2}", position, _items[position].Query.ArtistName, _items[position].Query.AlbumTitle);
string key = item.Query.ArtistName + "_" + item.Query.AlbumTitle;
if(mainActivity.BitmapCache.KeyExists(key))
{
int index = _items.FindIndex(x => x.Query.ArtistName == item.Query.ArtistName && x.Query.AlbumTitle == item.Query.AlbumTitle);
if (index >= 0)
{
var viewCell = _gridView.GetChildAt(index);
if (viewCell != null)
{
Task.Factory.StartNew(() =>
{
var imageView = viewCell.FindViewById<ImageView>(Resource.Id.albumCell_image);
imageView.SetImageBitmap(mainActivity.BitmapCache.GetBitmapFromMemoryCache(key));
//mainActivity.BitmapCache.LoadBitmapFromByteArray(albumArtData, artistName + "_" + albumTitle, image);
});
}
}
}
else
{
_fragment.OnRequestAlbumArt(item.Query.ArtistName, item.Query.AlbumTitle);
}
});

return view;
Expand All @@ -96,22 +115,24 @@ public void RefreshAlbumArtCell(string artistName, string albumTitle, byte[] alb
try
{
var mainActivity = (MainActivity)_context;
//Console.WriteLine("MobileLibraryBrowserGridAdapter - Received album art for {0}/{1}", artistName, albumTitle);
Console.WriteLine("MobileLibraryBrowserGridAdapter - Received album art for {0}/{1}", artistName, albumTitle);

int index = _items.FindIndex(x => x.Query.ArtistName == artistName && x.Query.AlbumTitle == albumTitle);
if (index >= 0)
{
var view = _gridView.GetChildAt(index);
if (view != null)
{
var image = view.FindViewById<ImageView>(Resource.Id.albumCell_image);
mainActivity.BitmapCache.LoadBitmapFromByteArray(albumArtData, artistName + "_" + albumTitle, image);
Task.Factory.StartNew(() => {
var image = view.FindViewById<ImageView>(Resource.Id.albumCell_image);
mainActivity.BitmapCache.LoadBitmapFromByteArray(albumArtData, artistName + "_" + albumTitle, image);
});
}
}
}
catch (Exception ex)
{
//Console.WriteLine("MobileLibraryBrowserGridAdapter - Failed to load album art: {0}", ex);
Console.WriteLine("MobileLibraryBrowserGridAdapter - Failed to load album art: {0}", ex);
}
}
}
Expand Down
65 changes: 65 additions & 0 deletions MPfm/MPfm.Android/Classes/Controls/SquareImageView.cs
@@ -0,0 +1,65 @@
// Copyright © 2011-2013 Yanick Castonguay
//
// This file is part of MPfm.
//
// MPfm is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// MPfm is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with MPfm. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;

namespace org.sessionsapp.android
{
public class SquareImageView : ImageView
{
public SquareImageView(Context context) : base(context)
{
Initialize();
}

public SquareImageView(Context context, IAttributeSet attrs) : base (context, attrs)
{
Initialize();
}

public SquareImageView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
{
Initialize();
}

public SquareImageView(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
Initialize();
}

private void Initialize()
{
}

protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
SetMeasuredDimension(MeasuredWidth, MeasuredWidth);
}
}
}
9 changes: 7 additions & 2 deletions MPfm/MPfm.Android/Classes/Helpers/BitmapCache.cs
Expand Up @@ -39,7 +39,7 @@ public BitmapCache(Activity activity, int memorySize, int maxWidth, int maxHeigh
memoryCache = new LruCache(memorySize);
this.activity = activity;
this.MaxWidth = maxWidth;
this.MaxHeight = maxHeight;
this.MaxHeight = maxHeight;
}

private void AddBitmapToMemoryCache(string key, Bitmap bitmap)
Expand All @@ -50,11 +50,16 @@ private void AddBitmapToMemoryCache(string key, Bitmap bitmap)
}
}

private Bitmap GetBitmapFromMemoryCache(string key)
public Bitmap GetBitmapFromMemoryCache(string key)
{
return (Bitmap)memoryCache.Get(key);
}

public bool KeyExists(string key)
{
return memoryCache.Get(key) != null;
}

public void LoadBitmapFromByteArray(byte[] bytes, string key, ImageView imageView)
{
Console.WriteLine("BitmapCache - LoadBitmapFromByteArray - key: {0}", key);
Expand Down
21 changes: 11 additions & 10 deletions MPfm/MPfm.Android/Classes/Services/WidgetService.cs
Expand Up @@ -37,14 +37,14 @@ public class WidgetService : Service

public override void OnStart(Intent intent, int startId)
{
Console.WriteLine("TestService - OnStart - startId: {0}", startId);
Console.WriteLine(">>>>>>>>>>> WidgetService - OnStart - startId: {0}", startId);
Initialize();
base.OnStart(intent, startId);
}

public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Console.WriteLine("TestService - OnStartCommand - startId: {0}", startId);
Console.WriteLine(">>>>>>>>>> WidgetService - OnStartCommand - startId: {0}", startId);
Initialize();
return base.OnStartCommand(intent, flags, startId);
}
Expand All @@ -53,14 +53,14 @@ private void Initialize()
{
_messengerHub = Bootstrapper.GetContainer().Resolve<ITinyMessengerHub>();
_playerService = Bootstrapper.GetContainer().Resolve<IPlayerService>();
_messengerHub.Subscribe<PlayerPlaylistIndexChangedMessage>((message) =>
{
Console.WriteLine("WidgetService - PlayerPlaylistIndexChangedMessage");
});
_messengerHub.Subscribe<PlayerStatusMessage>((message) =>
{
Console.WriteLine("WidgetService - PlayerStatusMessage - Status=" + message.Status.ToString());
});
//_messengerHub.Subscribe<PlayerPlaylistIndexChangedMessage>((message) =>
//{
// Console.WriteLine(">>>>>>>>>> WidgetService - PlayerPlaylistIndexChangedMessage");
//});
//_messengerHub.Subscribe<PlayerStatusMessage>((message) =>
//{
// Console.WriteLine(">>>>>>>>>> WidgetService - PlayerStatusMessage - Status=" + message.Status.ToString());
//});

// Force updating the view for the first time
UpdateView();
Expand All @@ -73,6 +73,7 @@ private void UpdateView()
public override IBinder OnBind(Intent intent)
{
// We don't need to bind to this service
Console.WriteLine(">>>>>>>>>>> WidgetService - OnBind");
return null;
}
}
Expand Down
37 changes: 0 additions & 37 deletions MPfm/MPfm.Android/Classes/Widgets/PlayerWidget.cs

This file was deleted.

76 changes: 76 additions & 0 deletions MPfm/MPfm.Android/Classes/Widgets/PlayerWidgetProvider.cs
@@ -0,0 +1,76 @@
// Copyright © 2011-2013 Yanick Castonguay
//
// This file is part of MPfm.
//
// MPfm is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// MPfm is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with MPfm. If not, see <http://www.gnu.org/licenses/>.

using System;
using Android.App;
using Android.Appwidget;
using Android.Content;
using Android.OS;
using Android.Widget;
using MPfm.Android.Classes.Services;

namespace MPfm.Android.Classes.Widgets
{
[BroadcastReceiver(Label = "Sessions")]
[IntentFilter(new string[] { "android.appwidget.action.APPWIDGET_UPDATE" })]
[MetaData("android.appwidget.provider", Resource = "@xml/widget_player")]
public class PlayerWidgetProvider : AppWidgetProvider
{
public override void OnUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
Console.WriteLine("PlayerWidgetProvider - OnUpdate - appWidgetIds.length: {0}", appWidgetIds.Length);
//context.StartService(new Intent(context, typeof(WidgetService)));
//Intent intent = new Intent(context, typeof(WidgetService));
//PendingIntent pendingIntent = PendingIntent.GetService(context, 0, intent, 0);
//AlarmManager alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService);
//alarmManager.Cancel(pendingIntent);
//alarmManager.SetRepeating(AlarmType.ElapsedRealtime, SystemClock.ElapsedRealtime(), 1000, pendingIntent);

for (int a = 0; a < appWidgetIds.Length; a++)
{
int appWidgetId = appWidgetIds[a];
RemoteViews views = new RemoteViews(context.PackageName, Resource.Layout.WidgetPlayer);
appWidgetManager.UpdateAppWidget(appWidgetId, views);
}
}

public override void OnEnabled(Context context)
{
Console.WriteLine("PlayerWidgetProvider - OnEnabled");
base.OnEnabled(context);
}

public override void OnDisabled(Context context)
{
Console.WriteLine("PlayerWidgetProvider - OnDisabled");
base.OnDisabled(context);
}

public override void OnDeleted(Context context, int[] appWidgetIds)
{
Console.WriteLine("PlayerWidgetProvider - OnDeleted");
base.OnDeleted(context, appWidgetIds);
}

//public override void OnReceive(Context context, Intent intent)
//{
// Console.WriteLine("PlayerWidgetProvider - OnReceive");
// base.OnReceive(context, intent);
// Console.WriteLine("PlayerWidgetProvider - OnReceive - intent.action: {0}", intent.Action);
//}
}
}
3 changes: 2 additions & 1 deletion MPfm/MPfm.Android/MPfm.Android.csproj
Expand Up @@ -82,6 +82,7 @@
<Compile Include="Classes\Adapters\MobileLibraryBrowserListAdapter.cs" />
<Compile Include="Classes\Application.cs" />
<Compile Include="Classes\Clients\MyWebViewClient.cs" />
<Compile Include="Classes\Controls\SquareImageView.cs" />
<Compile Include="Classes\Controls\EqualizerPresetGraphView.cs" />
<Compile Include="Classes\Controls\OutputMeterView.cs" />
<Compile Include="Classes\Controls\WaveFormView.cs" />
Expand All @@ -107,7 +108,7 @@
<Compile Include="Classes\Objects\GenericListItem.cs" />
<Compile Include="Classes\Receivers\ConnectionChangeReceiver.cs" />
<Compile Include="Classes\Services\WidgetService.cs" />
<Compile Include="Classes\Widgets\PlayerWidget.cs" />
<Compile Include="Classes\Widgets\PlayerWidgetProvider.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
Expand Down

0 comments on commit e3a81c7

Please sign in to comment.