mirror of
https://github.com/bitwarden/mobile
synced 2025-12-25 12:43:39 +00:00
push notification services
This commit is contained in:
BIN
src/Android/8bit.keystore.enc
Normal file
BIN
src/Android/8bit.keystore.enc
Normal file
Binary file not shown.
@@ -30,6 +30,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
<AndroidEnableMultiDex>true</AndroidEnableMultiDex>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -59,6 +60,9 @@
|
||||
<PackageReference Include="Xamarin.Essentials">
|
||||
<Version>1.1.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Firebase.Messaging">
|
||||
<Version>60.1142.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Forms" Version="3.6.0.344457" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.1" />
|
||||
<PackageReference Include="Xamarin.Android.Support.v7.AppCompat" Version="28.0.0.1" />
|
||||
@@ -80,6 +84,8 @@
|
||||
<Compile Include="Autofill\FilledItem.cs" />
|
||||
<Compile Include="Autofill\Parser.cs" />
|
||||
<Compile Include="Autofill\SavedItem.cs" />
|
||||
<Compile Include="Push\FirebaseInstanceIdService.cs" />
|
||||
<Compile Include="Push\FirebaseMessagingService.cs" />
|
||||
<Compile Include="Receivers\LockAlarmReceiver.cs" />
|
||||
<Compile Include="Receivers\PackageReplacedReceiver.cs" />
|
||||
<Compile Include="Renderers\ExtendedSliderRenderer.cs" />
|
||||
@@ -89,6 +95,7 @@
|
||||
<Compile Include="Renderers\CustomSearchBarRenderer.cs" />
|
||||
<Compile Include="Renderers\ExtendedListViewRenderer.cs" />
|
||||
<Compile Include="Renderers\HybridWebViewRenderer.cs" />
|
||||
<Compile Include="Services\AndroidPushNotificationService.cs" />
|
||||
<Compile Include="SplashActivity.cs" />
|
||||
<Compile Include="Renderers\BoxedView\BoxedViewRecyclerAdapter.cs" />
|
||||
<Compile Include="Renderers\BoxedView\BoxedViewRenderer.cs" />
|
||||
@@ -111,6 +118,10 @@
|
||||
<AndroidAsset Include="Assets\FontAwesome.ttf" />
|
||||
<AndroidAsset Include="Assets\RobotoMono_Regular.ttf" />
|
||||
<AndroidAsset Include="Assets\MaterialIcons_Regular.ttf" />
|
||||
<None Include="8bit.keystore.enc" />
|
||||
<None Include="ci-build-apks.ps1" />
|
||||
<GoogleServicesJson Include="google-services.json" />
|
||||
<GoogleServicesJson Include="google-services.json.enc" />
|
||||
<None Include="Properties\AndroidManifest.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -76,6 +76,20 @@ namespace Bit.Droid
|
||||
ServiceContainer.Register<IStorageService>("secureStorageService", secureStorageService);
|
||||
ServiceContainer.Register<IDeviceActionService>("deviceActionService", deviceActionService);
|
||||
ServiceContainer.Register<IPlatformUtilsService>("platformUtilsService", platformUtilsService);
|
||||
|
||||
// Push
|
||||
#if FDROID
|
||||
container.RegisterSingleton<IPushNotificationListener, NoopPushNotificationListener>();
|
||||
container.RegisterSingleton<IPushNotificationService, NoopPushNotificationService>();
|
||||
#else
|
||||
var notificationListenerService = new PushNotificationListenerService();
|
||||
ServiceContainer.Register<IPushNotificationListenerService>(
|
||||
"pushNotificationListenerService", notificationListenerService);
|
||||
var androidPushNotificationService = new AndroidPushNotificationService(
|
||||
mobileStorageService, notificationListenerService);
|
||||
ServiceContainer.Register<IPushNotificationService>(
|
||||
"pushNotificationService", androidPushNotificationService);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void Bootstrap()
|
||||
|
||||
25
src/Android/Push/FirebaseInstanceIdService.cs
Normal file
25
src/Android/Push/FirebaseInstanceIdService.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
#if !FDROID
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Firebase.Iid;
|
||||
|
||||
namespace Bit.Droid.Push
|
||||
{
|
||||
[Service]
|
||||
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
|
||||
public class FirebaseInstanceIdService : Firebase.Iid.FirebaseInstanceIdService
|
||||
{
|
||||
public override void OnTokenRefresh()
|
||||
{
|
||||
var storageService = ServiceContainer.Resolve<IStorageService>("storageService");
|
||||
var pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>("pushNotificationService");
|
||||
storageService.SaveAsync(Constants.PushRegisteredTokenKey, FirebaseInstanceId.Instance.Token);
|
||||
pushNotificationService.RegisterAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
42
src/Android/Push/FirebaseMessagingService.cs
Normal file
42
src/Android/Push/FirebaseMessagingService.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
#if !FDROID
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Firebase.Messaging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.Droid.Push
|
||||
{
|
||||
[Service]
|
||||
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
|
||||
public class FirebaseMessagingService : Firebase.Messaging.FirebaseMessagingService
|
||||
{
|
||||
public override void OnMessageReceived(RemoteMessage message)
|
||||
{
|
||||
if(message?.Data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var data = message.Data.ContainsKey("data") ? message.Data["data"] : null;
|
||||
if(data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var obj = JObject.Parse(data);
|
||||
var listener = ServiceContainer.Resolve<IPushNotificationListenerService>(
|
||||
"pushNotificationListenerService");
|
||||
listener.OnMessageAsync(obj, Device.Android);
|
||||
}
|
||||
catch(JsonReaderException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
2538
src/Android/Resources/Resource.designer.cs
generated
2538
src/Android/Resources/Resource.designer.cs
generated
File diff suppressed because it is too large
Load Diff
50
src/Android/Services/AndroidPushNotificationService.cs
Normal file
50
src/Android/Services/AndroidPushNotificationService.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
#if !FDROID
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.Droid.Services
|
||||
{
|
||||
public class AndroidPushNotificationService : IPushNotificationService
|
||||
{
|
||||
private readonly IStorageService _storageService;
|
||||
private readonly IPushNotificationListenerService _pushNotificationListenerService;
|
||||
|
||||
public AndroidPushNotificationService(
|
||||
IStorageService storageService,
|
||||
IPushNotificationListenerService pushNotificationListenerService)
|
||||
{
|
||||
_storageService = storageService;
|
||||
_pushNotificationListenerService = pushNotificationListenerService;
|
||||
}
|
||||
|
||||
public async Task<string> GetTokenAsync()
|
||||
{
|
||||
return await _storageService.GetAsync<string>(Constants.PushCurrentTokenKey);
|
||||
}
|
||||
|
||||
public async Task RegisterAsync()
|
||||
{
|
||||
var registeredToken = await _storageService.GetAsync<string>(Constants.PushRegisteredTokenKey);
|
||||
var currentToken = await GetTokenAsync();
|
||||
if(!string.IsNullOrWhiteSpace(registeredToken) && registeredToken != currentToken)
|
||||
{
|
||||
await _pushNotificationListenerService.OnRegisteredAsync(registeredToken, Device.Android);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _storageService.SaveAsync(Constants.PushLastRegistrationDateKey, DateTime.UtcNow);
|
||||
}
|
||||
}
|
||||
|
||||
public Task UnregisterAsync()
|
||||
{
|
||||
// Do we ever need to unregister?
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
87
src/Android/ci-build-apks.ps1
Normal file
87
src/Android/ci-build-apks.ps1
Normal file
@@ -0,0 +1,87 @@
|
||||
$rootPath = $env:APPVEYOR_BUILD_FOLDER;
|
||||
|
||||
$androidPath = $($rootPath + "\src\Android\Android.csproj");
|
||||
$appPath = $($rootPath + "\src\App\App.csproj");
|
||||
|
||||
echo "##### Increment Version"
|
||||
|
||||
$androidManifest = $($rootPath + "\src\Android\Properties\AndroidManifest.xml");
|
||||
|
||||
$xml=New-Object XML;
|
||||
$xml.Load($androidManifest);
|
||||
|
||||
$node=$xml.SelectNodes("/manifest");
|
||||
$node.SetAttribute("android:versionCode", $env:APPVEYOR_BUILD_NUMBER);
|
||||
|
||||
$xml.Save($androidManifest);
|
||||
|
||||
echo "##### Decrypt Keystore"
|
||||
|
||||
$encKeystorePath = $($rootPath + "\src\Android\8bit.keystore.enc");
|
||||
$secureFilePath = $($rootPath + "\secure-file\tools\secure-file.exe");
|
||||
|
||||
Invoke-Expression "& `"$secureFilePath`" -decrypt $($encKeystorePath) -secret $($env:keystore_dec_secret)"
|
||||
|
||||
echo "##### Sign Release Configuration"
|
||||
|
||||
msbuild "$($androidPath)" "/t:SignAndroidPackage" "/p:Configuration=Release" "/p:AndroidKeyStore=true" "/p:AndroidSigningKeyAlias=bitwarden" "/p:AndroidSigningKeyPass=$($env:keystore_password)" "/p:AndroidSigningKeyStore=8bit.keystore" "/p:AndroidSigningStorePass=$($env:keystore_password)" "/v:quiet"
|
||||
|
||||
echo "##### Copy Release apk to project root"
|
||||
|
||||
$signedApkPath = $($rootPath + "\src\Android\bin\Release\com.x8bit.bitwarden-Signed.apk");
|
||||
$signedApkDestPath = $($rootPath + "\com.x8bit.bitwarden-" + $env:APPVEYOR_BUILD_NUMBER + ".apk");
|
||||
|
||||
Copy-Item $signedApkPath $signedApkDestPath
|
||||
|
||||
echo "##### Clean Android and App"
|
||||
|
||||
msbuild "$($androidPath)" "/t:Clean" "/p:Configuration=FDroid"
|
||||
msbuild "$($appPath)" "/t:Clean" "/p:Configuration=FDroid"
|
||||
|
||||
echo "##### Backup project files"
|
||||
|
||||
Copy-Item $androidPath $($androidPath + ".original");
|
||||
Copy-Item $appPath $($appPath + ".original");
|
||||
|
||||
echo "##### Uninstall from Android.csproj"
|
||||
|
||||
$xml=New-Object XML;
|
||||
$xml.Load($androidPath);
|
||||
|
||||
$ns=New-Object System.Xml.XmlNamespaceManager($xml.NameTable);
|
||||
$ns.AddNamespace("ns", $xml.DocumentElement.NamespaceURI);
|
||||
|
||||
$firebaseNode=$xml.SelectSingleNode("/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.Firebase.Messaging']", $ns);
|
||||
$firebaseNode.ParentNode.RemoveChild($firebaseNode);
|
||||
|
||||
$xml.Save($androidPath);
|
||||
|
||||
echo "##### Uninstall from App.csproj"
|
||||
|
||||
$xml=New-Object XML;
|
||||
$xml.Load($appPath);
|
||||
|
||||
$hockeyNode=$xml.SelectSingleNode("/Project/ItemGroup/PackageReference[@Include='HockeySDK.Xamarin']");
|
||||
$hockeyNode.ParentNode.RemoveChild($hockeyNode);
|
||||
|
||||
$xml.Save($appPath);
|
||||
|
||||
echo "##### Restore NuGet"
|
||||
|
||||
$nugetPath = $($rootPath + "\nuget.exe");
|
||||
|
||||
Invoke-Expression "& `"$nugetPath`" restore"
|
||||
|
||||
echo "##### Build and Sign FDroid Configuration"
|
||||
|
||||
msbuild "$($androidPath)" "/logger:C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" "/p:Configuration=FDroid"
|
||||
msbuild "$($androidPath)" "/t:SignAndroidPackage" "/p:Configuration=FDroid" "/p:AndroidKeyStore=true" "/p:AndroidSigningKeyAlias=bitwarden" "/p:AndroidSigningKeyPass=$($env:keystore_password)" "/p:AndroidSigningKeyStore=8bit.keystore" "/p:AndroidSigningStorePass=$($env:keystore_password)" "/v:quiet"
|
||||
|
||||
echo "##### Copy FDroid apk to project root"
|
||||
|
||||
$signedApkPath = $($rootPath + "\src\Android\bin\FDroid\com.x8bit.bitwarden-Signed.apk");
|
||||
$signedApkDestPath = $($rootPath + "\com.x8bit.bitwarden-fdroid-" + $env:APPVEYOR_BUILD_NUMBER + ".apk");
|
||||
|
||||
Copy-Item $signedApkPath $signedApkDestPath
|
||||
|
||||
echo "##### Done"
|
||||
42
src/Android/google-services.json
Normal file
42
src/Android/google-services.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "1093287226212",
|
||||
"firebase_url": "https://bitwarden-dev.firebaseio.com",
|
||||
"project_id": "bitwarden-dev",
|
||||
"storage_bucket": "bitwarden-dev.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:1093287226212:android:f8d67b786db1b844",
|
||||
"android_client_info": {
|
||||
"package_name": "com.x8bit.bitwarden"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "1093287226212-m4mv8ho387tdgosc9lsltnmruul7ouo0.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyA4Xkn0do7Ky_OLff2L_7MXeNK6s-JVgXg"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"analytics_service": {
|
||||
"status": 1
|
||||
},
|
||||
"appinvite_service": {
|
||||
"status": 1,
|
||||
"other_platform_oauth_client": []
|
||||
},
|
||||
"ads_service": {
|
||||
"status": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
BIN
src/Android/google-services.json.enc
Normal file
BIN
src/Android/google-services.json.enc
Normal file
Binary file not shown.
Reference in New Issue
Block a user