标签归档:Android

e人e本?

今天一大早来到公司,看到一个新闻“e人e本”发布了一款平板设备,如图:

 

主要功能有以下:

Mind-Note
原笔记记事本

分类手写记事,即写即发,海量存储,永远写不完。智能查询1秒完成,重要文件加密保护

Mind-Net
无线上网

支持宽带、WIFI、3G三种无线上网方式,
随时随地快速上网,查看新闻,收发邮件

Mind-Book
彩色电子书

7寸彩屏显示,1000多本内置图书、万余种书报杂志在线下载,实时更新

Mind-Mail
手写邮件

独创手写邮件功能,写什么就收到什么。
手写签名与移动审批,让办公室无处不在

Mind-Card
智能名片管理

通过外接名片扫描设备,可快速识别并收集名片信息,无限存储,随时调用

从整体的介绍来看,这款平板设备其实就是一个升级版本的PDA,有一些非常贴心的商务功能,例如外接名片扫描功能以及手写笔记本和邮件等,而且号称1秒钟开机和30天待机,10小时续航,对于有钱而对iPad类似产品不感兴趣,对于稳重设计比较有感觉的人士还是很有吸引力的,虽然价格不菲¥3980,但是我们再来看看与其一起搭配的东西。

首先不说与机器功能无关的类似于皮套之类的东西了,从内容上来说,比较丰富的应用以及众多定制的高端杂志无疑是其比较吸引人的地方。虽然目前看来官方提供的应用还比较少,不过基于Android的终端有一个天然的优势,那就是拥有众多可获取的免费应用。

image

我想也许这也是一种致胜之道呢,何况目前还有联想注资来扶持该项目,虽然我们看联想最近几年在新兴的产品竞争中很少获得比较好的成绩,不过实力还是有的,其运营和渠道以及影响力上的优势非常明显。最主要的是我们看到了一些互联网相关产品的发展,当然我们可以称其为较为优秀的山寨,不过我坚持认为Android产品不存在什么山寨一说。Android天生的开放性,注定了其未来会成为一个主流产品生态圈的基础,而经历过山寨风云的中国大陆用户在山寨拨云见雾之后,是否还会被山寨蒙住双眼,我看未必。也许,我们的小企业也能创新呢?

———————————————————————————————————

PS:听说腾讯要出手机,名为QPhone,当时办公室有人顺口一说“什么,扣粪?”,我想也许这个恶搞的名词以后可能真的在某天会成为国内互联网的热词。

《黄金矿工喜讯特别版》发布了

从加入喜讯到今天整整两个月了,期间做了一个小产品,就是《黄金矿工喜讯特别版》。

游戏的创意来源于PC上flash版本的黄金矿工,不过重新结构了游戏的可玩性和关卡的设置,并新增了一些游戏模式的东西,加入了更多的设计性的要素,特别是画面感的增强,我个人认为应该是最大的。游戏发布并没有正式的在Google的Market上发布,只是选择性的在国内的一些知名的论坛上发了一些帖子。效果还算不错,在安卓网上的帖子,下载量已经达到了1383,在机锋网的帖子 下载量目前是874,感觉都还不错,然后今天下午放上了安卓市场里面,目前下载量是141,感觉还不错。跟之前自己的预期相比,目前的结果还是比较喜人的。

官方网址是:http://m.xixun.com/hjkg

目前提供了Android和Symbian版本,支持Android 1.5及以上版本和S60 V3版本

给一些截图吧:

下载地址: http://m.xixun.com/hjkg

Android上如何正确实现程序的联网,事关WIFI/CMWAP/CMNET

我想很多Android程序开发者都曾碰到过这样的问题,那就是如何让自己的程序在国内如此复杂的网络环境下顺利的接上网络,给我们的用户一个更好的体验。
从网络上一些已有的数据来看,Android手机用户群体的联网率普遍比较高,联网的方式非常多样,最多的还是使用WIFI,当然WIFI速度和资费上的优势让她成为了每一个玩机者的首选网络接入方式,但是很多的时候我们的条件并不是那么的尽如人意。例如在公车或地铁上,我们这些诸多支付不起3G资费的人士,首选的接入方式依然是CMWAP/CMNET,而由于国内网络的一些个问题,选择这两个或者其他的APN会有一些问题,问题就是我们可能需要设置代理才可以顺利登录网络。

以下是我自己在网络上寻找解决方案的时候,收集的一些信息,记录如下:

WAP是一中手机上网的协议。CTWAP是中国电信的WAP接入名称(China Telecom WAP),CMWAP是中国移动的WAP接入名称(China Mobile WAP),  UNIWAP是联通的WAP接入名称(china Unicom WAP),  另外CTNET/CMNET/UNINET同上。
CTWAP的上网网关:10.0.0.200:80
CMWAP的上网网关:10.0.0.172:80
UNIWAP使用的网关与CMWAP一致
我们可以通过MCC+MNC码的方式来进行简单的判断,但是实际上这种方式并不是完全正确的方法(自己在项目上碰到了该问题,因为实际情况中我们总是需要面对多种网络的情况)。这个时候其实我们可以稍微Hack一下,虽然Android并没有提供非常好的API,不过我们可以通过一些方法绕过去这里有一篇非常不错的文章http://www.javaeye.com/topic/565662 ,讲解得还算全面。
下面给出我自己的解决方案:
WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
  HttpClient httpClient = new DefaultHttpClient();
  if(!wifiManager.isWifiEnabled()){
   Uri uri = Uri.parse("content://telephony/carriers/preferapn"); //获取当前正在使用的APN接入点
   Cursor mCursor = this.getContentResolver().query(uri, null, null, null, null);
   if(mCursor != null){
    mCursor.moveToNext(); //游标移至第一条记录,当然也只有一条
    String proxyStr = mCursor.getString(mCursor.getColumnIndex("proxy"));
    if(proxyStr != null && proxyStr.trim().length() > 0){
     HttpHost proxy = new HttpHost(proxyStr, 80);
     httpClient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);
    }
   }
  }
  HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), 20 * 1000);
        HttpConnectionParams.setSoTimeout(httpClient.getParams(), 20 * 1000);
        HttpGet httpGet = new HttpGet(wrapGetUrl());
 try
        {
            HttpResponse response =httpClient.execute(httpGet);
            if(response.getStatusLine().getStatusCode() == 200){
             HttpEntity entity = response.getEntity();
             InputStream content = entity.getContent();
             BufferedInputStream bis = new BufferedInputStream(content);
             StringBuilder builder = new StringBuilder();
             int b;
             while((b=bis.read()) != -1){
              builder.append((char)b);
             }
             String resultStr = builder.toString();
               Log.v("result", resultStr);
}catch(Exception e){
}finally{
httpClient.getConnectionManager().shutdown();
}
该方案在打开WIFI/CMWAP/CMNET的情况下均单独测试成功。
同理HttpPost也可以如法炮制,下面附上一段代码:
int version = 3;
  Class versionClass = VERSION.class;
  TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
  WifiManager wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
  String manufacturer = "";
  String device = "";
  String networkOperatorName = tm.getNetworkOperatorName();
  String IMEI = tm.getDeviceId();
  try {
   Field field = versionClass.getField("SDK_INT");
   version = (Integer) field.get(new VERSION());
   Class buildClass = Build.class;
   Field manu_field = buildClass.getField("MANUFACTURER");
   manufacturer = (String) manu_field.get(new android.os.Build()) + " ";
   Field deviceField = buildClass.getField("DEVICE");
   device = (String) deviceField.get(new Build());
  } catch (Exception e) {

  }
  HttpClient httpclient = new DefaultHttpClient();
  try {
   if(!wifiManager.isWifiEnabled()){
    Uri uri = Uri.parse("content://telephony/carriers/preferapn");
    Cursor mCursor = this.getContentResolver().query(uri, null, null, null, null);
    if(mCursor != null){
     mCursor.moveToNext();
     String proxyStr = mCursor.getString(mCursor.getColumnIndex("proxy"));
     if(proxyStr != null && proxyStr.trim().length() > 0){
      HttpHost proxy = new HttpHost(proxyStr, 80);
      httpclient.getParams().setParameter(ConnRouteParams.DEFAULT_PROXY, proxy);
     }
    }
   }
   HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 20 * 1000);
            HttpConnectionParams.setSoTimeout(httpclient.getParams(), 20 * 1000);
   HttpPost httppost = new HttpPost("YOUR_POST_URL");
   List nameValuePairs = new ArrayList();
   nameValuePairs.add(new BasicNameValuePair("os", "Android"));
   nameValuePairs.add(new BasicNameValuePair("os_version",String.valueOf(version)));
   nameValuePairs.add(new BasicNameValuePair("device", manufacturer+device));
   nameValuePairs.add(new BasicNameValuePair("uuid", md5(IMEI)));
   nameValuePairs.add(new BasicNameValuePair("network", networkOperatorName));
   httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
   HttpResponse response;
   response = httpclient.execute(httppost);
   httpclient.execute(httppost);
   StatusLine statusLine = response.getStatusLine();
   if(statusLine.getStatusCode() == 200){
Toast.makeText(this, R.string.updatesucceed, Toast.LENGTH_SHORT).show();
   }else{
Toast.makeText(this, R.string.updatefailed, Toast.LENGTH_SHORT).show();
   }
  } catch (UnsupportedEncodingException e) {
   e.printStackTrace();
  } catch (ClientProtocolException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }finally{
   updateFlag = true;
   httpclient.getConnectionManager().shutdown();
  }

