使用 Push 云服务扩展 Android 应用程序

2014 年 5 月 15 日
 
author photo - Salim Zeitouni

Salim Zeitouni

Software Engineer, IBM Application and Integration Middleware

Find me on LinkedIn

author photo - belinda johnson

Belinda Johnson

Software Engineer, IBM Mobile Cloud Services

@BeeMarieJohnson

Codename: BlueMix 是一款 beta 级产品,随着我们不断让其功能更加完善和更易于使用,它也将不断改进。我们会竭尽全力保持本文最新,但并不总是完全跟得上现状。感谢大家的理解!

您可能已了解 Codename:BlueMix 的一些优势,这是 IBM 用于开发和部署移动和 Web 应用程序的开放平台。BlueMix 中许多预先构建的服务,使构建和增强应用程序变得很轻松。

在本文中,我们将使用 Push 服务扩展一个 Android 应用程序。 本系列的其他文章 介绍了如何向应用程序添加更多基于云的服务。

上一篇文章 已经介绍过,BlueList 应用程序是一个简单的 Android 应用程序。本文将向 BlueList 应用程序添加 Push 和 CloudCode 服务,以便在一个设备以某种方式更新一个列表时,该列表会在所有设备上更新。

借助 BlueMix 上的免费服务,您可以立即开始编写和扩展自己的应用程序!

上一篇文章 中,我们添加了 MobileData 服务,我们持久保存了一个列表中的各项。现在,我们将添加推送通知和 CloudCode,以便在更新列表时获得通知。如果未阅读本系列的上一篇文章,您可从 v1 代码着手,但需要执行 Catch up 任务,然后才能执行添加 Push 和 CloudCode 服务所需的步骤。如果已经阅读完上一篇文章,那么您现在可从现有的代码着手,执行以下步骤来添加 Push 和 CloudCode 服务。如果希望下载并直接使用 v2 代码,则需要执行一些步骤才能让包含 MobileData、Push 和 CloudCode 服务的 BlueList 应用程序正常工作。v2 代码包含本文中对 v1 代码所做的更改。

完成您的应用程序的前提条件

 
  • 阅读 上一篇文章,我们在上一篇文章中向 Android 应用程序添加了 MobileData 服务。该应用程序是本文的起点。
  • 熟悉 Android 开发
  • 一个 Android 开发环境。我们使用了带 ADT 的 Eclipse,但您也可以使用自己喜欢的开发环境。
  • 熟悉用来从 JazzHub 下载 v1 和 CloudCode 的 git
  • JazzHub 上的 v1 代码(单击上面的按钮)或上一篇文章中的现有代码。
  • JazzHub 上的 CloudCode 模块。下载此模块,它包含一个 package.zip、package.json 和 itemlist.js。
  • 来自 Google 的一个 GCM Sender ID 和 API 密钥。在 Google 的操作说明我们的操作说明 中了解如何获取此密钥。

    备注:您需要一个 Gmail 帐户来执行此任务。

补充任务:如果您跳过了上一篇文章

 
  1. JazzHub 下载 v1 代码,如果尚未下载该代码。
  2. 参见 上一篇文章 中的第 1 步.在 BlueMix 上创建 Mobile App Services 包
  3. 执行第 1.1 - 1.10 步,但有一处例外:这次不要删除 configuration.json 文件中额外的行。

    执行这些步骤,登录到 BlueMix 上并创建一个应用程序 (BlueList),下载 Android SDK,使用您的 API 密钥更新 configuration.json 文件,并向您的 libs 目录添加 ibmcore.jar 和 ibmdata.jar。

  4. 要在添加 Push 服务之前在模拟器中运行此代码来验证您的 Android 开发环境,现在正是时候。您应该能够执行上一篇文章中的第 7 步. 运行应用程序第 8 步. 在云中查看数据

    如果应用程序成功运行,则说明您赶上了进度,可以添加 Push 和 CloudCode 服务了!

开始之前:获取您的 GCM Sender ID 和 Push 所需的 JAR 文件

 

