我正在处理需要启动后台服务的AIR Native Extension。
我尝试了不同的启动服务的方法。
这是我的AIR Android Manifest部分(来自我的-app.xml文件)
//AIR android manifest section
<manifest android:installLocation="auto">
<application>
<activity android:name=".TestActivity">
<intent-filter>
<action android:name=".TestActivity"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<service android:name=".TestService">
<intent-filter>
<action android:name="test.default.service"/>
</intent-filter>
</service>
</application>
</manifest>
Service Class与Activity位于同一个包中。 Activity运行得很好,在Activity的onStart()方法中,我尝试使用以下方法启动服务:
方法1:
import android.app.Activity;
public class TestActivity extends Activity
{
@Override
protected void onStart()
{
super.onStart();
Intent intent = new Intent("test.default.service");
//clearly the classes are available because this compiles!
intent.setClass(TestActivity.this, TestService.class);
startService(intent);
}
}
结果:
Unable to start service Intent { act=test.default.service cmp=air.com.my.company/com.my.company.TestService } U=0: not found
方法2:
import android.app.Activity;
public class TestActivity extends Activity
{
@Override
protected void onStart()
{
super.onStart();
//start a service with intent
startService(new Intent("test.default.service"));
}
}
结果:
FATAL EXCEPTION: main
java.lang.RuntimeExeption: Unable to instantiate service air.com.my.company.TestService:
java.lang.ClassNotFoundException:
Didn't find class "air.com.my.company.TestService" on path: /data/app/air.com.my.company-1.apk
问题似乎是&#34; air。&#34;尝试启动服务时,正在为包名称添加前缀。在运行自己的自定义服务时,如何解决这个包名称的错误?
我已经遍布堆栈溢出,以及Adobe的论坛,似乎无法找到解决此问题的完整解决方案。
还有一些其他帖子涉及此主题,但没有一个提供带有源的实际运行解决方案。
我已经把这个减少到最简单的情况,我可以确保没有引起问题的额外移动部件。
有关如何从AIR中运行的扩展上下文启动Android服务的任何官方信息都会有所帮助。似乎Adobe甚至对这个问题都很安静。
答案 0 :(得分:1)
我认为您需要使用包名称
在清单添加中完全确定服务类的范围...
<service android:name="com.my.company.TestService">
不确定它会不会有用。我知道普通的Android正确地预装了这个类,但AIR应用程序得到了解决。可能导致问题的前缀。
更新
我们实际上是通过几个原生扩展来实现的,所以我知道它是正确的。
使用完全作用域类名声明服务不使用点速记符号,这是您遇到问题的地方。使用点速记,Android将假定该类位于您的应用程序包中,该应用程序包在AIR应用程序中
air.com.my.company
您的方式意味着您的ANE将无法在具有不同应用ID的其他应用中运行!
默认情况下,另一个AIR应用程序将显示为
air.com.other.company.TestService
所以留下速记符号意味着此应用程序将找不到您的服务/活动:
air.com.my.company.TestService
正确的方法是在您的本机代码中使用干净的包名称,比如com.company.nativepackage,然后将其包含在清单中,如下所示:
<application>
<activity android:name="com.company.nativepackage.TestActivity">
<intent-filter>
<action android:name="TestActivity"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<service android:enabled="true" android:exported="true" android:name="com.company.nativepackage.TestService">
<intent-filter>
<action android:name="air.com.my.company.DO_CUSTOM_ACTION"/>
</intent-filter>
</service>
</application>
这适用于任何应用程序,让您的ANE更加便携。希望这是有道理的。
答案 1 :(得分:0)
我已经输入了这个问题并回答了问题,因为我花了很多时间才能确切地知道需要什么,而且我希望能为其他许多开发人员带来一些严重的麻烦。
上面显示的Android清单完全没问题。 上面显示的代码(在两种方法中)都非常好。
问题在于签名证书和AIR应用程序的包名称。
Adobe AIR Native Extensions规则
规则1。
代码签名证书包必须与app.xml中的应用程序ID匹配
因此,如果证书包为com.my.company
,则航空应用ID必须为<id>com.my.company</id>
规则2。
使用ADT打包android的原生扩展时,会在包名称中添加前缀,使其看起来像air.com.my.company
。
当Android ActivityManager尝试运行您的服务时,它会在air.com.my.company
中查找它。因此,Service类必须位于java代码中的相同包中(包括'air'前缀)。我的TestService类现在定义为air.com.my.company.TestService
使用以下清单,它运行得很好!
<application>
<activity android:name=".TestActivity">
<intent-filter>
<action android:name="TestActivity"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<service android:enabled="true" android:exported="true" android:name=".TestService">
<intent-filter>
<action android:name="air.com.my.company.DO_CUSTOM_ACTION"/>
</intent-filter>
</service>
</application>
并且......以下是我如何调用该服务。
Intent intent = new Intent("air.com.my.company.DO_CUSTOM_ACTION");
intent.setClass(currentContext, TestService.class);
currentContext.startService(intent);
答案 2 :(得分:0)
对我来说,唯一的变化是我传递给本机包的上下文。在我的情况下,我有一些我的本机代码公开的init(context)方法,我最初使用它是这样的:
instance.init(context.getActivity());
这给了我“无法找到服务”的错误。所以我把它改成了:
instance.init(context.getActivity().getApplicationContext());
现在它有效。