AIR Native Extension - 启动Android后台服务

时间:2013-01-31 22:19:14

标签: android service air adobe air-native-extension

我正在处理需要启动后台服务的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甚至对这个问题都很安静。

3 个答案:

答案 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应用程序的包名称。

Adob​​e 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());

现在它有效。