获取您的项目编号和 GCM API 密钥

 
  1. 打开 Google Developers Console
  2. 单击 CREATE PROJECT,输入一个项目名称,单击 Create
  3. 从页面顶部复制项目编号。这是您的 GCM Sender Id (Google API Project Number),以后会需要该信息!
  4. 单击页面左侧的 APIs & auth
  5. 打开 Google Cloud Messaging for Android
  6. 在 APIs & auth 下,单击 Credentials
  7. 单击 Public API access 部分下的 CREATE NEW KEY
  8. 单击 Server key
  9. 单击 Create
  10. 从 Public API access 部分复制 API 密钥。这是您的 GCM Sender Auth Token (GCM API Key)。以后将需要此信息!

将 gcm.jar 添加到您的项目中

 
  1. 打开 Eclipse,选择 Window > Android SDK Manager
  2. 选择窗口底部的 Show:Obsolete 复选框。 Show Obsolete 选项的屏幕截图
  3. 滚动到底部,选择 Google Cloud Messaging for Android LibraryGoogle Cloud Messaging for Android Library 选项的屏幕截图
  4. 单击 Install 1 Package 并接受许可。 Install 1 Package 选项的屏幕截图
  5. 在您的文件资源管理器中找到 <Android_SDK_Location>\extras\google\gcm\gcm-client\dist
  6. 将 gcm.jar 文件复制到您项目的 libs 目录中。

将 ibmcloudcode.jar 和 ibmpush.jar 添加到您项目中

 
  1. 找到您在 上一篇文章 中第 1.7 步中下载的 Android SDK。
  2. 将 ibmcloudcode.jar 和 ibmpush.jar 文件复制到您项目的 libs 目录中。现在 libs 库中应该包含以下 5 个 jar 文件: jar 文件的屏幕截图

第 1 步. 在 BlueMix 中将 GCM API Key 添加到您的应用程序中

 
  1. 登录到 BlueMix
  2. 假设您已完成 上一篇文章 中的步骤或上面补充的任务步骤,在 DASHBOARD 视图中单击您的应用程序。
  3. 单击 Push 服务 Your_app_name:Push。 Push 服务的屏幕截图
  4. 在 Push 服务的 Configuration 选项卡下,单击 Google Cloud Messaging 下的 EDIT
  5. 填入您之前从 Google 获得的 GCM API Key 和 Google API Project Number,单击 SAVEEdit Button for Google Cloud Messaging 的屏幕截图

第 2 步. 熟悉服务器端的 CloudCode

 
  1. JazzHub 下载 CloudCode 模块,如果尚未下载该模块。
  2. 查看 package.json 并熟悉它。必须将该模块命名为 itemlist。您可以看到一个定义为 MBaasListApp 的 consumerId。该模块和 consumerId 需要与客户端 SDK 代码匹配。您可以更改它们,但一定要同时更新客户端代码。
  3. 此外,查看 itemlist.js 并熟悉它。您可以查看用来发送更新的代码,以及成功和错误处理代码。
  4. 它们都被压缩成一个名为 package.zip 的文件中。

第 3 步. 导入 CloudCode 模块 package.zip

 
  1. 登录到 BlueMix
  2. 从 DASHBOARD 视图,单击您的应用程序。
  3. 在 Services 下,单击 CloudCode 服务。 CloudCode 服务按钮的屏幕截图
  4. ON 滑到 OFF 来停止该应用程序。 停止应用程序的按钮的屏幕截图

    点击查看大图

  5. 单击 IMPORTIMPORT 按钮的屏幕截图

    点击查看大图

  6. 导航到刚下载的 CloudCode package.zip 文件并导入它。
  7. 单击该模块 (itemlist),然后单击 VARIABLES 来查看或编辑 consumerId 值。
  8. 启动该应用程序,方法是将滑块按钮滑回到 ON
  9. 返回到应用程序的 OVERVIEW,记下您用于 BlueList 的 API 密钥API 密钥位置的屏幕截图

    点击查看大图