初窥Android游戏开发

最近一个月的时间熟悉了一下Android平台上的游戏开发流程.因为游戏相对于软件来说还是有一定区别的,可能跟系统提供的大部分API关系并不是特别的大,主要使用的可能就是系统的图形和声音,以及影像相关的API了。

最初学习Android,只是跟着官方提供的文档和示例一个个地去抄,抄完了之后自己写,主要就学习了一下Activity的一些简单的知识,主要是Activity之间的通信,Activity的生命周期,以及Activity Stack等等一些。对于游戏开发几乎是0,因为之前自己做的工作主要是Java中间件开发,使用的技术是JNI,并没有太多的接触过业务逻辑,对于功能的实现和集成还是非常的生疏。此次游戏开发委实长了不少的经验啊。从对Android的基础绘图API和线程的控制,状态机的维护,资源的释放等等,不一而足啊。

下面列举一下,近来学习的一些方面:

  • SurfaceView的使用,我想这大概是Android为了游戏开发人员做的一个特殊的基类,通过继承该类,并实现SufaceHolder.CallBack接口便可,通过SurfaceHolder.lockCanvas()获取画布,之后的各种绘制操作均可在当前画布上执行(Canvas.draw()系列方法),之后使用SurfaceHolder.unlockCanvasAndPost(Canvas canvas)方法,将绘制刷新到屏幕。
  • Thread.sleep(long millis)方法中的millis是跟系统时钟相关的,并不是真正的实际的时长,所以在这里需要做一个换算,使用多次Thread.sleep(long millis)方法来探测当前的换算比是多少,然后使用自己所需要的时长乘以该比值,设置给sleep()方法,才能得到正确的效果。
  • 关于游戏配置资源的读写,在游戏中,通常会有几种资源文件,图像,声音,XML关卡数据,游戏运行时配置文件(ini/properties).声音,图像,XML文件通常只需要使用系统默认的资源管理方式即可,如果程序中不需要使用文件名来进行配置的话,但是如果需要使用“logo.png”类似的名字来进行配置的话,可能系统提供的通过资源预编译后ID的方式就并不是那么尽如人意了,通常这种情况下,可以通过AssetManager.open(String fileName)来打开assets目录下的文件,可以使用子目录只是fileName就应该是”subfolderName/filename”这种格式了。在写入配置文件时,Android 为每个应用程序都提供了一个私有目录,”file://data/data/fullpackagename/files/”目录(fullpackagename是当前应用程序所在的包名,例如com.xixun.games),通过调用Context.openFileInput(String name, int mode)和Context.openFileOutput(String name, int mode)来获取输入和输出流。
  • Bitmap相关方法将可能导致error:OutOfMemory,这个确实是在手持设备上的一个问题,Android Dalvik VM 的实现中,只给了每个应用程序8M(该数据从互联网查得,并未验证是否属实)的内存用于图形,当程序为Bitmap对象申请超过8M内存时,将会抛出该错误(不是异常)并退出程序,并没有什么非常好的方法一定能帮你解决这个问题,通常我们应该养成一种编程行为习惯,那就是在Bitmap不再使用的时候立刻将资源回收(调用Bitmap.recyle()方法),因为Bitmap的实现是系统级别的API,VM对这种对象的管理并不会那么尽如人意,所以最好还是程序自身来管理,否则在后续的开发中,如果再次加入更大的资源将极为频繁地出现该问题。那么什么时候可能会出现该问题呢?8M的内存,我什么时候可能知道内存快要用了呢?对,你不知道,我也不知道,不过我们要预防,而且自己在编程时也可以简单的计算一下,如果你使用png图片的话,1.5M,到了程序中,如果你将所有的png均转化成了Bitmap对象,那么你的程序中使用的内存就至少会使用4.5M的内存。而且如果图片还带透明效果的话,那么就可能是6M的内存了。

以上就是近期的一些学习总结。下次将分享一个关于Android应用程序访问网络的问题。

Andorid之菜鸟感观

前一阵突然想到玩一玩Android这个平台,回想当时还在大学的时候,曾经也下载过SDK,傻乎乎地折腾了一天,后来因为模拟器的问题无法解决而无果而终了。

如今再次回过头来看看当年那么年轻幼小的Android已经成为了庞然大物,众多的硬件厂商,翘首以待的运营商,数不胜数的开发人员(包括潜在的),让Android瞬时间成为了一个红得发烫的东西了。昨天lenovo发布了他们的最新款乐Phone手机,基于OMS开发的操作系统,应该和中移动的OPhone隶属于同一分支。刚刚看了keso的联想移得动吗?,跟我昨天和舍友的一番交流有较多相似之处,两年前以1亿美金出售其移动业务的联想,在今日反其昨日之道而行,所谓老马还吃回头草。自然是有他们的理由的,2008年是山寨手机最为抢手的日子,国内的手机市场中高端由国际手机制造厂商控制,而低端手机的市场被山寨机侵蚀,我们看到了波导的关门,联想的退出,中兴和华为退出品牌市场为他人做嫁衣裳,也许这就是当时联想的原因。而今天,山寨已经逐渐降温,走出国内走向世界了,出口第三世界的国家,山寨在赤道附近形成了的一道美丽的风景线。由iPhone主导的智能手机市场已经逐渐形成,国内智能机的消费群体和市场已经形成,但是鉴于咱们国家的诸多政策,iPhone以及其他优秀的产品很难在国内这个生态中生存,只能借着水货商家的一根根小水管养活了国内一些饥渴症患者。在这个时候,其实国内已经有了一个很好的消费空间和氛围,但是国内暂时没有什么能拿得出手的设备,经常宕机的魅族虽说是国产,但是也不能因为你是亲兄弟的产品就老死机啊。

再次进入市场的联想,选择了一个很好的时机,而且是在中移动推出OPhone之后,OMS的逐渐成熟和衍生,无疑给联想扫清了很多的道路。那么联想选择Android这个平台自然也是有它的理由的,当然我想最大的莫过于这个东西不要钱,拿来就能用,如果愿意还可以掏点钱,跟Google签订OEM的诸多协议,拿到私有分支的代码和API。关于Google Androd开源的两三事,可以参考最封闭的开源系统,话说Andorid的八宗罪

======================================

回到话题,这几日初步研究了一下Android,根据它的Tutorials学习了几个示范程序,然后看了一下SDK包中的Samples目录下的几个程序,感觉良好。

首先,Android的开发完全是面向Java的,与平台实际没有太多相关性,因为Google又一次很聪明的选择了一个已有的强大的平台来推广自己的产品,使用Linux Kernel+Java+API机制,几近完美的俘获了大部分开发人员的心,Android的开发门槛非常之低,你完全可以在你的PC上开发,Windows和Linux皆可,如果你再时尚一些,Mac OS系列也是没有问题的。不像iPhone那般,你必须有了小白之后才能开始你的开发,而且你得重新开始学习一门名为Objective-C的语言,也许之前你都没有听说过的一门语言。Android使用JNI机制,提供Java语法的API让诸多Java程序员直接成为了Android underlying developer。而且在金融危机的这一段时间,IT行业失业现象还是较为严重的,离开了企业的开发者完全可以在自己家中开始自己SOHO生活了。

其次,IDE的友好性,eclipse的ADT插件用起来真的很爽,能解决你绝大部分的问题(当然现在我还没哟遇到什么很棘手的问题),DDMS Perspective下强大的Log系统,和模拟器完美的结合能让你迅速的定位到问题的所在和异常信息。另外模拟器的高度可定制化,也是不错的,在新建模拟器时可以指定是否模拟SD Card,Touch-Screen等等。

第三,文档的丰满。总是感叹别人的产品为何就能做得这么成功,开发人员拿起文档就能直接开始干活了,这就是境界啊!虽然有些文档也存在错误,例如实例中的NotepadV2中就有一个明显的错误,关于Intent的返回值为RESULT_OK明显是错误的,因为调用这个Intent对象的NotepadV2自己定义了其需要的返回值为ACTIVITY_CREATE和ACTIVITY_EDIT,不过调试一下就能发现问题所在了,孰能无过呢。

最后,让我感觉非常不爽的一点是,我们国家的开发人员申请不了Dev Phone,杯具啊!

说了这么多,接下来该好好学习了。Android, I’m comming, Hello Android World!

http://blog.donews.com/keso/archive/2010/04/20/1583526.aspx联想以