<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>润物无声 &#187; PhoneGap</title>
	<atom:link href="http://blog.zhourunsheng.com/tag/phonegap/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.zhourunsheng.com</link>
	<description>天空一朵雨做的云</description>
	<lastBuildDate>Sat, 08 May 2021 05:17:21 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.41</generator>
	<item>
		<title>关于PhoneGap视频插件的代码更新</title>
		<link>http://blog.zhourunsheng.com/2012/04/%e5%85%b3%e4%ba%8ephonegap%e8%a7%86%e9%a2%91%e6%8f%92%e4%bb%b6%e7%9a%84%e4%bb%a3%e7%a0%81%e6%9b%b4%e6%96%b0/</link>
		<comments>http://blog.zhourunsheng.com/2012/04/%e5%85%b3%e4%ba%8ephonegap%e8%a7%86%e9%a2%91%e6%8f%92%e4%bb%b6%e7%9a%84%e4%bb%a3%e7%a0%81%e6%9b%b4%e6%96%b0/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 06:55:35 +0000</pubDate>
		<dc:creator><![CDATA[润物无声]]></dc:creator>
				<category><![CDATA[移动开发]]></category>
		<category><![CDATA[Cordova]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[插件]]></category>

		<guid isPermaLink="false">http://blog.zhourunsheng.com/?p=1441</guid>
		<description><![CDATA[<p>本文主要介绍PhoneGap视频插件的代码更新，具体插件的开发过程请参照我以前的博文《phonegap之and [&#8230;]</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2012/04/%e5%85%b3%e4%ba%8ephonegap%e8%a7%86%e9%a2%91%e6%8f%92%e4%bb%b6%e7%9a%84%e4%bb%a3%e7%a0%81%e6%9b%b4%e6%96%b0/">关于PhoneGap视频插件的代码更新</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>本文主要介绍PhoneGap视频插件的代码更新，具体插件的开发过程请参照我以前的博文《<a href="http://blog.zhourunsheng.com/2011/11/phonegap-%E4%B9%8B-android-%E7%AB%AF%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91/">phonegap之android端插件开发</a>》。现在PhoneGap已经把代码移交到apache开源项目cordova里面，本文代码的更新主要涉及到两项，一是把以前phoneGap的引用迁移到cordova的引用中，二是在原来插件代码的基础上增加回调机制。<span id="more-1441"></span></p>
<p>以前版本的视频插件可以在android设备上面正常工作，但是有一个潜在的问题，因为插件启动视频播放利用的是 “startActivity”方法，无法获取到视频播放结束的消息，本次代码的主要改进就是改变原来启动视频播放的函数，使用“startActivityForResult”方法，这样当视频播放结束的时候，“onActivityResult”方法会被回调，从而该插件就能正确通知插件使用者视频已正常播放结束，可以继续处理其他流程。</p>
<p>Java 端的完整代码如下：</p>
<pre>package com.dlgreat.bbhtml.plugins;

import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;

import android.content.Intent;
import android.net.Uri;

public class VideoPlayer extends Plugin {

private String callbackId;

@Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
   this.callbackId = callbackId;
   PluginResult.Status status = PluginResult.Status.OK;
   String result = "";

   try {
       if (action.equals("playVideo")) {
           playVideo(args.getString(0));

           PluginResult res = new PluginResult(PluginResult.Status.NO_RESULT);
           res.setKeepCallback(true);
           return res;
       }

       return new PluginResult(status, result);
   } catch (JSONException e) {
       return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
   }
}

private void playVideo(String url) {
    Uri uri = Uri.parse(url);
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(uri, "video/*");

    this.ctx.startActivityForResult(this, intent, 0);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
  if (requestCode == 0) {
     success(new PluginResult(PluginResult.Status.OK, ""), callbackId);
  }
}
}</pre>
<p>Javascript端的完整代码如下：</p>
<pre>/* PhoneGap 视频播放插件*/

/**
* Constructor
*/
function VideoPlayer() {};

/**
* Starts the video player intent
*
* @param url The url to play
*/
VideoPlayer.prototype.play = function(url, successCallback, errorCallback) {
   cordova.exec(successCallback, errorCallback, "VideoPlayer", "playVideo", [url]);
};

/**
* Load VideoPlayer
*/
cordova.addConstructor(function() {
    cordova.addPlugin("videoplayer", new VideoPlayer());
});</pre>
<p>插件的配置代码如下（xml/plugins.xml）：</p>
<pre>&lt;plugin name="VideoPlayer" value="com.dlgreat.bbhtml.plugins.VideoPlayer"/&gt;</pre>
<p>插件的使用代码如下：</p>
<pre>BBGlobalData.validBackKey = false;
window.plugins.videoplayer.play(data, function() {
     console.log('play video ok done !!!');
     setTimeout(function(){BBGlobalData.validBackKey = true;}, 300);
}, function() {
    console.log('play video error done !!!');
    setTimeout(function(){BBGlobalData.validBackKey = true;}, 300);
});</pre>
<p>通过如上代码的修正，即可以在程序中正确处理视频播放的消息回调，插件的待完善之处就是只处理了视频播放成功的消息，默认支持所有的视频格式，可以在java端代码的实现中加入视频文件格式的判断，文件完整性的判断等等，如果有出错的时候，可以利用“error”方法来返回处理结果，具体的参数和“success”一致！</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2012/04/%e5%85%b3%e4%ba%8ephonegap%e8%a7%86%e9%a2%91%e6%8f%92%e4%bb%b6%e7%9a%84%e4%bb%a3%e7%a0%81%e6%9b%b4%e6%96%b0/">关于PhoneGap视频插件的代码更新</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zhourunsheng.com/2012/04/%e5%85%b3%e4%ba%8ephonegap%e8%a7%86%e9%a2%91%e6%8f%92%e4%bb%b6%e7%9a%84%e4%bb%a3%e7%a0%81%e6%9b%b4%e6%96%b0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sencha Touch 程序设计之 Android 平台 Back 按键处理</title>
		<link>http://blog.zhourunsheng.com/2012/04/sencha-touch-%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e4%b9%8b-android-%e5%b9%b3%e5%8f%b0-back-%e6%8c%89%e9%94%ae%e5%a4%84%e7%90%86/</link>
		<comments>http://blog.zhourunsheng.com/2012/04/sencha-touch-%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e4%b9%8b-android-%e5%b9%b3%e5%8f%b0-back-%e6%8c%89%e9%94%ae%e5%a4%84%e7%90%86/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 07:23:40 +0000</pubDate>
		<dc:creator><![CDATA[润物无声]]></dc:creator>
				<category><![CDATA[移动开发]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[Sencha]]></category>
		<category><![CDATA[WebApp]]></category>

		<guid isPermaLink="false">http://blog.zhourunsheng.com/?p=1406</guid>
		<description><![CDATA[<p>利用 Sencha Touch 结合PhoneGap设计本地APP，免不了要分别处理android平台和iph [&#8230;]</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2012/04/sencha-touch-%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e4%b9%8b-android-%e5%b9%b3%e5%8f%b0-back-%e6%8c%89%e9%94%ae%e5%a4%84%e7%90%86/">Sencha Touch 程序设计之 Android 平台 Back 按键处理</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>利用 Sencha Touch 结合PhoneGap设计本地APP，免不了要分别处理android平台和iphone平台，两个平台的最大区别之一就是back键的处理。iphone平台没有back按键，只有home按键，按下该键的话程序会自动转入后台处理，该按键的效用等同于android平台的home按键，但是，android平台特殊的地方在于，它还有一个back键，熟悉了android平台的开发者或使用者，把该键的作用理解为退回程序的上一个页面，如果程序已经在主页面，此时则退出程序。</p>
<p>因为Sencha Touch对android平台进行了消息封装，默认对back键的处理，同home键的处理一致，这令很多android开发者或使用者使用其功能的话不太友好，我自己在调试程序的过程中就误操作过了N次，每次按下back键期望程序回退到上一个页面，没想到程序直接消失了，转到后台去了。<span id="more-1406"></span></p>
<p>网上搜索了一些解决方案，各有利弊，汇总贴可参照Sencha Touch官方论坛《<a href="http://www.sencha.com/forum/showthread.php?133948-Why-can-t-I-control-Android-phone-s-hardware-Back-button-in-Sencha-with-PhoneGap">Why-can-t-I-control-Android-phone-s-hardware-Back-button-in-Sencha-with-PhoneGap</a>》，下面介绍一下我设计的一个解决方案，在实测环境中工作良好，总结如下：</p>
<p>1. 首先在Sencha 启动代码中捕获android平台的back按键消息，阻止Sencha 框架的默认处理</p>
<pre>var App = new Ext.application({
 // ... APP 配置参数

 launch : function () {
  // ... 界面初始化
   BBGlobalData.mainPanel = Ext.create('Ext.Panel', {
       fullscreen: true,
       layout : 'card',
       cardAnimation : 'slide',
       items: [
           Ext.create('BBShow.view.LoginPanel'),
           Ext.create('BBShow.view.HomePanel'),
           Ext.create('BBShow.view.MediaPanel'),
           Ext.create('BBShow.view.PicCarousel'),
           Ext.create('BBShow.view.ReportListPanel'),
           Ext.create('BBShow.view.ReportPanel'),
       ]
   });

   Ext.Viewport.add(BBGlobalData.mainPanel);

   document.addEventListener('deviceready', function () {
     console.log('deviceready');
     document.addEventListener("backbutton", function () {
           console.log('user presses the back button on Android');
           // 获取当前的焦点页面，并发送自定义消息'back'
           BBGlobalData.mainPanel.getActiveItem().fireEvent('back');
    }, false);
  }, false);
}
})</pre>
<p>2. 在子页面中注册back消息的监听器</p>
<pre>/*定义登录面板*/
Ext.define('BBShow.view.LoginPanel', {
extend: 'Ext.Panel',

    config: {
      items: [
      {
        xtype: 'titlebar',
        docked: 'top',
        title: '用户登录'
      },
      // 其他页面内容
     ],
    listeners: [
     {
      fn: 'onBack',
      event: 'back', //注册监听自定义back按键消息
     }
    ]
  },

  onBack: function() {
    //BBGlobalData.gotoHomePanel(); //如，跳转到其他页面
    BBGlobalData.exitApp(); //或退出程序
  },
});</pre>
<p>3. 实现退出程序的处理，借助于PhoneGap</p>
<pre>   BBGlobalData.exitApp = function() {
   navigator.app.exitApp();
}</pre>
<p>4. 实现页面跳转的处理（主页面采用card view，类似于扑克的翻牌）</p>
<pre>BBGlobalData.gotoHomePanel = function() {
   BBGlobalData.mainPanel.setActiveItem(1);
}</pre>
<p>总结：其实总的解决方法还是很简单，只要把整体的框架搭建完善了，很容易就能在多平台之间转换了。</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2012/04/sencha-touch-%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e4%b9%8b-android-%e5%b9%b3%e5%8f%b0-back-%e6%8c%89%e9%94%ae%e5%a4%84%e7%90%86/">Sencha Touch 程序设计之 Android 平台 Back 按键处理</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zhourunsheng.com/2012/04/sencha-touch-%e7%a8%8b%e5%ba%8f%e8%ae%be%e8%ae%a1%e4%b9%8b-android-%e5%b9%b3%e5%8f%b0-back-%e6%8c%89%e9%94%ae%e5%a4%84%e7%90%86/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>编写 PhoneGap 程序调试问题解决方案</title>
		<link>http://blog.zhourunsheng.com/2012/03/%e7%bc%96%e5%86%99-phonegap-%e7%a8%8b%e5%ba%8f%e8%b0%83%e8%af%95%e9%97%ae%e9%a2%98%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/</link>
		<comments>http://blog.zhourunsheng.com/2012/03/%e7%bc%96%e5%86%99-phonegap-%e7%a8%8b%e5%ba%8f%e8%b0%83%e8%af%95%e9%97%ae%e9%a2%98%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 02:22:15 +0000</pubDate>
		<dc:creator><![CDATA[润物无声]]></dc:creator>
				<category><![CDATA[移动开发]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[WebApp]]></category>

		<guid isPermaLink="false">http://blog.zhourunsheng.com/?p=1353</guid>
		<description><![CDATA[<p>这几天做项目，需要设计一个和服务器交互的库，同时也有一个提高效率的需求就是设计缓存机制，无奈PhoneGap提 [&#8230;]</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2012/03/%e7%bc%96%e5%86%99-phonegap-%e7%a8%8b%e5%ba%8f%e8%b0%83%e8%af%95%e9%97%ae%e9%a2%98%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/">编写 PhoneGap 程序调试问题解决方案</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>这几天做项目，需要设计一个和服务器交互的库，同时也有一个提高效率的需求就是设计缓存机制，无奈PhoneGap提供的API太坑爹了，编写个缓存费了N大的劲才完成，记录一下要注意的地方。</p>
<p>1. 客户端浏览器调试Ajax请求报错“<span style="color: #ff0000;">Origin null is not allowed by Access-Control-Allow-Origin</span>. ”</p>
<p>解决办法：谷歌浏览器 <code>chrome.exe --disable-web-security</code></p>
<p>2. PhoneGap 远程调试</p>
<p>远程调试架构图如下所示：</p>
<p><img src="http://blog.zhourunsheng.com/wp-content/uploads/2012/05/02.jpg" alt="remote_debugging_architecture" width="500" height="357" /></p>
<p><span id="more-1353"></span></p>
<p>配置步骤如下：</p>
<p>a. 登录网址：<a href="http://debug.phonegap.com/">http://debug.phonegap.com/</a> 填写配置信息</p>
<p><img src="http://blog.zhourunsheng.com/wp-content/uploads/2012/05/06.jpg" alt="debug_phonegap_getting_started" width="500" height="162" /></p>
<p>b. 在本地代码中引用远程调试JS代码文件</p>
<p><img src="http://blog.zhourunsheng.com/wp-content/uploads/2012/05/03.jpg" alt="debug_phonegap_client" width="500" height="235" /></p>
<p>c. 打开远程调试窗口<a href="http://debug.phonegap.com/client/#bbshow">http://debug.phonegap.com/client/#bbshow</a> （bbshow为第一步骤配置的名字）</p>
<p><img src="http://blog.zhourunsheng.com/wp-content/uploads/2012/05/04.jpg" alt="debug_phonegap_server" width="500" height="256" /></p>
<p>在调试窗口中可以修改节点的属性，然后手机上的画面就会自动更新了。</p>
<p>3.  常用的代码总结</p>
<p>a. 设计 Ajax 数据通信（如用户登录）</p>
<pre>/*
用户登录模块

params = {};
params.username 登录用户名
params.password 登录用户密码

succcb  登录成功时候的回调函数 function(data);
errcb   登录失败时候的回调函数 function(text);
*/
function bb_login(params, succcb, errcb)
{
   var tmplate = login_req_xml(params);

   doPost(tmplate, function(data, textStatus, jqXHR) {
      if (data.status == 0) {
          errcb(data.info);
      } else {
          GServerData.curToken = data.data;
          succcb(data.data);
      }
   }, function(jqXHR, textStatus, errorThrown) {
         errcb(textStatus);
   });
}

/*用户登录的模板文件*/
function login_req_xml(params)
{
  var tmplate = '&lt;?xml version="1.0" encoding="utf-8"?&gt;'
       + '&lt;request&gt;'
       + '&lt;operation&gt;'
       + '&lt;module&gt;token&lt;/module&gt;'
       + '&lt;action&gt;login&lt;/action&gt;'
       + '&lt;params&gt;'
       + '&lt;username&gt;' + params.username + '&lt;/username&gt;'
       + '&lt;password&gt;' + params.password + '&lt;/password&gt;'
       + '&lt;/params&gt;'
       + '&lt;/operation&gt;'
       + '&lt;/request&gt;';
   return  tmplate;
}

/*
向服务器发送 POST 请求.

data: 向服务器发送的数据内容
succcb: 成功时候的回调函数 success(data, textStatus, jqXHR)
errcb:  失败时候的回调函数 error(jqXHR, textStatus, errorThrown)
*/
function doPost(data, succcb, errcb)
{
   $.ajax({
      type: "POST",
      url: Config.serverapi,
      data: data,
      cache: false,
      dataType: "json",
      success: succcb,
      error: errcb
   });
}

b.  数据缓存

/*
dataUrl 请求数据的网络URL地址
如果缓存成功，则会返回本地的File地址

succcb 登录成功时候的回调函数 function(data);
errcb 登录失败时候的回调函数 function(text);
*/
function bb_loadCacheData(dataurl, succcb, errcb)
{
  var errorCB = function (err) {
      console.log("Error processing : " + err.code);
      errcb("Error processing : " + err.code);
  }

var downLoadFile = function(db) {
  console.log("downLoadFile ... [" + dataurl + "]");

   //特别备注：在Phonegap1.5.0中，LocalFileSystem.TEMPORARY 和 LocalFileSystem.PERSISTENT 两者相反了
   window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) {
        var datadate = new Date().getTime();
        var filename = datadate + '_' + dataurl.substr(dataurl.lastIndexOf('/')+1);

        var fileTransfer = new FileTransfer();

        fileTransfer.download(
           dataurl,
           fileSystem.root.fullPath.substr("file://".length) + Config.datacachepath + filename,
           function(entry) {
               console.log("download complete: " + entry.fullPath);
               db.transaction(function (tx) {
                   tx.executeSql('INSERT INTO data_cache (dataurl, datapath, datadate) VALUES ("' + dataurl + '","' + entry.fullPath + '","' + datadate + '")');
               succcb(entry.fullPath);
               }, errorCB);
           },
          function(error) {
              console.log("download error source " + error.source);
              console.log("download error target " + error.target);
              console.log("download error code " + error.code);
              errcb("download error code " + error.code);
          }
      ); 
     }, errorCB);
   };

   var db = window.openDatabase("cache.db", "1.0", "BBShow Data Cache DB", 200000);
   db.transaction(function (tx) {
      tx.executeSql('CREATE TABLE IF NOT EXISTS data_cache (id unique, dataurl, datapath, datadate)');
      tx.executeSql('SELECT * FROM data_cache WHERE dataurl=?', [dataurl], function(tx, results) {
      if (results.rows.length &gt; 0) {
         window.resolveLocalFileSystemURI(results.rows.item(0).datapath, function(fileEntry) {
              console.log(fileEntry.fullPath);
              succcb(fileEntry.fullPath);
         }, function(error) {
              console.log("Unable to resolveLocalFileSystemURI: " + error.code);
              db.transaction(function (tx) {
              tx.executeSql('DELETE FROM data_cache WHERE dataurl=?', [dataurl]);
              downLoadFile(db);
         }, errorCB);
        });
      } else {
          downLoadFile(db);
      }
     }, errorCB);
   }, errorCB);
}</pre>
<p>总之，这两天才发现 PhoneGap不是一般的难用，真应该再多完善完善！！！</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2012/03/%e7%bc%96%e5%86%99-phonegap-%e7%a8%8b%e5%ba%8f%e8%b0%83%e8%af%95%e9%97%ae%e9%a2%98%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/">编写 PhoneGap 程序调试问题解决方案</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zhourunsheng.com/2012/03/%e7%bc%96%e5%86%99-phonegap-%e7%a8%8b%e5%ba%8f%e8%b0%83%e8%af%95%e9%97%ae%e9%a2%98%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>PhoneGap入门之问题解读</title>
		<link>http://blog.zhourunsheng.com/2012/02/phonegap%e5%85%a5%e9%97%a8%e4%b9%8b%e9%97%ae%e9%a2%98%e8%a7%a3%e8%af%bb/</link>
		<comments>http://blog.zhourunsheng.com/2012/02/phonegap%e5%85%a5%e9%97%a8%e4%b9%8b%e9%97%ae%e9%a2%98%e8%a7%a3%e8%af%bb/#comments</comments>
		<pubDate>Sat, 18 Feb 2012 02:30:39 +0000</pubDate>
		<dc:creator><![CDATA[润物无声]]></dc:creator>
				<category><![CDATA[移动开发]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.zhourunsheng.com/?p=1323</guid>
		<description><![CDATA[<p>很多PhoneGap新手总是需要一些基础问题的解答，Adobe技术布道师Andrew Trice常在其博文中回 [&#8230;]</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2012/02/phonegap%e5%85%a5%e9%97%a8%e4%b9%8b%e9%97%ae%e9%a2%98%e8%a7%a3%e8%af%bb/">PhoneGap入门之问题解读</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p><img class="alignleft" title="phonegap" alt="phonegap" src="http://farm8.staticflickr.com/7199/6894224361_9ec59d3a49_t_d.jpg" width="75" height="75"/>
<p>很多PhoneGap新手总是需要一些基础问题的解答，Adobe技术布道师Andrew Trice常在其博文中回答诸如” PhoneGap是什么?”、“phonegap应用开发出来是什么样的形态?”、“如何开发phonegap?”等问题。近日他将这些问题回答整理成文以帮助开发者理解和使用PhoneGap。</p>
<h3><strong>1. PhoneGap是什么?</strong></h3>
<p>PhoneGap是一个基于HTML和JavaScript的应用开发平台，使用它可以构建本地应用。你可以把PhoneGap看作一个正方形的web view container，它使用JavaScript编程接口实现用户在不同操作系统下的访问。你可以利用传统的web开发技术(如HTML、CSS、JavaScript )开发用户接口，利用PhoneGap容器把它们部署到不同的应用环境和设备上。</p>
<p>PhoneGap可以被用来开发跨平台的应用，这些平台包括Apple iOS、 Google Android,、Windows Phone、BlackBerry、 HP WebOS,、Symbian 和 Bada。你可以通过链接<a href="http://phonegap.com/about/features">http://phonegap.com/about/features</a> 获取更多关于PhoneGap支持的平台及其特色功能的信息。</p>
<p>PhoneGap是一个开源的框架,用户可以去<a href="http://incubator.apache.org/projects/callback.html">http://incubator.apache.org/projects/callback.html</a>获取更多信息。</p>
<p> <span id="more-1323"></span><br />
<h3><strong>2.开发出的PhoneGap应用是什么样的形态？</strong></h3>
<p>由于UI绘制引擎就是移动设备的内置web浏览器，所以PhoneGap应用的形态可能多种多样。你可以使用标准的HTML&amp;CSS使它看起来就像一个简单的网页，也可以使用UI框架使它像jQuery UI, Kendo UI, Sencha, Twitter Bootstrap或Skeleton(或者其它任意基于HTML/CSS/JS的用户框架接口)。另外你也可以采用CSS模式/主题使它看起来就像一个本地应用，如模仿iOS 和 Android的iUI，模仿BlackBerry的bbUI。</p>
<p>PhoneGap应用可以是基于HTML的静态UIs，也可以是利用JavaScript开发具有动态效果和交互体验动态UIs。这取决于特定的应用、用户体验设计、受众目标以及指示PhoneGap应用如何出现的应用实例。</p>
<p>使用PhoneGap应用，你可以通过缩小放大操作放大或者缩小查看的内容，或者利用利用viewport metadata tag锁定浏览内容的大小。你可以利用常规浏览器的操作方式滚动浏览网页也可以像iScroll一样采用基于接触的滑动方式浏览网页。</p>
<p>基于HTML, CSS &amp; JavaScript你有许多方式可以创建用户接口，所以并没有一个典型的外观。如果你没有使用任何的CSS模式，那么用户接口各元素默认和使用的操作系统或者浏览器保持一致，包括按钮、链接、色彩以及亮度。这时PhoneGap应用和操作系统默认的浏览器一样运行。</p>
<h3><strong>3. 如何利用PhoneGap开发应用？</strong></h3>
<p>利用PhoneGap开发应用非常简单，90%的PhoneGap应用只需要一个文本编辑器即可。PhoneGap也能很容易的与特定的设备整合形成开发环境。具体可以参考以各应用平台上的开发指导链接：</p>
<p>•iOS: <a href="http://phonegap.com/start#ios-x4">http://phonegap.com/start#ios-x4</a><br/> •Android: <a href="http://phonegap.com/start#android">http://phonegap.com/start#android</a><br/> •BlackBerry: <a href="http://phonegap.com/start#blackberry">http://phonegap.com/start#blackberry</a><br/> •Windows Phone: <a href="http://phonegap.com/start#wp">http://phonegap.com/start#wp</a><br/> •WebOS: <a href="http://phonegap.com/start#webos">http://phonegap.com/start#webos</a><br/> •Symbian: <a href="http://phonegap.com/start#symbian">http://phonegap.com/start#symbian</a></p>
<p><img title="phonegap_platforms" alt="phonegap_platforms" src="http://farm8.staticflickr.com/7064/6894224509_93c1ceee58_d.jpg" width="385" height="86"/></p>
<p>在开发PhoneGap应用应用时 ，一定要谨记你是在web浏览器实例中运行代码。你是利用HTML和JavaScript开发应用而不是本地代码，因此不需要其它任何东西。实际上我的大部分开发都是利用HTML编辑器和Chrome浏览器实现的。当我需要在设备上做测试的时候再切换到特定的设备环境。</p>
<h3><strong>4. 如何调试PhoneGap应用？</strong></h3>
<p>调试PhoneGap应用是PhoneGap开发过程中最棘手部分。只在物理设备上测试，并不能测试出所有的JavaScript异常。下面是一些具体的调式策略：</p>
<p><strong>尽可能利用桌面浏览器调试</strong></p>
<p>由于PhoneGap应用是利用HTML, CSS, and JavaScript进行开发的，你可以利用HTML编辑器开发大部分应用然后利用桌面web浏览器调试。最新版本的web浏览器(包括Chrome、IE、Firefox、 Opera 和Safari)都提供了丰富的调试功能。利用web浏览器开发工具，你可以检查HTML DOM元素，检查CSS的模式、设置JavaScript断点、检查内存和JavaScript变量。通过下面链接可以获得更多更多关于桌面浏览器开发工具的信息：</p>
<p>•Chrome Developer Tools: <a href="http://code.google.com/chrome/devtools/docs/overview.html">http://code.google.com/chrome/devtools/docs/overview.html</a><br/> •Firefox via FireBug: <a href="http://getfirebug.com/">http://getfirebug.com/</a><br/> •Safari Developer Tools: <a href="https://developer.apple.com/technologies/safari/developer-tools.html">https://developer.apple.com/technologies/safari/developer-tools.html</a><br/> •IE Developer Tools: <a href="http://msdn.microsoft.com/en-us/ie/aa740478">http://msdn.microsoft.com/en-us/ie/aa740478</a><br/> •Opera Developer Tools: <a href="http://dev.opera.com/articles/view/opera-developer-tools/">http://dev.opera.com/articles/view/opera-developer-tools/</a></p>
<p>你一旦利用桌面工具开发了应用的主要功能，便可以切换到特定的设备环境增加特定的设备功能并与PhoneGap APIs整合。</p>
<p>利用真实设备进行测试是必不可少的。利用真实设备测试可能获得不同于桌面浏览器和模拟器的性能，也可以发现不同的bug和问题包括API的不同和UX脚本的不同。</p>
<p><strong>用debug.phonegap.com调试</strong></p>
<p>利用debug.phonegap.com可以进行远程的基于设备的调试。利用Weinre调试工具你可以远程检查DOM、测试资源下载、检测网络使用、检测时间线以及控制台输出。如果你已经使用了上述列出的开发工具，就会发现它们看起来很相似。只是你不能在移动设备上设置断点，但是肯定比什么都没有强。</p>
<p><strong>利用iOS5进行远程web调试</strong></p>
<p>利用iOS5模拟器实现远程调试只需要开通远程调试功能即可。然后利用iOS5桌面模拟器发布应用。一旦应用运行它就会打开一个本地Safari实例http://localhost:9999/。这将启动远程调试工具，完成断点设置和脚本测试。</p>
<p>通过连接<a href="http://hiediutley.com/2011/11/22/debugging-ios-apps-using-safari-web-inspector/">http://hiediutley.com/2011/11/22/debugging-ios-apps-using-safari-web-inspector/</a>你可以获取更多信息。</p>
<p><strong>其他调试信息</strong></p>
<p>通过下面链接你可以阅读更多关于PhoneGap应用应用的调试信息：</p>
<p>•<a href="http://phonegap.com/2011/05/18/debugging-phonegap-javascript/">http://phonegap.com/2011/05/18/debugging-phonegap-javascript/</a><br/> •<a href="http://wiki.phonegap.com/w/page/16494768/Debugging%20PhoneGap%20Apps">http://wiki.phonegap.com/w/page/16494768/Debugging%20PhoneGap%20Apps</a></p>
<h3><strong>5. 如何部署PhoneGap应用？</strong></h3>
<p>部署PhoneGap应用和创建移动设备web是一样的，唯一不同的就是PhoneGap应用程序在本地初始化HTML设置而不是远程服务器。PhoneGap应用加载初始化的HTML，它可以用来申请服务器或者本地上的资源。由于PhoneGap是基于浏览器的，可以像浏览器一样运行。你可以同时下载各种网页但是一旦你下载或者关闭一个网页很可能丢失通过JavaScript脚本存储在内存中的数据。PhoneGap也支持单页浏览模式，建议用户使用单页浏览模式。</p>
<p><strong>单页浏览模式部署</strong></p>
<p>单页浏览架构就是指只有一个HTML页基于数据和用户输入进行动态更新，你可以把它看做是客户/服务器模式，由一个客户应用和一个服务器组成。客户应用可以请求数据或者进行更新而不用重新加载web页。</p>
<p>通过使用单页浏览模式你可以维护内存中的数据。通过如下链接可以了解更多关于单页模式的知识<a href="http://en.wikipedia.org/wiki/Single-page_application">http://en.wikipedia.org/wiki/Single-page_application</a>。</p>
<p>可以利用任意常见的JS架构如Angular, Ember, Backbone, Mustache部署PhoneGap 应用。</p>
<h3><strong>6.如何使PhoneGap应用在移动设备和应用环境中运行？</strong></h3>
<p>对每一个给定的平台而言，PhoneGap应用采用和本地应用相同的规则部署，你必须遵守每一个应用平台的部署规则。你可以利用每个平台的构建过程为这个平台编译可执行文件也可以利用build.phonegap.com进行编译。build.phonegap.com是可以为每个平台编译使用时具体平台的应用的服务。构建过程的输出是适用于一个特定平台的二进制文件：适用于iOS的IPA，适用于Android的APK。通过下面链接你可以获得更多信息：</p>
<p>•iOS App Store: <a href="https://developer.apple.com/programs/ios/distribute.html">https://developer.apple.com/programs/ios/distribute.html</a><br/> •Google Android Market: <a href="https://market.android.com/publish">https://market.android.com/publish</a><br/> •Amazon App Store: <a href="https://developer.amazon.com/welcome.html">https://developer.amazon.com/welcome.html</a><br/> •BlackBerry App World: <a href="https://bdsc.webapps.blackberry.com/devzone/appworld">https://bdsc.webapps.blackberry.com/devzone/appworld</a><br/> •Barnes &amp; Nobe Nook Store: <a href="https://nookdeveloper.barnesandnoble.com/">https://nookdeveloper.barnesandnoble.com</a><br/> •Windows Phone Marketplace:<a href="http://msdn.microsoft.com/en-us/library/ff941089(v=vs.92).aspx">http://msdn.microsoft.com/en-us/library/ff941089(v=vs.92).aspx</a></p>
<h3><strong>7. PhoneGap和AIR的区别是什么？</strong></h3>
<p>PhoneGap和AIR最根本的不同就是你利用Flash平台(如Flex, Flash, ActionScript, MXML)开发AIR应用而基于HTML, CSS, &amp; JavaScript开发PhoneGap应用。AIR应用利用AIR开发环境运行，这样应用只需要一个代码基便可以在所有它支持的平台上运行，PhoneGap可以在每一个它支持的平台上的浏览器上运行。由于这个原因，不同的平台可能有不同的代码基，在开发PhoneGap应用时需要考虑这一点。</p>
<p>可以在iOS、Android、BlackBerry Playbook和desktop (mac and windows)包括上Windows Metro开发AIR应用。通过下面链接可以了解更多关于AIR支持的平台的信息。</p>
<p><a href="http://www.adobe.com/products/air/tech-specs.html">http://www.adobe.com/products/air/tech-specs.html</a></p>
<p>ActionScript动作脚本语言支持传统的继承编程模式。可以使用Flex框架构建AIR应用，这使得开发者可以快速的构建企业类应用。AIR应用中的组件是具有行为、属性和图形上下文的逻辑客体。</p>
<p>基于JavaScript的应用支持原型继承编程，有许多开源框架和工具可以被使用。HTML/JS通过HTML DOM元素实现可视化。虽然利用JavaScript模板可以创建HTML接口，但是实际上你只是创建了具有属性和模式的DOM元素。</p>
<p>虽然两者构建应用的语法不通但是基本的交互式设计和交互式开发的概念却是一直的。两个开发平台各有优缺点。</p>
<p><strong>接下来做什么？</strong></p>
<p>你可以去链接<a href="http://phonegap.com/">http://phonegap.com/</a> 下载PhoneGap并开发，当然你也可以去链接 <a href="http://phonegap.com/apps">http://phonegap.com/apps</a>查看其他人开发的应用。</p>
<p>原文链接：（英文）<a href="http://www.tricedesigns.com/2012/02/14/what-is-phonegap-other-common-questions/" target="_blank">“What is PhoneGap?” &amp; Other Common Questions</a>（中文）<a href="http://www.webapptrend.com/2012/02/1820.html">新手必读：PhoneGap入门六大问题</a></p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2012/02/phonegap%e5%85%a5%e9%97%a8%e4%b9%8b%e9%97%ae%e9%a2%98%e8%a7%a3%e8%af%bb/">PhoneGap入门之问题解读</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zhourunsheng.com/2012/02/phonegap%e5%85%a5%e9%97%a8%e4%b9%8b%e9%97%ae%e9%a2%98%e8%a7%a3%e8%af%bb/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>PhoneGap 之 Android 端插件开发</title>
		<link>http://blog.zhourunsheng.com/2011/11/phonegap-%e4%b9%8b-android-%e7%ab%af%e6%8f%92%e4%bb%b6%e5%bc%80%e5%8f%91/</link>
		<comments>http://blog.zhourunsheng.com/2011/11/phonegap-%e4%b9%8b-android-%e7%ab%af%e6%8f%92%e4%bb%b6%e5%bc%80%e5%8f%91/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 13:33:53 +0000</pubDate>
		<dc:creator><![CDATA[润物无声]]></dc:creator>
				<category><![CDATA[移动开发]]></category>
		<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[插件]]></category>

		<guid isPermaLink="false">http://blog.zhourunsheng.com/?p=1143</guid>
		<description><![CDATA[<p>前面一篇文章 《移动 APP 之跨平台解决方案》介绍了一种跨平台的解决方案，即用开发web app的方式来编写 [&#8230;]</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2011/11/phonegap-%e4%b9%8b-android-%e7%ab%af%e6%8f%92%e4%bb%b6%e5%bc%80%e5%8f%91/">PhoneGap 之 Android 端插件开发</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>前面一篇文章 《<a title="移动 APP 之跨平台解决方案" href="http://blog.zhourunsheng.com/2011/10/%e7%a7%bb%e5%8a%a8-app-%e4%b9%8b%e8%b7%a8%e5%b9%b3%e5%8f%b0%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/">移动 APP 之跨平台解决方案</a>》介绍了一种跨平台的解决方案，即用开发web app的方式来编写mobile app。鉴于PhoneGap才刚刚新起，还有许多功能因为平台的差异性无法很好的解决，所以我们在实际的开发中，发现有很多功能还需要完善，一种比较好的方式就是编写平台依赖的插件，进而扩展PhoneGap的功能。</p>
<p><img title="lunny" src="http://blog.zhourunsheng.com/wp-content/uploads/2011/11/lunny-300x133.jpg" alt="lunny" width="300" height="133" /><span id="more-1143"></span></p>
<p>本文介绍一下开发和使用插件的一个流程，以 <a href="https://github.com/phonegap/phonegap-plugins/tree/master/Android/VideoPlayer" target="_blank">VideoPlayer</a> 为例。</p>
<ol>
<li>环境搭建，下载 phonegap-android 的源码，下载地址 <a href="https://github.com/phonegap/phonegap-plugins">https://github.com/phonegap/phonegap-plugins</a></li>
<li>编写video.js，提供给web开发端的接口定义，定义了一个VideoPlayer类和play函数，参数为要播放的文件视频地址，代码如下：
<pre>/**
 * Constructor
 */
function VideoPlayer() {
};

/**
 * Starts the video player intent
 *
 * @param url           The url to play
 */
VideoPlayer.prototype.play = function(url) {
    PhoneGap.exec(null, null, "VideoPlayer", "playVideo", [url]);
};

/**
 * Load VideoPlayer
 */
PhoneGap.addConstructor(function() {
    PhoneGap.addPlugin("videoPlayer", new VideoPlayer());
});</pre>
</li>
<li>编写 Android VideoPlayer 的具体实现代码，VideoPlayer/src/com/phonegap/plugins/video/VideoPlayer.java
<pre>package com.phonegap.plugins.video;

import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
import android.net.Uri;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;

public class VideoPlayer extends Plugin {
    private static final String YOU_TUBE = "youtube.com";

    @Override
    public PluginResult execute(String action, JSONArray args, String callbackId) {
        PluginResult.Status status = PluginResult.Status.OK;
        String result = "";

        try {
            if (action.equals("playVideo")) {
                playVideo(args.getString(0));
            }
            else {
                status = PluginResult.Status.INVALID_ACTION;
            }
            return new PluginResult(status, result);
        } catch (JSONException e) {
            return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
        }
    }

    private void playVideo(String url) {
        // Create URI
        Uri uri = Uri.parse(url);

        Intent intent = null;
        // Check to see if someone is trying to play a YouTube page.
        if (url.contains(YOU_TUBE)) {
            // If we don't do it this way you don't have the option for youtube
            intent = new Intent(Intent.ACTION_VIEW, uri);
        } else {
            // Display video player
            intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "video/*");
        }

        this.ctx.startActivity(intent);
    }
}</pre>
</li>
<li>配置插件, res/xml/plugins.xml 添加如下代码
<pre>&lt;plugin name="VideoPlayer" value="com.phonegap.plugins.video.VideoPlayer"/&gt;</pre>
</li>
<li>编写代码进行调用,文件开头引入js代码框架，然后进行VideoPlayer类的play函数调用
<pre>&lt;script type="text/javascript" charset="utf-8" src="phonegap.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" charset="utf-8" src="video.js"&gt;&lt;/script&gt;

 //Sample use:
 /**
    * Display an intent to play the video.
    *
    * @param url           The url to play
    */
 //play(url)

window.plugins.videoPlayer.play("http://path.to.my/video.mp4");
window.plugins.videoPlayer.play("file:///path/to/my/video.mp4");</pre>
</li>
<li>到此为止，插件的开发和部署，以及调用就都ok了，是不是很简单( ⊙ o ⊙ )啊！</li>
</ol>
<p>最后向大家推荐一本书籍《PhoneGap Beginner's Guide》，相信通过本书的学习，就知道了怎样利用PhoneGap来开发跨平台的mobile app了，同时也可以关注<a href="https://github.com/phonegap">https://github.com/phonegap</a>项目的最新进展情况和新特性，如果可以的话，贡献自己的力量来进行完善和扩充，O(∩_∩)O~！</p>
<p><a rel="nofollow" href="http://blog.zhourunsheng.com/2011/11/phonegap-%e4%b9%8b-android-%e7%ab%af%e6%8f%92%e4%bb%b6%e5%bc%80%e5%8f%91/">PhoneGap 之 Android 端插件开发</a>，首发于<a rel="nofollow" href="http://blog.zhourunsheng.com">润物无声</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.zhourunsheng.com/2011/11/phonegap-%e4%b9%8b-android-%e7%ab%af%e6%8f%92%e4%bb%b6%e5%bc%80%e5%8f%91/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://path.to.my/video.mp4" length="151" type="video/mp4" />
		</item>
	</channel>
</rss>