第 4 步. 添加一些客户端代码,与我们刚设置的 Push 和 CloudCode 服务进行交互。

 
  1. 假设您已完成 上一篇文章 中的步骤或上面的补充任务部分,我们将开始更改此项目代码,生成 v2 代码。
  2. configuration.json 文件应位于 assets 文件夹中。将您的应用程序 ID(用于 BlueList 的 API 密钥)添加到适当的位置,如果尚未这么做。将下面的 plug ins:[ ...] 行复制到您的 configuration.json 文件中,并使用您的项目编号更新 gcmSenderId。(不要忘记在 applicationID: 行末尾添加结束逗号 (,)!)
    {
    	applicationID: "<INSERT_YOUR_APP_ID_HERE>",
    	plugins: [
    	{
    		id: "IBMPushService",
    		class: "com.ibm.mobile.services.push.IBMPushService",
    		parameters: {
    			gcmSenderId: "<INSERT_YOUR_GCM_SENDER_ID_HERE>"
    		}
    	}
    	]
    }
  3. 打开 AndroidManifest.xml 并按如下所示更新 permissionactivity 部分。在最后一个活动部分之后添加针对 RECEIVEREGISTRATION 的新 GCM Intent Service 和 intent-filter。
    <!--  Push Permission -->
    <permission
    android:name="com.ibm.bluelist.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
    
    <!--  Permissions -->		
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!--  Push Permissions -->	
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="com.ibm.bluelist.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <activity
        android:name="com.ibm.bluelist.MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboardHidden|orientation">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    			
        <!-- Push Settings Start -->
        <!-- Notification Intent -->
        <intent-filter>
            <action android:name="com.ibm.bluelist.BlueList.IBMPushNotification" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <!-- Push Settings End -->
    			
    </activity>
    <activity
        android:name="com.ibm.bluelist.EditActivity"
        android:label="@string/title_activity_edit"
        android:configChanges="keyboardHidden|orientation">
    </activity>					
    					
    <!-- Push Settings Start -->
    <!-- Add GCM Intent Service and intent-filters for RECEIVE and REGISTRATION of notifications -->
    <activity android:name="com.ibm.mobile.services.push.IBMUIActivity" />
    <service android:name="com.ibm.mobile.services.push.IBMPushIntentService" /> 
            
    <receiver android:name="com.ibm.mobile.services.push.IBMPushBroadcastReceiver"
     android:permission="com.google.android.c2dm.permission.SEND">
    	<intent-filter>
    		<action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
    		<category android:name="com.ibm.mbaas.push.sdk.client.android.sample" /> 
    	</intent-filter>
    
    	<intent-filter>
    		<action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 
    		<category android:name="com.ibm.mbaas.push.sdk.client.android.sample" /> 
    	</intent-filter>
    </receiver>
    <!-- Push Settings End -->
  4. 打开 BlueListApplication.java 并准备执行一些更改。
  5. 创建一个可供以后使用的 IBMPushServiceActivity 变量。创建表示设备别名和 consumerId字符串,它们在 CloudCode 模块中定义。此外,为 IBMPushServiceIBMPushNotificationListener 和该活动创建变量。
    public static final int EDIT_ACTIVITY_RC = 1;
    private static final String CLASS_NAME = BlueListApplication.class.getSimpleName();
    	
    // Add Push definitions
    public static IBMPushService push = null;
    private Activity mActivity;
    private static final String deviceAlias = "TargetDevice1";		
    private static final String consumerID = "MBaaSListApp";	
    private IBMPushNotificationListener notificationListener = null;
    
    List<Item> itemList;
  6. 跟踪 4 个 ActivityLifecycleCallbacks 内的活动状态。
    public BlueListApplication() {
    	registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
    		@Override
    		public void onActivityCreated(Activity activity,Bundle savedInstanceState) {
    			Log.d(CLASS_NAME, "Activity created: " + activity.getLocalClassName());
    			//Track activity
    			mActivity = activity;
    			//Initialize the SDK
    		    IBMBaaS.initializeSDK(activity);
    		}
    		@Override
    		public void onActivityStarted(Activity activity) {
    			Log.d(CLASS_NAME, "Activity started: " + activity.getLocalClassName());
    			//Track activity
    			mActivity = activity;
    		}
    		@Override
    		public void onActivityResumed(Activity activity) {
    			Log.d(CLASS_NAME, "Activity resumed: " + activity.getLocalClassName());
    			//Track activity
    			mActivity = activity;
    		}
    		@Override
    		public void onActivitySaveInstanceState(Activity activity,Bundle outState) {
    			Log.d(CLASS_NAME, "Activity saved instance state: " 
                + activity.getLocalClassName());
    		}
    		@Override
    		public void onActivityPaused(Activity activity) {
    			Log.d(CLASS_NAME, "Activity paused: " + activity.getLocalClassName());
    			//Track activity
    			if (activity != null && activity.equals(mActivity))
    				mActivity = null;
    		}
    		@Override
    		public void onActivityStopped(Activity activity) {
    			Log.d(CLASS_NAME, "Activity stopped: " + activity.getLocalClassName());
    		}
    		@Override
    		public void onActivityDestroyed(Activity activity) {
    			Log.d(CLASS_NAME, "Activity destroyed: " + activity.getLocalClassName());
    		}
    	});
    }
  7. 创建一个活动后,初始化 Push,注册该设备,然后注册 IBMPushResponseListener。此外,定义通知监听器。您的新 onActivityCreated 方法应类似于:
    public void onActivityCreated(Activity activity,Bundle savedInstanceState) {
       Log.d(CLASS_NAME, "Activity created: " + activity.getLocalClassName());
       //Track activity
       mActivity = activity;
       //Initialize the SDK
       IBMBaaS.initializeSDK(activity);
       //Initialize Push and register device
       push = IBMBaaS.getPluginManager().getPluginByClass(IBMPushService.class);
       push.register(deviceAlias, consumerID, new IBMPushResponseListener<String>() {
          @Override
          public void onSuccess(String deviceId) {
             Log.d(CLASS_NAME, "Device Successfully Registered");
          }
    
          @Override
          public void onFailure(IBMPushException ex) {
             Log.e(CLASS_NAME, "Exception: " + ex.getMessage());
          }
       });
       //Define IBMPushNotificationListener behavior on Push notifications
       notificationListener = new IBMPushNotificationListener() {
       @Override
       public void onReceive(final IBMPushMessage message) {
          mActivity.runOnUiThread(new Runnable(){
             @Override
             public void run() {
                Class<? extends Activity> actClass = mActivity.getClass();
                if (actClass == MainActivity.class) {
                   ((MainActivity)mActivity).listItems();
                   Log.e(CLASS_NAME, "Notification message received: " + message.toString());
                   //present the message when sent from Push notification console.
                   if(!message.getAlert().contains("ItemList was updated")){
                      mActivity.runOnUiThread(new Runnable() {
                         public void run() {
                            new AlertDialog.Builder(mActivity)
                         .setTitle("Push notification received")
                         .setMessage(message.getAlert())
                         .setPositiveButton(android.R.string.ok,
    					    new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                            }
                         })
                         .show();
                         }
                      });
    
                   }
                   if(!message.getAlert().contains("ItemList was updated")){
                      mActivity.runOnUiThread(new Runnable() {
                         public void run() {
                            new AlertDialog.Builder(mActivity)
                         .setTitle("Push notification received")
                         .setMessage(message.getAlert())
                         .setPositiveButton(android.R.string.ok,
    					    new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                            }
                         })
                         .show();
                         }
                      });
                    }
                 }
             }
          });
       }
    };
    }
  8. 在使用活动或暂停活动时检查 push 服务。您的新 onActivityResumed 方法和 onActivityPaused 方法应类似于:
    public void onActivityResumed(Activity activity) {
    	Log.d(CLASS_NAME, "Activity resumed: " + activity.getLocalClassName());
    	//Track activity
    	mActivity = activity;
    	if (push != null) {
    		push.listen(notificationListener);
    	}
    }
    public void onActivityPaused(Activity activity) {
    	Log.d(CLASS_NAME, "Activity paused: " + activity.getLocalClassName());
    	//Track activity
    	if (activity != null && activity.equals(mActivity))
       		mActivity = null;
    	if (push != null) {
    		push.hold();
    	}
    }
  9. 在 MainActivity.java 中,添加在编辑、创建和删除项目时对 updateOtherDevices 的调用。添加新的 updateOtherDevices 方法,它将调用您之前上传到应用程序中的 CloudCode 模块 (itemlist.js)。
    清单 1. 实现 updateOtherDevices()
    /* 
     * Invoke Cloud functions 
     */
    private void updateOtherDevices() {
    	String module = "itemlist";
    	String function = "sendUpdateNotification";
    	// This is a shortcut for invoking cloud functions
    	IBMBaaS.getPluginManager().getPluginByClass(IBMCloudCodeService.class)
    		.callFunction(module, function);
    }
    /*if an edit has been made, notify that the data set has changed.*/
    case BlueListApplication.EDIT_ACTIVITY_RC:
    	// Call updateOtherDevices to invoke Cloud functions
    	updateOtherDevices();
    	sortItems(itemList);
    	lvArrayAdapter.notifyDataSetChanged();
    	break;
    }
    清单 2. Create 上的 updateOtherDevices()
    public void createItem(View v) {
    	. . .
    	public void onResult(Item object) {
    		if (!isFinishing()) {
    			listItems();
    			// Call updateOtherDevices to invoke Cloud functions
    			updateOtherDevices();
    		}
    	}
    清单 3. Delete 上的 updateOtherDevices()
    public void deleteItem(Item item) {
    	. . .
    	public void onResult(Item item) {
    		if (!isFinishing()) {
    			runOnUiThread(new Runnable() {
    				public void run() {
    					// Call updateOtherDevices to invoke Cloud functions
    					updateOtherDevices();
    					lvArrayAdapter.notifyDataSetChanged();
    				}
    			});
    		}
    	}

第 5 步. 运行应用程序

 
  1. 目前,您已经更改了代码,您的代码现在应该与第 2 版等同!
  2. 在两个不同的模拟器中运行最新的代码。

    备注:确保您的 Android 设备支持 Google APIs

    • 在 Eclipse 中,转到 Project > Properties > Android
    • 确保选择了适用于您的 API 级别的 Google API,单击 Apply
    • 打开 Android Virtual Device Manager,选择您的设备,单击 Edit 并将 Target: 设置为 Google APIs (Google Inc.) - API Level XX(其中 XX 与您的 API 级别匹配)。
  3. 添加一些杂货列表商品。
  4. 观看是否每个列表都已更新!

第 6 步. 从 BlueMix 测试发送通知

 
  1. 登录到 BlueMix
  2. 从 DASHBOARD 视图,单击您的应用程序。
  3. 单击 Push 服务图标。
  4. 单击 Notification 选项卡。
  5. 在 Message text 字段中填入您想要的任何内容,然后单击 NEXT您的通知消息的屏幕截图
  6. 选择 Recipients,单击 SEND
  7. 观看您的移动设备或模拟器是否收到了推送通知! 设备上的通知消息的屏幕截图

结束语

 

使用 Codename: BlueMix 中的 Push 和 CloudCode 服务扩展您的应用,您应该能够通过此操作了解到通过移动云服务来使用和集成移动数据功能是多么容易!在本系列中,到目前为止,您已经使用了 MobileData 服务来存储、删除、更新和查询一个存储在云上的对象列表。您还使用 Push 和 CloudCode 服务在所有设备上刷新了此列表,在设备以某种方式更新该列表时发送通知。


相关主题:本系列的上一篇文章(MobileData 服务)

添加评论

注意:评论中不支持 HTML 语法


剩余 1000 字符

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=移动开发, Cloud computing
ArticleID=971279
ArticleTitle=使用 Push 云服务扩展 Android 应用程序
publish-date=05152014