项目组用air来开发手游, 但有些在原生应用里很容易实现的功能没有办法在air中直接调用,比如说震动,服务等等。但Adobe 提供了一种方法让air间接调用本地代码(java,object-c...),就是接下来要介绍的ANE(Adobe Native Extension) 也叫本地扩展。
查了下资料,早在2011年11月 Adobe 官方就发一篇介绍ANE的文章附一个简单的例子, 在去年八月份Adobe 开发者中心 开始发一系列较为详尽的文章, 有兴趣可以阅读下:
http://www.adobe.com/cn/devnet/air/articles/developing-native-extensions-air.html
http://www.adobe.com/cn/devnet/air/air_for_android.html
我先照着官方例子,做了一个调节多好媒体音量的扩展,并在测试机器正常运转。于是我开始着手准备项目需求 -- 利用Andriod 服务来推送应用消息, 于是也有了这系列文章的由来,接下来我将介绍我做的一些工作。
一、 HellAndriod Service
由于我这前没有做过Andriod 开发,对java也不是很熟悉,唯一的Java编程经历是在大学时参与过的J2EE的项目,所以我先做了一个Andriod 服务的本地应用练练手. 这样的例子在网上很多,略作修改,代码如下:
package com.wenbo.helloandriod; import android.app.Notification; public class BackgroundService extends Service { private NotificationManager notificationMgr; private Thread mthr; private int mCount=0; private Boolean mSend=true; @Override public void onCreate() { super.onCreate(); notificationMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); displayNotificationMessage("starting Background Service"); if(mthr == null || mSend == false) { mSend=true; mthr = new Thread(null, new ServiceWorker(), "Background Service"); mthr.start(); } } @Override public void onDestroy() { super.onDestroy(); mSend = false; } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } class ServiceWorker implements Runnable { @Override public void run() { // do background processing here..... // stop the service when done... // BackgroundService.this.stopSelf() while(mSend) { try{ Thread.sleep(1000); Log.d("", "runnable" + mCount); displayNotificationMessage("runnable" + mCount); } catch (InterruptedException e) { e.printStackTrace(); } } } } private void displayNotificationMessage(String message) { Log.d("", message); mCount++; @SuppressWarnings("deprecation") Notification notification = new Notification(R.drawable.ic_launcher, message, System.currentTimeMillis()); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0); notification.setLatestEventInfo(this, "女神之贱", message, contentIntent); notificationMgr.notify(R.id.app_notification_id, notification); } }
在服务里开个线程,每隔一秒发一个后台通知。 然后我们建立一个入口启动它。
package com.wenbo.helloandriod; import android.os.Bundle; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "starting service"); Button bindBtn = (Button) findViewById(R.id.start); bindBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub startService(new Intent(MainActivity.this, BackgroundService.class)); } }); Button unbindBtn = (Button) findViewById(R.id.stop); unbindBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub stopService(new Intent(MainActivity.this, BackgroundService.class)); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
做完这些,别忘了配置权限, 在AndroidManifest.xml的<activity></activity>后面添加
<service android:name="BackgroundService"/>
安装到模拟器上或真实机器上 打开程序启动后就可以看到每隔一秒后台消息便会更新一次。按下stop后停止更新。
好了,下一节我将要按照ANE的要求改造它。
由于不能上传附件,我将另两个关键文件也贴出来。
一个是res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView1" android:layout_below="@+id/textView1" android:text="start" /> <Button android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/start" android:layout_below="@+id/start" android:layout_marginTop="15dp" android:text="stop" /> </RelativeLayout>
另一个是AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wenbo.helloandriod" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.wenbo.helloandriod.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="BackgroundService"/> </application> </manifest>