Created
October 14, 2022 06:00
-
-
Save P3PPP/233cc23b0353af06b41db84555f75a4c to your computer and use it in GitHub Desktop.
Android13の通知権限の挙動を確認した
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using Android; | |
using Android.App; | |
using Android.Content; | |
using Android.Gms.Tasks; | |
using Android.Media; | |
using Android.Nfc; | |
using Android.OS; | |
using Android.Runtime; | |
using Android.Util; | |
using Android.Views; | |
using AndroidX.AppCompat.App; | |
using AndroidX.AppCompat.Widget; | |
using AndroidX.Core.App; | |
using AndroidX.Core.Content; | |
using AndroidX.Core.View; | |
using AndroidX.DrawerLayout.Widget; | |
using Firebase.Installations; | |
using Google.Android.Material.FloatingActionButton; | |
using Google.Android.Material.Navigation; | |
using Google.Android.Material.Snackbar; | |
using static AndroidX.Activity.Result.Contract.ActivityResultContracts; | |
namespace Android13Nortification | |
{ | |
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)] | |
public class MainActivity : AppCompatActivity, NavigationView.IOnNavigationItemSelectedListener | |
{ | |
string _deviceToken; | |
protected override void OnCreate(Bundle savedInstanceState) | |
{ | |
base.OnCreate(savedInstanceState); | |
Xamarin.Essentials.Platform.Init(this, savedInstanceState); | |
SetContentView(Resource.Layout.activity_main); | |
Toolbar toolbar = FindViewById<Toolbar>(Resource.Id.toolbar); | |
SetSupportActionBar(toolbar); | |
FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab); | |
fab.Click += FabOnClick; | |
DrawerLayout drawer = FindViewById<DrawerLayout>(Resource.Id.drawer_layout); | |
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, Resource.String.navigation_drawer_open, Resource.String.navigation_drawer_close); | |
drawer.AddDrawerListener(toggle); | |
toggle.SyncState(); | |
NavigationView navigationView = FindViewById<NavigationView>(Resource.Id.nav_view); | |
navigationView.SetNavigationItemSelectedListener(this); | |
} | |
public override void OnBackPressed() | |
{ | |
DrawerLayout drawer = FindViewById<DrawerLayout>(Resource.Id.drawer_layout); | |
if(drawer.IsDrawerOpen(GravityCompat.Start)) | |
{ | |
drawer.CloseDrawer(GravityCompat.Start); | |
} | |
else | |
{ | |
base.OnBackPressed(); | |
} | |
} | |
public override bool OnCreateOptionsMenu(IMenu menu) | |
{ | |
MenuInflater.Inflate(Resource.Menu.menu_main, menu); | |
return true; | |
} | |
public override bool OnOptionsItemSelected(IMenuItem item) | |
{ | |
int id = item.ItemId; | |
if (id == Resource.Id.action_settings) | |
{ | |
return true; | |
} | |
return base.OnOptionsItemSelected(item); | |
} | |
private async void FabOnClick(object sender, EventArgs eventArgs) | |
{ | |
View view = (View) sender; | |
Snackbar.Make(view, "Replace with your own action", Snackbar.LengthLong) | |
.SetAction("Action", (Android.Views.View.IOnClickListener)null).Show(); | |
//CreateNotificationChannel(); | |
//PostLocalNotification(); | |
AskNotificationPermission(); | |
//var tokenResult = Firebase.Messaging.FirebaseMessaging.Instance.GetToken() | |
// .GetResult(Java.Lang.Class.FromType(typeof(InstallationTokenResult))); | |
//_deviceToken = tokenResult.ToString(); | |
//Console.WriteLine($"device token: {_deviceToken}"); | |
} | |
public bool OnNavigationItemSelected(IMenuItem item) | |
{ | |
int id = item.ItemId; | |
if (id == Resource.Id.nav_camera) | |
{ | |
// Handle the camera action | |
} | |
else if (id == Resource.Id.nav_gallery) | |
{ | |
} | |
else if (id == Resource.Id.nav_slideshow) | |
{ | |
} | |
else if (id == Resource.Id.nav_manage) | |
{ | |
} | |
else if (id == Resource.Id.nav_share) | |
{ | |
} | |
else if (id == Resource.Id.nav_send) | |
{ | |
} | |
DrawerLayout drawer = FindViewById<DrawerLayout>(Resource.Id.drawer_layout); | |
drawer.CloseDrawer(GravityCompat.Start); | |
return true; | |
} | |
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) | |
{ | |
if (requestCode == RequestCode_PostNotifications) | |
{ | |
switch (grantResults[0]) | |
{ | |
case Android.Content.PM.Permission.Denied: | |
// 権限リクエストで通知権限が拒否された。あるいは自動的に拒否された。 | |
// ShouldShowRequestPermissionRationale(Manifest.Permission.PostNotifications)がtrueの | |
// 文脈で出した権限リクエストがユーザーに拒否されると、次回から権限リクエストはUIが表示されず | |
// 自動的に拒否されるようになる。 | |
// その場合、通知権限を許可してもらうには、ユーザーに設定画面で変更するようお願いする必要がある。 | |
if (_isInContextOfShouldShowRequestPermissionRationale) | |
{ | |
_isInContextOfShouldShowRequestPermissionRationale = false; | |
// アプリ制御のために、権限リクエストUIを表示できなくなったことを記録しておくなどする。 | |
} | |
return; | |
case Android.Content.PM.Permission.Granted: | |
// 権限リクエストで通知権限が許可された。 | |
return; | |
} | |
} | |
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); | |
base.OnRequestPermissionsResult(requestCode, permissions, grantResults); | |
} | |
int RequestCode_PostNotifications = new Random().Next(); | |
bool _isInContextOfShouldShowRequestPermissionRationale = false; | |
private void AskNotificationPermission() | |
{ | |
if (Build.VERSION.SdkInt < BuildVersionCodes.Tiramisu) | |
{ | |
// Android 13(API 33)より前は実行時の通知権限がないので確認不可。 | |
return; | |
} | |
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.PostNotifications) | |
== Android.Content.PM.Permission.Granted) | |
{ | |
// 通知が許可されているので権限リクエストの必要なし。 | |
Log.Info(nameof(MainActivity), "Manifest.Permission.PostNotifications is granted."); | |
return; | |
} | |
_isInContextOfShouldShowRequestPermissionRationale = false; | |
if (ShouldShowRequestPermissionRationale(Manifest.Permission.PostNotifications)) | |
{ | |
Log.Info(nameof(MainActivity), "Displaying POST_NOTIFICATION permission rationale to provide additional context."); | |
_isInContextOfShouldShowRequestPermissionRationale = true; | |
// ShouldShowRequestPermissionRationale(Manifest.Permission.PostNotifications)がtrueを返す場合、 | |
// 通知を使用する機能について説明するUIを表示する機会が与えられる。 | |
// ユーザーが望む場合に権限リクエスト | |
// ユーザーが判断を保留して通知機能なしでアプリを続行できるようにする必要がある。 | |
var builder = new AndroidX.AppCompat.App.AlertDialog.Builder(this); | |
builder.SetMessage("このアプリは通知機能を使って重要なお知らせをお知らせする場合があります。") | |
.SetPositiveButton("権限確認に進む", (s, e) => ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.PostNotifications }, RequestCode_PostNotifications)) | |
.SetNegativeButton("今はしない", (s, e) => { }); | |
builder.Show(); | |
} | |
else | |
{ | |
// 直接通知権限をリクエストする。 | |
// ShouldShowRequestPermissionRationale(Manifest.Permission.PostNotifications)がtrueの時に | |
// ユーザーが拒否していた場合は、UIが表示されずに自動的に拒否される。 | |
ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.PostNotifications }, RequestCode_PostNotifications); | |
} | |
} | |
private void CreateNotificationChannel() | |
{ | |
// 通知チャンネルの作成は通知権限が拒否された状態でも可能だった。 | |
var channel = new NotificationChannel( | |
"NotificationChannel_1", | |
"通知チャンネル_1", | |
NotificationImportance.Default | |
); | |
var notificationManager = Application.Context.GetSystemService(Context.NotificationService) | |
as NotificationManager; | |
notificationManager.CreateNotificationChannel(channel); | |
} | |
private void PostLocalNotification() | |
{ | |
// 通知権限が拒否された状態で通知を登録してもエラーにはならない。(単に無視される模様) | |
var builder = new NotificationCompat.Builder(this, "NotificationChannel_1") | |
.SetSmallIcon(Resource.Drawable.side_nav_bar) | |
.SetContentTitle("現在の時刻") | |
.SetContentText($"now is {DateTime.Now}") | |
.SetPriority(NotificationCompat.PriorityDefault); | |
NotificationManagerCompat.From(this).Notify(0, builder.Build()); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment