我正在开发一款使用Air Native Extensions(ANE)的Android Air应用程序。从ANE我调用一个创建Pending Intent的函数,该函数传递给Notification。接下来,本机函数启动服务并将其传递给Pending Intent和Notification。这是该部分的代码:
public class StartServiceFunction implements FREFunction {
@Override
public FREObject call(FREContext context, FREObject[] args) {
Log.d("MyApplicationStartServiceFunction", "call(StartService)");
Context applicationContext = context.getActivity().getApplicationContext();
try {
String appPackageName = args[0].getAsString();
String applicationID = args[1].getAsString();
String notificationMessage = args[2].getAsString();
String statusServiceURL = args[3].getAsString();
String triggerResponse = args[4].getAsString();
Intent appLaunchIntent = applicationContext.getPackageManager().getLaunchIntentForPackage(appPackageName);
PendingIntent pendingLaunchIntent = PendingIntent.getActivity(applicationContext, 0, appLaunchIntent, 0);
int icon = context.getResourceId("drawable.notification_icon");
Notification serviceNotification = new Notification.Builder(applicationContext)
.setContentTitle(applicationID)
.setContentText(notificationMessage)
.setSmallIcon(icon)
.setContentIntent(pendingLaunchIntent)
.build();
Log.d("MyApplicationStartServiceFunction", "call(StartService): notification Created");
Intent serviceIntent = new Intent(applicationContext, MyApplicationService.class);
serviceIntent.putExtra("serviceNotification", serviceNotification);
serviceIntent.putExtra("statusServiceURL", statusServiceURL);
serviceIntent.putExtra("triggerResponse", triggerResponse);
serviceIntent.putExtra("pendingLaunchIntent", pendingLaunchIntent);
applicationContext.startService(serviceIntent);
Log.d("MyApplicationStartServiceFunction", "call(StartService): startService issued");
return FREObject.newObject(true);
} catch (Exception e) {
Log.d("MyApplicationStartServiceFunction", "Exception: " + e.getMessage());
e.printStackTrace();
}
try {
return FREObject.newObject(false);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
这部分代码就像魅力一样。
接下来,当在服务中调用onStartCommand()
方法时,我将Pending Intent
和Notification
中的Intent
作为参数传递给上述方法。获得通知的目的是将服务设置为它所执行的前台进程(startForeground()
),并且还允许用户在他点击通知时重新输入应用程序。传递挂起意图的关键是,当满足某些条件时,服务可以激活它(Pending Intent
)并使应用程序成为主要的可见进程。这是我用于此的代码(请记住,它的一部分被省略,因为它不是问题而且工作正常):
public class MyApplicationService extends Service implements TriggeredResponseListener {
private Timer timer;
private PendingIntent pendingLaunchIntent;
private String statusServiceURL;
private String triggerResponse;
@Override
public IBinder onBind(Intent arg0) {
Log.d("MyApplicationService", "onBind()");
return null;
}
@Override
public void onCreate() {
Log.d("MyApplicationService", "onCreate()");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyApplicationService", "onStartCommand(): " + intent.toString());
Notification serviceNotification = intent.getParcelableExtra("serviceNotification");
startForeground(1,serviceNotification);
Log.d("MyApplicationService", "onStartCommand(): startForegroundService");
pendingLaunchIntent = intent.getParcelableExtra("pendingLaunchIntent");
statusServiceURL = intent.getStringExtra("statusServiceURL");
triggerResponse = intent.getStringExtra("triggerResponse");
Log.d("MyApplicationService", "onStartCommand(): getParcelableExtras");
if(timer == null)
{
timer = new Timer("Printer");
HttpServiceTask serviceTask = new HttpServiceTask(statusServiceURL, triggerResponse);
serviceTask.addEventListener(this);
timer.schedule(serviceTask, 0, 2000);
Log.d("MyApplicationService", "onStartCommand(): startTimer");
}
return START_REDELIVER_INTENT;
}
public void handleTriggeredResponseEvent(TriggeredResponseEvent eventObject) {
Log.d("MyApplicationService", "handleEvent()");
destroyTimer();
HttpServiceTask serviceTask = eventObject.httpServiceTask;
serviceTask.removeEventListener(this);
Log.d("MyApplicationService", "handleEvent(): launching pendingLaunchIntent");
try{
pendingLaunchIntent.send();
} catch (Exception e) {
Log.d("MyApplicationService", "handleEvent(): " + e.getMessage());
e.printStackTrace();
}
this.stopSelf();
Log.d("MyApplicationService", "handleEvent(): stopSelf");
}
private void destroyTimer() {
if (timer != null){
timer.cancel();
timer = null;
}
}
@Override
public void onDestroy() {
Log.d("MyApplicationService", "onDestroy():");
destroyTimer();
Log.d("MyApplicationService", "onDestroy(): destroyTimer():");
super.onDestroy();
}
}
该代码ALMOST工作正常。它适用于大多数情况,但不适用于每一种情况。
涉及与Pending Intent
相关的操作的方法是handleTriggeredResponseEvent()
,所以让我们关注那个问题。如您所见,当调用此处理程序时,将发送Pending Intent
。请记住,它应与Notification
完全相同,因为它是由同一Pending Intent
制作的。
如果尚未从最近的应用程序列表中关闭Air mobile应用程序(按住Home
按钮),Pending Intent
将成功激活handleTriggeredResponseEvent()
和Air应用程序将再次成为用户可见的主要应用程序。
从最近的应用程序列表中关闭Air mobile应用程序时出现问题。当满足条件并且调用方法handleTriggeredResponseEvent()
时,一切都正确运行,即使pendingLaunchIntent.send()
运行也没有抛出任何异常。唯一的区别是应用程序未启动。我只能看到一个黑屏(Air运行时启动?),但不能运行Air mobile应用程序。
另一方面,当我从“最近的应用程序列表”关闭Air应用程序并激活通知栏上的服务通知时,即使它使用与{{Pending Intent
相同的handleTriggeredResponseEvent()
,也会正确启动应用程序。 1}}方法。
我检查了所有Log语句,代码运行时没有任何错误,并且在所有方案中都以相同的方式运行。
这怎么可能?从Pending Intent
方法发送的handleTriggeredResponseEvent()
不应该与激活服务通知时发送的效果相同吗?
显然我错过了一些东西。它可能是Application Manifest XML中的内容吗?接下来是清单中服务的声明:
<application android:debuggable="true">
<service android:enabled="true" android:exported="true" android:name="com.mycompany.myextension.services.MyService">
<intent-filter>
<action android:name="air.com.mycompany.myextension.DO_CUSTOM_ACTION"/>
</intent-filter>
</service>
</application>
任何帮助都将深表感谢。提前谢谢。
我可以捕获LogCat错误,它们在这里:
01-22 15:21:27.625: I/ActivityManager(381): Killing 25792:air.QOE/u0a122: remove task
01-22 15:21:27.664: W/ActivityManager(381): Exception when starting activity air.QOE/.AppEntry
01-22 15:21:27.664: W/ActivityManager(381): android.os.DeadObjectException
01-22 15:21:27.664: W/ActivityManager(381): at android.os.BinderProxy.transact(Native Method)
01-22 15:21:27.664: W/ActivityManager(381): at android.app.ApplicationThreadProxy.scheduleLaunchActivity(ApplicationThreadNative.java:743)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityStack.realStartActivityLocked(ActivityStack.java:821)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityStack.startSpecificActivityLocked(ActivityStack.java:949)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityStack.resumeTopActivityLocked(ActivityStack.java:2321)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityStack.resumeTopActivityLocked(ActivityStack.java:1862)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityStack.resumeTopActivityLocked(ActivityStack.java:1837)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:1411)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:1356)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityStack.activityPaused(ActivityStack.java:1266)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityManagerService.activityPaused(ActivityManagerService.java:4609)
01-22 15:21:27.664: W/ActivityManager(381): at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:401)
01-22 15:21:27.664: W/ActivityManager(381): at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:1729)
01-22 15:21:27.664: W/ActivityManager(381): at android.os.Binder.execTransact(Binder.java:367)
01-22 15:21:27.664: W/ActivityManager(381): at dalvik.system.NativeStart.run(Native Method)
01-22 15:21:27.726: I/ActivityManager(381): Process air.QOE (pid 25792) has died and restarted (pid 25900).
在乞讨时,似乎DeadObjectException告诉我没有任何活动来处理意图,但后来我添加了以下代码:
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
Log.d("EasyControlService", "launchApplication(): Activities ready for intent: " + activities.size());
if (activities.size() == 0){
Log.d("EasyControlService", "launchApplication(): there are no activities ready for intent");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
表示活动仍然存在。
答案 0 :(得分:1)
Sebastian,从我所看到的情况可能会发生这种情况,因为您在同一个过程中运行该服务。您甚至不需要Pending意图来启动应用程序,您可以按照常规意图执行此操作。您唯一需要做的就是让服务在一个单独的进程上运行。您可以在清单上的android:process=”:name_of_the_process”
标记上添加<service>
。