Xamarin Android:当我通过通知打开我的应用程序时,启动画面不起作用
Xamarin Android: When I open my application by notification splash-screen doesn't work
如果我通过单击通知(来自 Google Cloud Messaging)打开应用程序,我不会看到启动画面
GcmListenerService.cs
using Android.App;
using Android.Content;
using Android.OS;
using Android.Gms.Gcm;
using Android.Util;
using System;
using Android.Database.Sqlite;
namespace Dharma.Droid
{
[Service (Exported = false), IntentFilter (new [] { "com.google.android.c2dm.intent.RECEIVE" })]
public class MyGcmListenerService : GcmListenerService
{
public override void OnMessageReceived (string from, Bundle data)
{
var message = data.GetString ("message");
Log.Debug ("MyGcmListenerService", "From: " + from);
Log.Debug ("MyGcmListenerService", "Message: " + message);
DataAccess.InsertDowload (message);
SendNotification (message);
}
void SendNotification (string message)
{
var intent = new Intent (this, typeof(MainActivity));
intent.AddFlags (ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new Notification.Builder (this)
.SetSmallIcon (Resource.Drawable.mhu2)
.SetContentTitle ("Mobile Health Unit")
.SetContentText ("U heeft een nieuwe vragenlijst.")
.SetAutoCancel (true)
.SetContentIntent (pendingIntent);
var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify (0, notificationBuilder.Build());
}
}
}
InstanceIdListenerService.cs
using Android.App;
using Android.Content;
using Android.Gms.Gcm.Iid;
namespace Dharma.Droid
{
[Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]
class MyInstanceIDListenerService : InstanceIDListenerService
{
public override void OnTokenRefresh()
{
var intent = new Intent (this, typeof (RegistrationIntentService));
StartService (intent);
}
}
}
RegistrationIntentService.cs
using System;
using Android.App;
using Android.Content;
using Android.Util;
using Android.Gms.Gcm;
using Android.Gms.Gcm.Iid;
namespace Dharma.Droid
{
[Service(Exported = false)]
class RegistrationIntentService : IntentService
{
static object locker = new object();
public RegistrationIntentService() : base("RegistrationIntentService") { }
protected override void OnHandleIntent (Intent intent)
{
try
{
Log.Info ("RegistrationIntentService", "Calling InstanceID.GetToken");
lock (locker)
{
var instanceID = InstanceID.GetInstance (this);
var token = instanceID.GetToken (
"***************", GoogleCloudMessaging.InstanceIdScope, null);
Log.Info ("RegistrationIntentService", "GCM Registration Token: " + token);
SendRegistrationToAppServer (token);
Subscribe (token);
}
}
catch (Exception e)
{
Log.Debug("RegistrationIntentService", "Failed to get a registration token");
return;
}
}
void SendRegistrationToAppServer (string token)
{
}
void Subscribe (string token)
{
var pubSub = GcmPubSub.GetInstance(this);
pubSub.Subscribe(token, "/topics/global", null);
}
}
}
SplashActivity.cs
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.Views;
using Android.Widget;
using Android.Support.V7.App;
using Android.Util;
using System.Threading.Tasks;
using Android.Gms.Common;
namespace Dharma.Droid
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : AppCompatActivity
{
static readonly string TAG = "X:" + typeof (SplashActivity).Name;
public override void OnCreate(Bundle savedInstanceState, PersistableBundle persistentState)
{
base.OnCreate(savedInstanceState, persistentState);
}
protected override void OnResume()
{
base.OnResume();
Task startupWork = new Task(() =>
{
Task.Delay(5000); // Simulate a bit of startup work.
});
startupWork.ContinueWith(t =>
{
NetworkDiscovery network = new NetworkDiscovery();
CredentialsService cs = new CredentialsService();
if (GetToken() && network.IsOnline())
{
StartActivity(typeof (MainActivity));
}
else
{
StartActivity(typeof (NoInternetActivity));
}
}, TaskScheduler.FromCurrentSynchronizationContext());
startupWork.Start();
}
public bool GetToken()
{
if (IsPlayServicesAvailable ())
{
var intent = new Intent (this, typeof (RegistrationIntentService));
StartService (intent);
return true;
}
else
{
return false;
}
}
public bool IsPlayServicesAvailable ()
{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable (this);
if (resultCode != ConnectionResult.Success)
{
return false;
}
else
{
return true;
}
}
}
}
问题在于这些行:
var intent = new Intent (this, typeof(MainActivity));
intent.AddFlags (ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);
特别是 var intent = new Intent (this, typeof(MainActivity));
您告诉通知在单击时打开 MainActivity
的位置。如果你想显示启动画面,你应该告诉它打开启动画面,而不是通过将该行替换为:
var intent = new Intent (this, typeof(SplashActivity));
唯一的问题是如果应用程序已经打开,您可能不想再次显示启动画面。要解决这个问题,我建议做一些类似 this 的事情,他们在 IsRunning
上有一个 boolean
,它在 MainActivity
生命周期事件中设置。您可以像这样检查 boolean
:
Activity intent;
if(MainActivity.IsRunning) {
intent = new Intent (this, typeof(MainActivity));
intent.AddFlags (ActivityFlags.ClearTop);
} else {
intent = new Intent (this, typeof(SplashActivity));
intent.AddFlags (ActivityFlags.ClearTop);
}
var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);
警告,我没有测试上面的代码。
如果我通过单击通知(来自 Google Cloud Messaging)打开应用程序,我不会看到启动画面
GcmListenerService.cs
using Android.App;
using Android.Content;
using Android.OS;
using Android.Gms.Gcm;
using Android.Util;
using System;
using Android.Database.Sqlite;
namespace Dharma.Droid
{
[Service (Exported = false), IntentFilter (new [] { "com.google.android.c2dm.intent.RECEIVE" })]
public class MyGcmListenerService : GcmListenerService
{
public override void OnMessageReceived (string from, Bundle data)
{
var message = data.GetString ("message");
Log.Debug ("MyGcmListenerService", "From: " + from);
Log.Debug ("MyGcmListenerService", "Message: " + message);
DataAccess.InsertDowload (message);
SendNotification (message);
}
void SendNotification (string message)
{
var intent = new Intent (this, typeof(MainActivity));
intent.AddFlags (ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new Notification.Builder (this)
.SetSmallIcon (Resource.Drawable.mhu2)
.SetContentTitle ("Mobile Health Unit")
.SetContentText ("U heeft een nieuwe vragenlijst.")
.SetAutoCancel (true)
.SetContentIntent (pendingIntent);
var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify (0, notificationBuilder.Build());
}
}
}
InstanceIdListenerService.cs
using Android.App;
using Android.Content;
using Android.Gms.Gcm.Iid;
namespace Dharma.Droid
{
[Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]
class MyInstanceIDListenerService : InstanceIDListenerService
{
public override void OnTokenRefresh()
{
var intent = new Intent (this, typeof (RegistrationIntentService));
StartService (intent);
}
}
}
RegistrationIntentService.cs
using System;
using Android.App;
using Android.Content;
using Android.Util;
using Android.Gms.Gcm;
using Android.Gms.Gcm.Iid;
namespace Dharma.Droid
{
[Service(Exported = false)]
class RegistrationIntentService : IntentService
{
static object locker = new object();
public RegistrationIntentService() : base("RegistrationIntentService") { }
protected override void OnHandleIntent (Intent intent)
{
try
{
Log.Info ("RegistrationIntentService", "Calling InstanceID.GetToken");
lock (locker)
{
var instanceID = InstanceID.GetInstance (this);
var token = instanceID.GetToken (
"***************", GoogleCloudMessaging.InstanceIdScope, null);
Log.Info ("RegistrationIntentService", "GCM Registration Token: " + token);
SendRegistrationToAppServer (token);
Subscribe (token);
}
}
catch (Exception e)
{
Log.Debug("RegistrationIntentService", "Failed to get a registration token");
return;
}
}
void SendRegistrationToAppServer (string token)
{
}
void Subscribe (string token)
{
var pubSub = GcmPubSub.GetInstance(this);
pubSub.Subscribe(token, "/topics/global", null);
}
}
}
SplashActivity.cs
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.Views;
using Android.Widget;
using Android.Support.V7.App;
using Android.Util;
using System.Threading.Tasks;
using Android.Gms.Common;
namespace Dharma.Droid
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : AppCompatActivity
{
static readonly string TAG = "X:" + typeof (SplashActivity).Name;
public override void OnCreate(Bundle savedInstanceState, PersistableBundle persistentState)
{
base.OnCreate(savedInstanceState, persistentState);
}
protected override void OnResume()
{
base.OnResume();
Task startupWork = new Task(() =>
{
Task.Delay(5000); // Simulate a bit of startup work.
});
startupWork.ContinueWith(t =>
{
NetworkDiscovery network = new NetworkDiscovery();
CredentialsService cs = new CredentialsService();
if (GetToken() && network.IsOnline())
{
StartActivity(typeof (MainActivity));
}
else
{
StartActivity(typeof (NoInternetActivity));
}
}, TaskScheduler.FromCurrentSynchronizationContext());
startupWork.Start();
}
public bool GetToken()
{
if (IsPlayServicesAvailable ())
{
var intent = new Intent (this, typeof (RegistrationIntentService));
StartService (intent);
return true;
}
else
{
return false;
}
}
public bool IsPlayServicesAvailable ()
{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable (this);
if (resultCode != ConnectionResult.Success)
{
return false;
}
else
{
return true;
}
}
}
}
问题在于这些行:
var intent = new Intent (this, typeof(MainActivity));
intent.AddFlags (ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);
特别是 var intent = new Intent (this, typeof(MainActivity));
您告诉通知在单击时打开 MainActivity
的位置。如果你想显示启动画面,你应该告诉它打开启动画面,而不是通过将该行替换为:
var intent = new Intent (this, typeof(SplashActivity));
唯一的问题是如果应用程序已经打开,您可能不想再次显示启动画面。要解决这个问题,我建议做一些类似 this 的事情,他们在 IsRunning
上有一个 boolean
,它在 MainActivity
生命周期事件中设置。您可以像这样检查 boolean
:
Activity intent;
if(MainActivity.IsRunning) {
intent = new Intent (this, typeof(MainActivity));
intent.AddFlags (ActivityFlags.ClearTop);
} else {
intent = new Intent (this, typeof(SplashActivity));
intent.AddFlags (ActivityFlags.ClearTop);
}
var pendingIntent = PendingIntent.GetActivity (this, 0, intent, PendingIntentFlags.OneShot);
警告,我没有测试上面的代码。