Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BadgeCounter #807 #1126

Merged
merged 44 commits into from
Jul 23, 2023
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
c7fae39
BadgeCounter #807
VladislavAntonyuk Apr 3, 2023
3471fe3
Merge branch 'main' into badge-counter
brminnick Apr 14, 2023
581bd0a
Merge branch 'main' into badge-counter
VladislavAntonyuk May 29, 2023
1ba0087
Rename to Badge
VladislavAntonyuk May 29, 2023
24fd11f
Update tests
VladislavAntonyuk May 29, 2023
a942925
Remove Xamarin.Android.ShortcutBadger dependency
VladislavAntonyuk May 30, 2023
e511bfd
Fix Tizen build
VladislavAntonyuk May 30, 2023
b1de892
Merge branch 'main' into badge-counter
brminnick Jun 1, 2023
cd1a48e
Merge branch 'main' into badge-counter
VladislavAntonyuk Jun 4, 2023
20ffb79
Merge branch 'main' into badge-counter
VladislavAntonyuk Jun 16, 2023
56d1aa9
Add default badge provider, add nova
VladislavAntonyuk Jun 16, 2023
55e549d
Fix SamsungBadgeProvider
VladislavAntonyuk Jun 16, 2023
cd36f81
SetProvider
VladislavAntonyuk Jun 19, 2023
5117d72
Initialize array only once
VladislavAntonyuk Jun 19, 2023
0633161
Merge branch 'main' into badge-counter
VladislavAntonyuk Jul 3, 2023
95a73bc
Merge branch 'main' into badge-counter
brminnick Jul 6, 2023
8a0f544
`dotnet format`
brminnick Jul 6, 2023
197f0ea
Update SamsungBadgeProvider.cs
brminnick Jul 6, 2023
d697dac
Update BadgeViewModel.cs
brminnick Jul 6, 2023
d0333d7
Update DefaultBadgeProvider.android.cs
brminnick Jul 6, 2023
3443d8f
Use `Lazy<T>` to ensure thread safety
brminnick Jul 6, 2023
c58d2fb
Merge branch 'main' into badge-counter
VladislavAntonyuk Jul 7, 2023
d7f8429
GetCount
VladislavAntonyuk Jul 7, 2023
e0ac0ba
feat: Add support for Samsung badge provider
VladislavAntonyuk Jul 7, 2023
9343f67
Fix SamsungBadgeProvider.cs and BadgeTests.cs
VladislavAntonyuk Jul 7, 2023
2d91307
Merge branch 'badge-counter' of https://github.com/CommunityToolkit/M…
brminnick Jul 10, 2023
4de4dbd
Fix build error
brminnick Jul 10, 2023
2224027
Merge branch 'main' into badge-counter
VladislavAntonyuk Jul 11, 2023
04fcf44
Update CommunityToolkit.Maui.Sample.csproj
brminnick Jul 13, 2023
1a454ff
Update DefaultBadgeProvider.android.cs
brminnick Jul 13, 2023
3b0c851
Update BadgeImplementation.macios.cs
brminnick Jul 13, 2023
426c5f3
Update EssentialsGalleryViewModel.cs
brminnick Jul 13, 2023
35ddaa4
Update BaseGalleryViewModel.cs
brminnick Jul 13, 2023
ad18954
Update MainApplication.cs
brminnick Jul 13, 2023
c17a568
Add null check
brminnick Jul 13, 2023
a758c34
Remove `count` field
brminnick Jul 13, 2023
dd41f01
Update DefaultBadgeProvider.android.cs
brminnick Jul 13, 2023
43acf03
Add additional text explaining Bade
brminnick Jul 13, 2023
82b07d7
Remove GetCount, use uint instead of int
VladislavAntonyuk Jul 14, 2023
5a46c0d
fix tizen build
VladislavAntonyuk Jul 14, 2023
0e311d6
Update src/CommunityToolkit.Maui.Core/Essentials/Badge/BadgeImplement…
VladislavAntonyuk Jul 14, 2023
1a1743f
Update src/CommunityToolkit.Maui.Core/Essentials/Badge/BadgeImplement…
VladislavAntonyuk Jul 14, 2023
4c0baea
Update src/CommunityToolkit.Maui.Core/Essentials/Badge/Android/BadgeF…
VladislavAntonyuk Jul 14, 2023
01b0bd0
Update src/CommunityToolkit.Maui.Core/Essentials/Badge/Android/Defaul…
VladislavAntonyuk Jul 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,4 @@ paket-files/

# Visual Studio Code
.vscode
/samples/workload-install.ps1
VladislavAntonyuk marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions samples/CommunityToolkit.Maui.Sample/AppShell.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public partial class AppShell : Shell
CreateViewModelMapping<VariableMultiValueConverterPage, VariableMultiValueConverterViewModel, ConvertersGalleryPage, ConvertersGalleryViewModel>(),

// Add Essentials View Models
CreateViewModelMapping<BadgePage, BadgeViewModel, EssentialsGalleryPage, EssentialsGalleryViewModel>(),
CreateViewModelMapping<FileSaverPage, FileSaverViewModel, EssentialsGalleryPage, EssentialsGalleryViewModel>(),
CreateViewModelMapping<FolderPickerPage, FolderPickerViewModel, EssentialsGalleryPage, EssentialsGalleryViewModel>(),
CreateViewModelMapping<SpeechToTextPage, SpeechToTextViewModel, EssentialsGalleryPage, EssentialsGalleryViewModel>(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@
<ApplicationVersion>1</ApplicationVersion>

<!--
Uncomment these lines if you need to debug the SG code
Uncomment the line below if you need to debug the SG code
If you see any LongPath issue on Windows, check this doc
https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later
-->
<!--<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>-->

<!-- Uncomment the line below if Android App installation fails -->
<!--<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>-->
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -79,4 +82,5 @@
<PropertyGroup Condition="$([MSBuild]::IsOSPlatform('windows'))=='false' and $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))=='maccatalyst' and $(Configuration) == 'Debug'">
<RuntimeIdentifiers>maccatalyst-arm64;maccatalyst-x64</RuntimeIdentifiers>
</PropertyGroup>

</Project>
3 changes: 3 additions & 0 deletions samples/CommunityToolkit.Maui.Sample/MauiProgram.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using CommunityToolkit.Maui.ApplicationModel;
using CommunityToolkit.Maui.Maps;
using CommunityToolkit.Maui.Markup;
using CommunityToolkit.Maui.Media;
Expand Down Expand Up @@ -156,6 +157,7 @@ static void RegisterViewsAndViewModels(in IServiceCollection services)
services.AddTransientWithShellRoute<VariableMultiValueConverterPage, VariableMultiValueConverterViewModel>();

// Add Essentials Pages + ViewModels
services.AddTransientWithShellRoute<BadgePage, BadgeViewModel>();
services.AddTransientWithShellRoute<FileSaverPage, FileSaverViewModel>();
services.AddTransientWithShellRoute<FolderPickerPage, FolderPickerViewModel>();
services.AddTransientWithShellRoute<SpeechToTextPage, SpeechToTextViewModel>();
Expand Down Expand Up @@ -199,6 +201,7 @@ static void RegisterEssentials(in IServiceCollection services)
services.AddSingleton<IDeviceInfo>(DeviceInfo.Current);
services.AddSingleton<IFileSaver>(FileSaver.Default);
services.AddSingleton<IFolderPicker>(FolderPicker.Default);
services.AddSingleton<IBadge>(Badge.Default);
services.AddSingleton<ISpeechToText>(SpeechToText.Default);
services.AddSingleton<ITextToSpeech>(TextToSpeech.Default);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8" ?>
<pages:BasePage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:CommunityToolkit.Maui.Sample.Pages"
x:Class="CommunityToolkit.Maui.Sample.Pages.Essentials.BadgePage"
xmlns:vm="clr-namespace:CommunityToolkit.Maui.Sample.ViewModels.Essentials"
x:TypeArguments="vm:BadgeViewModel"
x:DataType="vm:BadgeViewModel"
Title="Badge">

<Grid
RowDefinitions="*, *"
ColumnDefinitions="*, *"
ColumnSpacing="12"
RowSpacing="12"
VerticalOptions="Center">
VladislavAntonyuk marked this conversation as resolved.
Show resolved Hide resolved

<Label
Grid.ColumnSpan="2"
Text="Toggle Home Screen Icon Badge Count"
FontSize="18"
VerticalOptions="End"
HorizontalOptions="Center" />

<Button
Text="+"
Grid.Column="0"
Grid.Row="1"
SemanticProperties.Hint="Increments AppIcon badge"
Command="{Binding IncrementCommand}"
VerticalOptions="Start"
HorizontalOptions="End" />

<Button
Text="-"
Grid.Column="1"
Grid.Row="1"
SemanticProperties.Hint="Decrements AppIcon badge"
Command="{Binding DecrementCommand}"
VerticalOptions="Start"
HorizontalOptions="Start" />

</Grid>

</pages:BasePage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using CommunityToolkit.Maui.Sample.ViewModels.Essentials;

namespace CommunityToolkit.Maui.Sample.Pages.Essentials;

public partial class BadgePage : BasePage<BadgeViewModel>
{
public BadgePage(BadgeViewModel viewModel) : base(viewModel)
{
InitializeComponent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!-- Samsung -->
<uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />
VladislavAntonyuk marked this conversation as resolved.
Show resolved Hide resolved

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<queries>
<intent>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Android.App;
using Android.OS;
using Android.Runtime;
using CommunityToolkit.Maui.ApplicationModel;

namespace CommunityToolkit.Maui.Sample;

Expand All @@ -9,6 +11,9 @@ public class MainApplication : MauiApplication
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
: base(handle, ownership)
{
var samsungProvider = new SamsungBadgeProvider();
BadgeFactory.SetBadgeProvider("com.sec.android.app.launcher", samsungProvider);
BadgeFactory.SetBadgeProvider("com.sec.android.app.twlauncher", samsungProvider);
}

protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using Android.Content;
using Android.Database;
using CommunityToolkit.Maui.ApplicationModel;
using Application = Android.App.Application;

namespace CommunityToolkit.Maui.Sample;

class SamsungBadgeProvider : IBadgeProvider
{
const string contentStringUri = "content://com.sec.badge/apps?notify=true";
static readonly string[] contentProjection = { "_id", "class" };
static readonly string[] packageNameArray = new string[1];

public void SetCount(int count)
{
var contentUri = Android.Net.Uri.Parse(contentStringUri);
if (contentUri is null)
{
return;
}

var packageName = Application.Context.PackageName;
if (packageName is null)
{
return;
}

var componentName = Application.Context.PackageManager?.GetLaunchIntentForPackage(packageName)?.Component;
if (componentName is null)
{
return;
}

var contentResolver = Application.Context.ContentResolver;
ICursor? cursor = null;
try
{
packageNameArray[0] = packageName;
cursor = contentResolver?.Query(contentUri, contentProjection, "package=?", packageNameArray, null);
if (cursor is not null)
{
var entryActivityExist = false;
var selectionArgs = new string[1];
while (cursor.MoveToNext())
{
var id = cursor.GetInt(0);
selectionArgs[0] = id.ToString();
var contentValues = GetContentValues(componentName, count, false);
contentResolver?.Update(contentUri, contentValues, "_id=?", selectionArgs);
if (componentName.ClassName.Equals(cursor.GetString(cursor.GetColumnIndex("class"))))
{
entryActivityExist = true;
}
}

if (!entryActivityExist)
{
var contentValues = GetContentValues(componentName, count, true);
contentResolver?.Insert(contentUri, contentValues);
}
}
}
finally
{
if (cursor?.IsClosed is false)
{
cursor.Close();
}
}
}

static ContentValues GetContentValues(ComponentName componentName, int badgeCount, bool isInsert)
{
var contentValues = new ContentValues();
if (isInsert)
{
contentValues.Put("package", componentName.PackageName);
contentValues.Put("class", componentName.ClassName);
}

contentValues.Put("badgecount", badgeCount);
return contentValues;
}

public int GetCount()
{
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using CommunityToolkit.Maui.ApplicationModel;
using CommunityToolkit.Mvvm.Input;

namespace CommunityToolkit.Maui.Sample.ViewModels.Essentials;

public partial class BadgeViewModel : BaseViewModel
{
readonly IBadge badge;

int count;

public BadgeViewModel(IBadge badge)
{
this.badge = badge;
count = badge.GetCount();
}

[RelayCommand]
void Increment()
{
count++;
badge.SetCount(count);
}

[RelayCommand]
void Decrement()
{
if (count > 0)
{
count--;
badge.SetCount(count);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public class EssentialsGalleryViewModel : BaseGalleryViewModel
public EssentialsGalleryViewModel()
: base(new[]
{
SectionModel.Create<BadgeViewModel>("Badge", "Allows the user to set app icon badge count on the home screen"),
SectionModel.Create<FileSaverViewModel>("FileSaver", "Allows the user to save files to the filesystem"),
SectionModel.Create<FolderPickerViewModel>("FolderPicker", "Allows picking folders from the file system"),
SectionModel.Create<SpeechToTextViewModel>("SpeechToText", "Converts speech to text"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@

<PackageReference Include="System.Speech" Version="7.0.0" Condition="'$(TargetFramework)' == 'net7.0-windows10.0.19041.0'" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Android.Content;
using Android.Content.PM;

namespace CommunityToolkit.Maui.ApplicationModel;

/// <summary>
/// Factory for <see cref="IBadge"/>
/// </summary>
public static class BadgeFactory
{
static readonly Dictionary<string, IBadgeProvider> providers = new();
static readonly DefaultBadgeProvider defaultBadgeProvider = new();

/// <summary>
/// Register provider for launcher type
/// </summary>
/// <param name="launcherType">Launcher type</param>
/// <param name="provider">Provider implementation</param>
public static void SetBadgeProvider(string launcherType, IBadgeProvider provider)
{
providers[launcherType] = provider;
}

/// <summary>
/// Get badge provider for current launcher
/// </summary>
/// <returns>Provider implementation</returns>
public static IBadgeProvider GetBadgeProvider()
{
var launcherType = GetLauncherType();
if (launcherType is null)
{
return defaultBadgeProvider;
}

providers.TryGetValue(launcherType, out var provider);
return provider ?? defaultBadgeProvider;
}

static string? GetLauncherType()
{
var intent = new Intent(Intent.ActionMain);
VladislavAntonyuk marked this conversation as resolved.
Show resolved Hide resolved
intent.AddCategory(Intent.CategoryHome);
using var resolveInfo = OperatingSystem.IsAndroidVersionAtLeast(33) ?
Application.Context.PackageManager?.ResolveActivity(intent, PackageManager.ResolveInfoFlags.Of(0)) :
Application.Context.PackageManager?.ResolveActivity(intent, PackageInfoFlags.MatchDefaultOnly);

if (resolveInfo is { ActivityInfo.PackageName: not null })
{
return resolveInfo.ActivityInfo.PackageName;
}

return Application.Context.PackageName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace CommunityToolkit.Maui.ApplicationModel;

/// <inheritdoc />
public class BadgeImplementation : IBadge
{
/// <inheritdoc />
public void SetCount(int count)
{
var badgeProvider = BadgeFactory.GetBadgeProvider();
badgeProvider.SetCount(count);
}

/// <inheritdoc />
public int GetCount()
{
var badgeProvider = BadgeFactory.GetBadgeProvider();
return badgeProvider.GetCount();
}
}