大树的Blog

.NET 爱好者,android爱好者。

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  214 随笔 :: 1 文章 :: 16 评论 :: 0 引用

2011年7月19日 #

摘要: Linux命令整理 Linux提供了大量的命令,利用它可以有效地完成大量的工作,如磁盘操作、文件存取、目录操作、进程管理、文件权限设定等。所以,在Linux系统上工作离不开使用系统提供的命令。要想真正理解Linux系统,就必须从Linux命令学起,通过基础的命令学习可以进一步理解Linux系统。不同Linux发行版的命令数量不一样,但Linux发行版本最少的命令也有200多个。这里笔者把比较重要和使用频率最多的命令,按照它们在系统中的作用分成下面六个部分一一介绍。本文主要参考曹元其先生的《Linux必学的60个命令》。◆ 安装和登录命令:login、shutdown、halt、reboot、i阅读全文
posted @ 2011-07-19 16:52 大树2 阅读(163) 评论(0) 编辑

掌握Linux编程的10个步骤 转载

做linux c语言开发有一小阵子了,在这边自己总结了些心得,相信能让不懂得Linux编程的人慢慢步入Linux殿堂。有任何不对或不准确之处欢迎讨论。

1. 安装 linux 操作系统

既然要学习linux下的c语言开发,那么安装个linux操作系统是必须的。建议安装Ubuntu,这是我目前见过界面最友好的linux操作系统了。关于如何使用Ubuntu以及在其上作开发,可参考我的另外一篇敝作《Ubuntu使用心得》:http://download.csdn.net/source/2206289

2. 熟悉 linux 操作系统下的命令

Linux提供了大量的命令,利用它可以有效地完成大量的工作,如磁盘操作、文件存取、目录操作、进程管理、文件权限设定等。所以,在Linux系统上工作离不开使用系统提供的命令。要想真正理解Linux系统,就必须从Linux命令学起,通过基础的命令学习可以进一步理解Linux系统。

关于linux下的命令,欢迎参考我blog上一篇文章《Linux命令整理》:http://blog.csdn.net/sikinzen/archive/2010/04/19/5503769.aspx

3. 学会一种源码编辑器

很多大牛推荐使用 vim/emacs之类的工具,但我还是用着不习惯,应该是我能力未到。我个人比较喜欢的开发方式是:在windows下编辑代码,在linux下编译。

我自己非常喜欢用SourceInsight来编辑代码,这个工具的使用可参考我blog上一篇文章《Source Insight的应用技巧、宏功能》:http://blog.csdn.net/sikinzen/archive/2010/04/09/5468511.aspx

4. 掌握gcc和gdb

掌握gcc的基本用法,并且会用gdb来调试程序。

5. 用好 C 语言

工作中发现:C语言大家都会,但核心思想就不一定都能理会。我自己觉得也只是摸到了门径,还需要实践锻炼。

推荐:《C陷阱与缺陷》、《C专家编程》、《C程序设计语言》。

6. 学会写makefile,以及用它来组织源码

当项目大了后,用命令行逐个逐个编译、link文件的工作量是非常恐怖的,这时候make就起作用,即使是很小的项目,我认为也应该采用make组织。

关于makefile,请参考网上文章《跟我一起写Makefile》或《GNU make中文手册》。这两篇文章都相当得好。

7. Linux应用编程

终于说到正题了,呵呵。

Linux上的应用编程基本上两本书就搞定了:《APUE》和《UNP》,前者锻炼基本功,后者学习网络编程。

这边我直接引用网上某位先生的评论:

如果想学习UNIX/LINUX的编程,《APUE》绝对经典的教材,加深一下功底,学习《UNP》的第二卷。这样基本上系统方面的就可以掌握了。 然后再看Douglus E. Comer的《用TCP/IP进行网际互连》第一卷,学习一下网络的知识,再看《UNP》的第一卷,不仅学习网络编程,而且对系统编程的一些常用的技巧就很熟悉了,如果继续网络编程,建议看《TCP/IP进行网际互连》的第三卷,里面有很多关于应用协议telnet、ftp等协议的编程。

8. Linux驱动与内核编程
驱动程序的门槛较高,首先你要学会Linux应用编程,至少看过《APUE》。

驱动编程的主要工作我认为至少有两点:理解linux内核框架和模块的概念、懂得看芯片datasheet。

第一点其实就是先学会编写一个测试驱动程序。

推荐经典教材:《linux设备驱动程序》。

另外,还有 《深入理解Linux内核》。

最重要的是:手头要有一块嵌入式板子进行实践。

9. 掌握一种 cvs 工具

如果不懂cvs的话,赶紧到 baidu 搜索下。不用cvs的项目很容易面临代码丢失的问题,且不易做bug回归。

10. 数据结构和算法

上过计算机基础课的人都知道:程序=数据结构+算法。这两项才是程序员的根本,如同武侠小说中的“内功”。  有时间的话建议重温这两部分。推荐书籍:《Algorithms in C》、《算法导论》

呵呵,其实这一小块我没有发言权,我自己是从自动化专业转行来写程序的,数据结构和算法都没学过,目前正在自学恶补中。

 

后记:

通过上面几个步骤,我想成为一个称职的linux程序员是没问题了。但如果要成为专家的话,我自己觉得还应该为自己选好方向并努力前进。

让我们一块努力!

posted @ 2011-07-19 16:48 大树2 阅读(215) 评论(0) 编辑

2011年7月4日 #

1、如何在一个按钮上放上一张图片?
把按钮和图片套在一个FrameLayout中

<!-- 必须将button和ImageView分别嵌套在两个LinearLayout中才能 实现将图片放在按钮上 -->
   <FrameLayout
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <LinearLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
     <Button
      style="@style/menu_btn_style"
      android:id="@+id/fan_us"
      android:text="@string/mainmenu_facebook_fan_us" />
    </LinearLayout>
    <LinearLayout
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
     <ImageView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginLeft="16dp"
      android:layout_marginTop="13dp"
      android:src="@drawable/facebookicon" />
    </LinearLayout>
   </FrameLayout>
   
   
   
2、如何自定义组件
自定义一个下划线形式的输入框

第一:确定要画多少条下划线
第二:每条线的宽度
第三:下划线的间距

(1)自定义文本输入框
package com.heima.guesswho.util;

import com.heima.android.guesswho.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.EditText;

public class DashlineEditText extends EditText {
 /*
  * 假设下划线总长100个单位,要画7条下划线,每条下划线间距为2个单位
  * 具体算法如下:
  * 每条下划线的长度:(100+2)/7-2
  * for(int i = 0;i<7,i++){
  *     第i条线
  *   x1 = ((100+2)/7)*i
  *   y1 = getHeight()
  *   x2 = ((100+2)/7)*i+(100+2)/7-2
  *   y2 = getHeight()
  * }
  *
  */
 
 private Paint linePaint = new Paint();
 private  int segmentCount = 8;//总共画8条分割线,可以作为默认值
 private  int distance = 5;//每个分割线的间距为4个单位,可以作为默认值
 
 /*
  * 从布局文件中得到对应属性的值
  */
 public DashlineEditText(Context context, AttributeSet attrs) {
  super(context, attrs);
  setBackgroundDrawable(null);//消除文本框效果的作用
  //linePaint.setColor(Color.RED);//设置画笔的颜色
  
  TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DashLineET);
  segmentCount = array.getInt(R.styleable.DashLineET_segment_count, segmentCount);//从指定属性中拿到对应的值,若没设置,则用默认值
  distance = array.getInt(R.styleable.DashLineET_distance, distance);
  int color = array.getInt(R.styleable.DashLineET_dashline_color, Color.RED);
  linePaint.setColor(color);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  int width = getWidth();//自定义控件的宽度
  int height = getHeight()-3;//必须减去数才能显示出下划线
  
  //画出每一条下划线
  for(int i = 0; i < segmentCount; i++){
   int oneSegmentWidth = (width+distance)/segmentCount - distance;//每条下划线的长度
   int startX = (segmentCount+distance)*i ;//每条下划线的起点位置
   int stopX = startX+oneSegmentWidth ;//每条下划线的终点位置
   canvas.drawLine(startX, height, stopX, height, linePaint);
  }  
 }
}


(2)布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/debug_name" />

 <com.heima.guesswho.util.DashlineEditText
  android:layout_width="100dp"
  android:layout_height="12dp"
  android:text="test" />
</LinearLayout>


定义自定义组件的属性

第一步:在string.xml文件中配置declare-styleable

   <!-- 定义DashLineEditText的属性 -->
 <declare-styleable
  name="DashLineET">
  <attr
   name="segments_cnt"
   format="integer" />
  <attr
   name="distance"
   format="dimension" />
  <attr
   name="dashline_color"
   format="color" />
  <attr
   name="hint_msg"
   format="reference" />
  <attr
   name="hint_color"
   format="color" />
 </declare-styleable>
 
第二步:在自定义组件中复写构造方法,用来获取布局文件中属性的值

 
 /*
  * 从布局文件中得到对应属性的值
  */
 public DashlineEditText(Context context, AttributeSet attrs) {
  super(context, attrs);
  setBackgroundDrawable(null);//消除文本框效果的作用
  //linePaint.setColor(Color.RED);//设置画笔的颜色
  
  TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DashLineET);
  segmentCount = array.getInt(R.styleable.DashLineET_segment_count, segmentCount);//从指定属性中拿到对应的值,若没设置,则用默认值
  distance = array.getInt(R.styleable.DashLineET_distance, distance);
  int color = array.getInt(R.styleable.DashLineET_dashline_color, Color.RED);
  linePaint.setColor(color);
 }

 


第三步:在使用自定义组件的布局文件中加入命名空间

如xmlns:heima="http://schemas.android.com/apk/res/com.heima.android.guesswho"


heima 为我们使用属性时使用的前缀,相当于使用Android属性时要使用android前缀一样
其中com.heima.android.guesswho,为清单文件标识应用的包名

布局文件如下


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:heima="http://schemas.android.com/apk/res/com.heima.android.guesswho"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 <TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/debug_name" />

 <com.heima.guesswho.util.DashlineEditText
  android:layout_width="100dp"
  android:layout_height="12dp"
  heima:segment_count="10"
  heima:distance="3"
  android:text="test" />
</LinearLayout>
  


 <com.heima.guesswho.util.DashlineEditText
    android:layout_width="210dip"
   heima:segment_count="9"
    heima:distance="4dip"
    heima:dashline_color="@color/font_white"
    android:layout_height="wrap_content"
    android:textColor="#FF0000"
    android:hint="@string/input_name_prompt"
    android:text="" />

posted @ 2011-07-04 16:10 大树2 阅读(81) 评论(0) 编辑

android手机拨号器,以及短信发送器的简单实现

其中本例中的手机拨号器并不是我们自己完全去实现,而是通过intent让android系统自带的拨号器去实现拨号的功能,

一、电话拨号器

 

第一步:对资源文件夹values中的string.xml文件进行配置,(在应用程序中需用到的字符串资源如button按钮上的名字、TextView中的内容都在此定义,然后再布局文件中可以进行使用)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, PhoneActivity!</string>
    <string name="app_name">电话拨号器</string>
    <string name="textview_name">请输入电话号码</string>
    <string name="button_name">拨号</string>
</resources>


第二步:对资源中布局文件夹下的main.xml文件进行配置,该文件控制Activity的布局


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
 <TextView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/textview_name"
    />
    <EditText 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
   android:id="@+id/edittext_id"
    />
    <Button
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/button_name"
   android:id="@+id/button_id"
    />
</LinearLayout>

第三步:实现包含业务逻辑的具体的Activity

package com.heima.phone;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class PhoneActivity extends Activity {
 EditText editText;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        editText = (EditText) this.findViewById(R.id.edittext_id);
        Button button = (Button) this.findViewById(R.id.button_id);
        button.setOnClickListener(new PhoneListener());
    }
   
    private final class PhoneListener implements View.OnClickListener{
     /*
      *<action android:name="android.intent.action.CALL" />
      *<category android:name="android.intent.category.DEFAULT" />
      *<data android:scheme="tel" />
      */
  @Override
  public void onClick(View v) {
   String telephone = editText.getText().toString();
   Intent intent = new Intent();
   intent.setAction("android.intent.action.CALL");
   intent.setData(Uri.parse("tel:"+telephone));
   startActivity(intent);// 隐式注册android.intent.category.DEFAULT,因此无需显示调用intent.setAction("android.intent.action.CALL");
  }
     
    }
}

二、短信发送器

第一步:配置资源文件string.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, SMSActivity!</string>
    <string name="app_name">短信发送器</string>
    <string name="telephone_number">请输入手机号码</string>
    <string name="sms_content">请输入短信内容</string>
    <string name="buttonname">发送短信</string>
    <string name="show">发送成功</string>
</resources>

第二步:配置布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
 <TextView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/telephone_number"
    />
   
    <EditText
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/phone_id"
    />
  
    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/sms_content"
    />
   
    <EditText
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:maxLines="3"
    android:id="@+id/sms_id"
    />
   
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/button_id"
    />
</LinearLayout>

第三步:实现Activity

package com.heima.sms;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.telephony.gsm.SmsManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class SMSActivity extends Activity {
 EditText phone;
 EditText sms;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        phone = (EditText) this.findViewById(R.id.phone_id);
        sms = (EditText) this.findViewById(R.id.sms_id);
        Button button = (Button) this.findViewById(R.id.button_id);
        button.setOnClickListener(new SMSListener());
    }
   
    private final class SMSListener implements View.OnClickListener{

  @Override
  public void onClick(View v) {
   String phoneNumber = phone.getText().toString();
   String smscontent = sms.getText().toString();
   //得到短信管理器
   SmsManager manager = SmsManager.getDefault();
   //divideMessage方法用于分割内容过长的短信
   ArrayList<String> contents = manager.divideMessage(smscontent);
   for(String content:contents){
    /* 各个参数的含义
     * destinationAddress 短信接收者号码、
     * scAddress 短信转发中心号码,一般为默认为null即可
     * text 短信内容sentIntent 不太清楚,暂时设为null   
     * deliveryIntent 不太清楚,暂时设为null
     */
    manager.sendTextMessage(phoneNumber, null, content, null, null);
   }
   //不要忘记写show方法,否则没有信息发送状态提示,Toast.LENGTH_LONG标示显示时间稍长
   Toast.makeText(getApplicationContext(), R.string.show, Toast.LENGTH_LONG).show();
  }
     
     
    }
}

 

特别注意在短信发送器的例子中一定要注意在AndroidManifest.xml文件中配置属性,
<uses-permission android:name="android.permission.SEND_SMS"/>
否则老是报程序异常终止异常

posted @ 2011-07-04 16:06 大树2 阅读(61) 评论(0) 编辑

android.os.Environment

提供访问环境变量  

java.lang.Object

android.os.Environment  

 

Environment 静态方法:

  方法 : getDataDirectory ()

返回 : File 

解释 : 返回Data的目录 

 

方法 : getDownloadCacheDirectory ()

返回 : File

解释 : 返回下载缓冲区目录

方法 : getExternalStorageDirectory ()

返回 : File

解释 : 返回扩展存储区目录(SDCard)


方法 : getExternalStoragePublicDirectory (String type)

返回 : File

解释 : 返回一个高端的公用的外部存储器目录来摆放某些类型的文件(来自网上) 

方法 : getRootDirectory ()

返回 : File

解释 : 返回Android的根目录

方法 : getExternalStorageState ()

返回 : String

解释 : 返回外部存储设备的当前状态  

 

 

getExternalStorageState () 返回的状态String 类型常量 :

常量 : MEDIA_BAD_REMOVAL

值    : "bad_removal"

解释 : 在没有正确卸载SDCard之前移除了 

常量 : MEDIA_CHECKING

值    : "checking"

解释 : 正在磁盘检查

 

常量 : MEDIA_MOUNTED

值    : "mounted"

解释 : 已经挂载并且拥有可读可写权限

 

常量 : MEDIA_MOUNTED_READ_ONLY

值    : "mounted_ro"

解释 : 已经挂载,但只拥有可读权限

 

常量 : MEDIA_NOFS

值    : "nofs"

解释 : 对象空白,或者文件系统不支持

 

常量 : MEDIA_REMOVED

值    : "removed"

解释 : 已经移除扩展设备

 

常量 : MEDIA_SHARED

值    : "shared"

解释 : 如果SDCard未挂载,并通过USB大容量存储共享

 

常量 : MEDIA_UNMOUNTABLE

值    : "unmountable"

解释 : 不可以挂载任何扩展设备

 

常量 : MEDIA_UNMOUNTED

值    : "unmounted"

解释 : 已经卸载

使用时只需先判断SDCard当前的状态然后取得SdCard的目录即可(见源代码)

---------------------------------------------------------------------------------------------------------

  1. //SDcard 操作  
  2. ublic void SDCardTest() {  
  3. // 获取扩展SD卡设备状态  
  4. String sDStateString = android.os.Environment.getExternalStorageState();  
  5.   
  6. // 拥有可读可写权限  
  7. if (sDStateString.equals(android.os.Environment.MEDIA_MOUNTED)) {  
  8.   
  9.     try {  
  10.   
  11.         // 获取扩展存储设备的文件目录  
  12.         File SDFile = android.os.Environment  
  13.                 .getExternalStorageDirectory();  
  14.   
  15.         // 打开文件  
  16.         File myFile = new File(SDFile.getAbsolutePath()  
  17.                 + File.separator + "MyFile.txt");  
  18.   
  19.         // 判断是否存在,不存在则创建  
  20.         if (!myFile.exists()) {  
  21.             myFile.createNewFile();  
  22.         }  
  23.   
  24.         // 写数据  
  25.         String szOutText = "Hello, World!";  
  26.         FileOutputStream outputStream = new FileOutputStream(myFile);  
  27.         outputStream.write(szOutText.getBytes());  
  28.         outputStream.close();  
  29.   
  30.     } catch (Exception e) {  
  31.         // TODO: handle exception  
  32.     }// end of try  
  33.   
  34. }// end of if(MEDIA_MOUNTED)  
  35. // 拥有只读权限  
  36. else if (sDStateString  
  37.         .endsWith(android.os.Environment.MEDIA_MOUNTED_READ_ONLY)) {  
  38.   
  39.     // 获取扩展存储设备的文件目录  
  40.     File SDFile = android.os.Environment.getExternalStorageDirectory();  
  41.   
  42.     // 创建一个文件  
  43.     File myFile = new File(SDFile.getAbsolutePath() + File.separator  
  44.             + "MyFile.txt");  
  45.   
  46.     // 判断文件是否存在  
  47.     if (myFile.exists()) {  
  48.         try {  
  49.   
  50.             // 读数据  
  51.             FileInputStream inputStream = new FileInputStream(myFile);  
  52.             byte[] buffer = new byte[1024];  
  53.             inputStream.read(buffer);  
  54.             inputStream.close();  
  55.   
  56.         } catch (Exception e) {  
  57.             // TODO: handle exception  
  58.         }// end of try  
  59.     }// end of if(myFile)  
  60. }// end of if(MEDIA_MOUNTED_READ_ONLY)  
  61. // end of func  

计算SDCard的容量大小

android.os.StatFs

一个模拟linux的df命令的一个类,获得SD卡和手机内存的使用情况  

java.lang.Object

android.os.StatFs

 

构造方法:

StatFs (String path)

 

公用方法: 

方法 : getAvailableBlocks ()

返回 : int

解释 :返回文件系统上剩下的可供程序使用的块

 

方法 : getBlockCount ()

返回 : int

解释 : 返回文件系统上总共的块

 

方法 : getBlockSize ()

返回 : int

解释 : 返回文件系统 一个块的大小单位byte

 

方法 : getFreeBlocks ()

返回 : int

解释 : 返回文件系统上剩余的所有块 包括预留的一般程序无法访问的

 

方法 : restat (String path)

返回 : void

解释 : 执行一个由该对象所引用的文件系统雷斯塔特.(Google翻译)


想计算SDCard大小和使用情况时, 只需要得到SD卡总共拥有的Block数或是剩余没用的Block数,再乘以每个Block的大小就是相应的容量大小了单位byte.(见代码)  

Java代码 
  1.     public void SDCardSizeTest() {  
  2.   
  3. // 取得SDCard当前的状态  
  4. String sDcString = android.os.Environment.getExternalStorageState();  
  5.   
  6. if (sDcString.equals(android.os.Environment.MEDIA_MOUNTED)) {  
  7.   
  8.     // 取得sdcard文件路径  
  9.     File pathFile = android.os.Environment  
  10.             .getExternalStorageDirectory();  
  11.   
  12.     android.os.StatFs statfs = new android.os.StatFs(pathFile.getPath());  
  13.   
  14.     // 获取SDCard上BLOCK总数  
  15.     long nTotalBlocks = statfs.getBlockCount();  
  16.   
  17.     // 获取SDCard上每个block的SIZE  
  18.     long nBlocSize = statfs.getBlockSize();  
  19.   
  20.     // 获取可供程序使用的Block的数量  
  21.     long nAvailaBlock = statfs.getAvailableBlocks();  
  22.   
  23.     // 获取剩下的所有Block的数量(包括预留的一般程序无法使用的块)  
  24.     long nFreeBlock = statfs.getFreeBlocks();  
  25.   
  26.     // 计算SDCard 总容量大小MB  
  27.     long nSDTotalSize = nTotalBlocks * nBlocSize / 1024 / 1024;  
  28.   
  29.     // 计算 SDCard 剩余大小MB  
  30.     long nSDFreeSize = nAvailaBlock * nBlocSize / 1024 / 1024;  
  31. }// end of if  
  32. // end of func  
posted @ 2011-07-04 16:04 大树2 阅读(173) 评论(0) 编辑

2011年6月30日 #

android 之互联网应用

 

1> socket;

2> url;

3> http;

4> httpurlconnection;

5> apache http;

6> webview & javascript;

7> wifi无线传输;

8> 蓝牙无线传输.

 

 

1> socket介绍,用法

Socket通常也称做”套接字“,用于描述IP地址和端口,废话不多说,它就是网络通信过程中端点的抽象表示。值得一提的是,Java在包java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。这是两个封装得非常好的类,使用起来很方便!

    下面将首先创建一个SocketServer的类作为服务端如下,该服务端实现了多线程机制,可以在特定端口处监听多个客户请求,一旦有客户请求,Server总是会创建一个服务纯种来服务新来的客户,而自己继续监听。程序中accept()是一个阻塞函数,所谓阻塞性方法就是说该方法被调用后将等待客户的请求,直到有一个客户启动并请求连接到相同的端口,然后accept()返回一个对应于客户的Socket。这时,客户方和服务方都建立了用于通信的Socket,接下来就是由各个Socket分别打开各自的输入、输出流。

  • SocketServer类,服务器实现:
1 package HA.Socket;
2
3 import java.io.*;
4 import java.net.*;
5
6  public class SocketServer {
7
8 ServerSocket sever;
9
10 public SocketServer(int port){
11 try{
12 sever = new ServerSocket(port);
13 }catch(IOException e){
14 e.printStackTrace();
15 }
16 }
17
18 public void beginListen(){
19 while(true){
20 try{
21 final Socket socket = sever.accept();
22
23 new Thread(new Runnable(){
24 public void run(){
25 BufferedReader in;
26 try{
27 in = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
28 PrintWriter out = new PrintWriter(socket.getOutputStream());
29 while (!socket.isClosed()){
30 String str;
31 str = in.readLine();
32 out.println("Hello!world!! " + str);
33 out.flush();
34 if (str == null || str.equals("end"))
35 break;
36 System.out.println(str);
37 }
38 socket.close();
39 }catch(IOException e){
40 e.printStackTrace();
41 }
42 }
43 }).start();
44 }catch(IOException e){
45 e.printStackTrace();
46 }
47 }
48 }
49 }
  • SocketClient类,客户端实现:
1 package HA.Socket;
2
3 import java.io.*;
4 import java.net.*;
5
6  public class SocketClient {
7 static Socket client;
8
9 public SocketClient(String site, int port){
10 try{
11 client = new Socket(site,port);
12 System.out.println("Client is created! site:"+site+" port:"+port);
13 }catch (UnknownHostException e){
14 e.printStackTrace();
15 }catch (IOException e){
16 e.printStackTrace();
17 }
18 }
19
20 public String sendMsg(String msg){
21 try{
22 BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
23 PrintWriter out = new PrintWriter(client.getOutputStream());
24 out.println(msg);
25 out.flush();
26 return in.readLine();
27 }catch(IOException e){
28 e.printStackTrace();
29 }
30 return "";
31 }
32 public void closeSocket(){
33 try{
34 client.close();
35 }catch(IOException e){
36 e.printStackTrace();
37 }
38 }
39 public static void main(String[] args) throws Exception{
40
41 }
42
43 }

    接下来就是来测试Socket通信了!

   先运行TestSocketServer类,打开服务端,在12345端口处监听!

1 package HA.Socket;
2
3  public class TestSocketServer {
4
5 public static void main(String[] argvs){
6 SocketServer server = new SocketServer(12345);
7 server.beginListen();
8 }
9 }

   再运行TestSocketClient类:

1 package HA.Socket;
2
3  public class TestSocketClient {
4
5 public static void main(String[] args){
6
7 SocketClient client = new SocketClient("127.0.0.1",12345);
8 System.out.println(client.sendMsg("nimei1"));
9 client.closeSocket();
10
11 SocketClient client1 = new SocketClient("127.0.0.1",12345);
12 System.out.println(client1.sendMsg("nimei1111"));
13 client1.closeSocket();
14
15 SocketClient client11 = new SocketClient("127.0.0.1",12345);
16 System.out.println(client11.sendMsg("nimei11111111"));
17 client11.closeSocket();
18
19 SocketClient client111 = new SocketClient("127.0.0.1",12345);
20 System.out.println(client111.sendMsg("nimei11111111111111111"));
21 client111.closeSocket();
22
23 }
24 }

 输出结果如下:

服务端:

Client is created! site:127.0.0.1 port:12345
Hello
!world!! nimei1
Client
is created! site:127.0.0.1 port:12345
Hello
!world!! nimei1111
Client
is created! site:127.0.0.1 port:12345
Hello
!world!! nimei11111111
Client
is created! site:127.0.0.1 port:12345
Hello
!world!! nimei11111111111111111

客户端:

nimei1
nimei1111
nimei11111111
nimei11111111111111111

 

 

2> url ,urlconnection,httpurlconnection,  Android通过URL获取网络资源

 

 url.OpenConnection()可以创建URLConnection实例也可以创建HttpURLConnection实例.

有GET,POST获取数据方式.

 

由于访问网络,所以要在AndroidManifest.xml中加入访问因特网服务的权限

<uses-permission android:name="android.permission.INTERNET" /> 

如果不加入的话,就会出现permission denied的异常

 

1、首先,我们需要URL类,表示我们要获取内容的网址

URL myURL=new URL(HTTP://www.baidu.com/hello.txt);

2、同时,用类URLConnection表示一个打开的网络连接

URLConnection ucon=myURL.openConnection();

3、对于从网络上读到的数据,用字节流的形式表示

InputStream is=ucon.getInputStream();

为了避免频繁读取字节流,提高读取效率,用BufferedInputStream缓存读到的字节流

InputStream is=ucon.getInputStream();

BufferedInputStream bis=new BufferedInputStream(is);

4、准备好BufferdInputStream后,我们就可以用read方法读入网络数据

 ByteArrayBuffer baf=new ByteArrayBuffer(50);
         int current=0;
         while((current=bis.read())!=-1)


         {
          baf.append((byte)current);
         }
5、由于读到的数据只是字节流,无法直接显示到屏幕上,所以我们得在显示之前将字节流转换为可读取的字符串

myString=EncodingUtils.getString(baf.toByteArray(),"UTF-8");

如果读取的是.txt等文件是UTF-8格式的,就需要对数据进行专门的转换

 

//定义获取文件内容的URL
         URL myURL=new URL("http://baike.baidu.com/view/46765.htm");
         //打开URL链接
         URLConnection ucon=myURL.openConnection();
         //使用InputStream,从URLConnection读取数据
         InputStream is=ucon.getInputStream();
         BufferedInputStream bis=new BufferedInputStream(is);
         //用ByteArrayBuffer缓存
         ByteArrayBuffer baf=new ByteArrayBuffer(50);
         int current=0;
         while((current=bis.read())!=-1)
         {
          baf.append((byte)current);
         }
         //将缓存的内容转化为String,用UTF-8编码
         myString=EncodingUtils.getString(baf.toByteArray(), "UTF-8");
        }catch(Exception e)
        {
         myString=e.getMessage();
        }
        //设置屏幕显示
        tv.setText(myString);
        this.setContentView(tv);

 

 

 

6> webview.浏览器

 

这里我们初步体验一下在android是使用webview浏览网页,在SDK的Dev Guide中有一个WebView的简单例子 。

在开发过程中应该注意几点:
    1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错误。
    2.如果访问的页面中有Javascript,则webview必须设置支持Javascript。
        webview.getSettings().setJavaScriptEnabled(true); 
    3.如果页面中链接,如果希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖 webview的WebViewClient对象。

mWebView.setWebViewClient(new WebViewClient(){       
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {       
                        view.loadUrl(url);       
                        return true;       
                    }       
        });  
mWebView.setWebViewClient(new WebViewClient(){    
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {    
                        view.loadUrl(url);    
                        return true;    
                    }    
        }); 

 4.如果不做任何处理,浏览网页,点击系统“Back”键,整个Browser会调用finish()而结束自身,如果希望浏览的网 页回退而不是推出浏览器,需要在当前Activity中处理并消费掉该Back事件。

public boolean onKeyDown(int keyCode, KeyEvent event) {       
        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {       
            mWebView.goBack();       
                   return true;       
        }       
        return super.onKeyDown(keyCode, event);       
    }    
public boolean onKeyDown(int keyCode, KeyEvent event) {    
        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {    
            mWebView.goBack();    
                   return true;    
        }    
        return super.onKeyDown(keyCode, event);    
    }  
 

下一步让我们来了解一下android中webview是如何支持javascripte自定义对象的,在w3c标准中js有 window,history,document等标准对象,同样我们可以在开发浏览器时自己定义我们的对象调用手机系统功能来处理,这样使用js就可以 为所欲为了。

  看一个实例:

view plaincopy to clipboardprint?
public class WebViewDemo extends Activity {        
    private WebView mWebView;       
    private Handler mHandler = new Handler();       
       
    public void onCreate(Bundle icicle) {       
        super.onCreate(icicle);       
        setContentView(R.layout.webviewdemo);       
        mWebView = (WebView) findViewById(R.id.webview);       
        WebSettings webSettings = mWebView.getSettings();       
        webSettings.setJavaScriptEnabled(true);       
        mWebView.addJavascriptInterface(new Object() {       
            public void clickOnAndroid() {       
                mHandler.post(new Runnable() {       
                    public void run() {       
                        mWebView.loadUrl("javascript:wave()");       
                    }       
                });       
            }       
        }, "demo");       
        mWebView.loadUrl("http://www.cnblogs.com/csj007523/admin/file:///android_asset/demo.html");       
    }       
}  
public class WebViewDemo extends Activity {     
    private WebView mWebView;    
    private Handler mHandler = new Handler();    
    
    public void onCreate(Bundle icicle) {    
        super.onCreate(icicle);    
        setContentView(R.layout.webviewdemo);    
        mWebView = (WebView) findViewById(R.id.webview);    
        WebSettings webSettings = mWebView.getSettings();    
        webSettings.setJavaScriptEnabled(true);    
        mWebView.addJavascriptInterface(new Object() {    
            public void clickOnAndroid() {    
                mHandler.post(new Runnable() {    
                    public void run() {    
                        mWebView.loadUrl("javascript:wave()");    
                    }    
                });    
            }    
        }, "demo");    
        mWebView.loadUrl("http://www.cnblogs.com/csj007523/admin/file:///android_asset/demo.html");    
    }    

我们看addJavascriptInterface(Object obj,String interfaceName)这个方法,该方法将一个java对象绑定到一个javascript对象中,javascript对象名就是 interfaceName(demo),作用域是Global。这样初始化webview后,在webview加载的页面中就可以直接通过 javascript:window.demo访问到绑定的java对象了。来看看在html中是怎样调用的。

<html>       
        <mce:script language="javascript"><!--     
       
                function wave() {       
                    document.getElementById("droid").src="android_waving.png";       
                }       
             
// --></mce:script>       
        <body>       
            <a onClick="window.demo.clickOnAndroid()">       
                                <img id="droid" src="android_normal.png" mce_src="android_normal.png"/><br>       
                                Click me!       
            </a>       
        </body>       
</html>     
<html>    
        <mce:script language="javascript"><!--  
    
                function wave() {    
                    document.getElementById("droid").src="android_waving.png";    
                }    
          
// --></mce:script>    
        <body>    
            <a onClick="window.demo.clickOnAndroid()">    
                                <img id="droid" src="android_normal.png" mce_src="android_normal.png"/><br>    
                                Click me!    
            </a>    
        </body>    
</html>    

这样在javascript中就可以调用java对象的clickOnAndroid()方法了,同样我们可以在此对象中定义很多方法(比 如发短信,调用联系人列表等手机系统功能。),这里wave()方法是java中调用javascript的例子。

这里还有几个知识点:

1)为了让WebView从apk文件中加载assets,Android SDK提供了一个schema,前缀为"http://www.cnblogs.com/csj007523/admin/file:///android_asset/"。WebView遇到这样的schema,就去当前包中的 assets目录中找内容。如上面的"http://www.cnblogs.com/csj007523/admin/file:///android_asset/demo.html"
2)addJavascriptInterface方法中要绑定的Java对象及方法要运行另外的线程中,不能运行在构造他的线程中,这也是使用 Handler的目的。

 

 

 

posted @ 2011-06-30 09:34 大树2 阅读(350) 评论(3) 编辑

2011年6月17日 #

一、什么是增强现实?
当你想知道今天的天气情况的时候,还是在听新闻联播之后的天气预报吗?当你想知道哪辆公车可以回家的时候,还是要挨个公交站牌去找寻么?当你想认识一个漂亮mm的时候,还是要鼓起勇气跑上前去跟她搭讪吗?当你在街上游荡,想找到一家吃晚餐的地方的时候,你还是查完大众点评查谷歌地图吗?如果现在有一种技术,可以让你想知道天气的时候,直接仰望苍穹;想知道公车信息的时候,直接去问公车;想知道mm信息的时候,直接扫描mm本人;想找附近吃饭的地方时,直接摄像头环绕周边…会不会听上去有点离谱呢?其实这项技术已经发展的非常成熟了,就是增强现实技术。

增强现实(AR)是在虚拟现实技术基础上发展起来的一种新兴计算机应用和人机交互技术。它借助计算机和可视化技术将虚拟的信息应用到真实世界,真实的环境和虚拟的物体实时地叠加到了同一个画面或空间同时存在。简单的说就是虚实结合。

“传统的增强现实服务过于平面,无法将周围环境的有用信息完整呈现且运用,他们所发展中的接合自然网络服务(Articulated Naturality Web),则可以让人以截然不同的方式来使用科技;未来实际配合手机来用,将可以让使用者有相当多广泛的用途,例如说以相机来扫描辨识饭店外观,即可进行空房查询、订房等,若以相机扫描空荡荡、尚未装潢的办公室,则会叫出一系列的办公室装潢元素,让使用者来配对,甚是还可以照照天空,来显示一天的天气预测等等,诸如此类的应用,可以说是有相当多延伸空间。”

二、基本原理
LBS常用的POI信息会有三个维度的信息:

名称
类别
坐标
而通过手机摄像头定位一个虚拟物品或虚拟信息则需要这样三类数据:

GPS坐标
数字罗盘确定的手机朝向
加速器给出的手机与地面角度
当用户为屏幕中的景物添加标注,或者放置虚拟物品到屏幕中时,需要同时附带这三类数据,其他用户通过摄像头查看景物时,才能通过这三类数据匹配出相应的信息。

三、当虚拟照进现实
1、Foursquare的位置层

Foursquare推出的“位置层”(Location-layers)功能,允许企业通过“Tips”想用户推送信息。该功能类似于“增强现实”原理,使现实世界中的信息以数字的形式反映出来。

2、Layar的开放平台

荷兰一家名叫SPRXmobile的公司推出的Layar的软件,推出的开放平台计划。随着第三方API的发布,互联网服务商们争相将在Layar平台上构建自己的数据层,而Layar软件自身的功能也因此变得更加丰富。用户只需要将手机的摄像头对准周围的建筑物或者开放空间,就能在手机屏幕下方看到与之相关的现实数据,其中包括房屋出租、餐馆打折、招聘启事以及ATM位置等实用信息。

3、Discover Anywhere Mobile

多伦多的旅行向导提供商Discover Anywhere Mobile完成一款iPhone应用程序的开发,该应用提供北美33个城市的地铁、轻轨、列车和机场信息的增强现实视图。在下一版iPhone OS推出之时,该应用将正式发布。

4、Mobizily

奥地利创业公司Mobizily开发的Wikitude世界浏览器,前身是一款增强现实旅行指南软件。这款软件的初衷是为全世界背包客建立一个手机上的虚拟旅行手册,帮助用户自行标注、分享现实世界中的景点,并通过手机上的Wikitude软件查阅其他用户提供的相关景点描述。Wikitude中所有景点信息主要由用户提供,并通过维基模式来维护。在Wikitude.me网站上,用户可以使用自己的Google、Yahoo!、Twitter或是OpenID帐号登录并提交新的注释内容,降低了产生内容的门槛。

四、目前使用场景
1、餐馆服务

 

Yelp是众所周知的第一个采用AR技术的客户端,打开手机摄像头就可以查看周围商户的信息。我推测是需要定位+方向识别技术。盛大游玩网的客户端切客也采用了这个增强现实技术。

2、旅游

 

Wikitude通过用户提供的游记和和地点信息提供旅游攻略

3、测距离

 

4、虚拟宠物

 

图 ARf是iPhone上一款增强现实宠物养成游戏,需要二维码扫描技术支持

5、天气查询

 

TwittARound是一款iPhone上的增强现实软件,可以利用摄像头对准天空来判断当前的天气状况。需要定位技术加上云存储的天气数据库。

6、娱乐游戏

 

AR Invaders 将AR技术引入游戏,无论你身处何处,都是真实的战场!游戏利用设备自带的摄像头捕捉周围的实时画面,利用陀螺仪和重力感应来判断玩家的动作、方向和位置变化,玩家则需要在实境中搜索着外星飞船并击毁他们,阻止外星人的入侵。AR Invaders 需要陀螺仪支持,所以仅适用于iPhone 4 和 Touch 4。

五、未来的移动用户体验
在web2.0时代,人们迫切需要更多的互动性,更多的即时性,更多的个性化,更多的垂直化,随着AR技术跟手机发展的结合,相信一个崭新的web3.0时代已经在向我们招手,虚实结合、高度交互性以及三维定位功能,将极大程度的调用用户参与的热情,还原互联网的真实感,让互联网跟真是世界的关系更紧密,是现在lbs服务的三维化。AR也为互动营销、移动广告发展带来了巨大的商机,它创造出全新的用户体验,在一种轻松活跃的环境中,使用户与品牌产生零距离的接触。

1、全新的广告形态

用增强现实技术实现的虚拟广告投放,大大的有别于什么报纸广告、电视广告、户外广告、搜索引擎广告。

2、全新的搜索模式

之前也撰文移动搜索产品的用户体验提到过,未来的搜索将要不在局限与那一个框,摄像头搜索将会有很大的想像空间,营造全新的位置搜索引擎时代。

3、全新的游戏模式

虽然Mytown之类的已经对LBG(基于位置的游戏)进行过实践摸索,但是相信这种平面的LBS远没有AR游戏带给用户的参与感强烈。

4、全新的社交方式

现在我们还停留在纸质名片的阶段,未来每个人都可以有一个立体的社交主页,帮订自己的SNS、微博,通过人脸识别技术,用户就能利用摄像头看到你的信息、动态,添加你为社区好友。

5、全新的浏览器

只要开启摄像头,就能获得周围一切我想要的信息,通过在不同的图层中切换,找到感兴趣的垂直信息,这不是浏览器是什么?这是基于摄像头的浏览器。

6、全新的生活方式

基于位置你再也不会迷失了,周边的餐馆、今天的天气、公车的路线、周围的美女、商场的打折信息、前方漂亮的鞋是什么牌子等等,我们将要迎来一个全新的移动互联网时代。

虽然AR技术在国外已经比较成熟,并频繁并应用到商业化产品中,但是在国内还停留在学术研究阶段,出了盛大游玩网出的切客里使用到了AR技术之外,我还暂时不知道第二家。但是相信随着AR技术的不断完善,国内手机市场情况孕育到位,相信未来,Augmented Reality + Location会是一个趋势,开发者的想象力跟使用者的需求间是否能对应到,不久之后应该就会有答案了。

 

posted @ 2011-06-17 14:42 大树2 阅读(195) 评论(0) 编辑

 

---AR技术必须和基于LBS的广告、搜索、社交应用场景相结合,才能创造出更大的商业价值

 

 


行走在大街上的你在寻觅一家餐馆,你掏出手机打开某一个应用,之后将摄像头对准大街两侧的景物。手机显示屏中的景物墙体上,出现了附近若干家中餐馆的方向和距离,你走近其中的一家,这家的建筑外墙上弹出了消费点评网站上食客们对其菜品的许多条评论。你觉得还不错,于是在某一个合作网站上check-in,领到了一枚可以打折的徽章,之后走进餐馆。步入餐馆后,屏幕上的内墙上首先弹出了该餐馆的Tips,告知你今天的特色菜以及某一个菜品的暂停供应。而在等服务生上菜的过程中,你通过手机摄像头看到了同样在此店用餐过的用户“满墙”的趣味留言。整个快乐的过程,都在同一款应用中实现。
这不是科幻小说情节,而是不久即将实现的基于扩增实境(Augmented Reality,简称AR,亦称增强现实)的应用。
 诞生于上个世纪60年代的AR技术,虽然在上世纪90年代便已出现了个人化应用和开发工具包(SDK),但它的商业化进程却十分缓慢。而在iOS和Android平台引爆移动互联网时代之后,针对AR的研究和应用实现了突飞猛进的发展。
在2008年之前还难觅其踪影的AR应用,如今已经出现在各大终端平台。虽然这类应用尚未成为人们日常生活的必需配置,亦未在各大应用商店“登顶”,但业内人士当初的判断已经部分实现——AR应用已经覆盖了游戏、教育、生活信息和商业运营等各个领域。特别是在苹果、英特尔、高通等产业实力巨头相继加入“搭台”之后,AR的应用前景被普遍看好。
然而,普及之后,AR技术本身恐怕难以产生商业价值,又由于自身的技术革命性,AR的商业化注定不会一帆风顺。它的技术标准,它的数据来源,都将是产业势力各方博弈的焦点。
终端引爆应用
自诞生以来的近40年间,AR的应用环境一直局限于工业领域。2000年,科学家Bruce·Thomas开发出了第一款基于AR的户外游戏——ARQuake,并在第四届可穿戴式电脑论坛上进行了展示。但由于当时可供大众使用的移动设备十分稀少且硬件条件不足,这使得在之后很长一段时期内,基于AR 的应用都没能走近大众。在这期间,索尼在PS3上发布的AR应用——the Eye of Judgment也未取得市场认同。
软硬件技术的瓶颈是AR走向大众化的首要制约。这一点对于基于AR的游戏(即在虚拟物体背后渲染出摄像头捕捉到的现实景观)来说,尤为重要。
工业化应用与生活应用的最大区别在于“实境”的范畴——对于大众来说,一项新电子技术首先应满足的是随机的娱乐和生活信息需求。这就要求AR必须突破空间局限,在随机的场合使用。显然,这在移动计算时代(智能终端)到来之前是无法实现的。
2007年前后,iOS和Android平台的出现,宣布了移动计算时代的正式降临。第二年便出现了第一款大众化AR应用——针对G1,定位于旅游景点信息展示的Wikitude AR Travel Guide,但由于没有针对性的技术支持,在此后的两年内,智能终端上的AR应用功能仍十分简单。
苹果公司在意识到AR应用的前景后,在2009年9月发布的iOS 3.1(iPhone 3Gs)中加入了对AR的支持,开始在操作系统层面推进AR的发展。
苹果的支持大大推动了AR的应用研发。3Gs发布之后,iPhone上出现了第一款基于LBS的AR应用——Nearest Tube,用来查询伦敦的地铁口位置。在这之后,便是著名的AR研发公司Layar的建立。
在终端厂商拉开AR大幕之后,芯片厂商也及时跟进了。2009年,高通与佐治亚学院合作成立了AR研发实验室并在2010年10月发布了新的AR软件开发工具包,还同时启动了AR开发者挑战赛。两位立陶宛开发者Paulius Liekis和Arminas Didiokas组成的团队,以其作品Paparazzi赢得冠军并获得12.5万美元的奖金。此外,高通已经亲自上场和美国著名的芭比娃娃制造商Mattel合作,将经典的Rock‘Em Sock’Em(格斗机器人)游戏以一种全新的方式推入市场。
值得一提的还有通用汽车。来自通用开发实验室的汽车AR系统名为G.M.Tinkers,这套系统通过在车内外安装多个摄像头和传感器,能够监视司机眼球和头部的运动并及时将一些补充信息显示在前挡风玻璃上,让司机们能够更好地了解周围的路况。
苹果从iPhone4开始加入的陀螺仪技术,也给AR带来更加稳定和流畅的画面体验。
实际上,从iOS上第一款AR应用Nearest Tube,到之前人们幻想中的AR星战游戏——Star Wars Arcade: Falcon Gunner(运用了陀螺仪技术)登陆iOS,之间仅仅用了1年时间。
业内人士认为,在苹果这样的终端厂商,英特尔、高通等芯片厂商以及通用汽车这样的传统行业巨头的推动下,AR产业已经到了一个引爆点。
与应用场景适配
实际上,AR技术的大众化或者产业化程度,取决于两个维度上的约束条件:除了软硬件技术之外,另一个是AR技术与现实应用场景的适配。
在游戏之外,如Wikitude AR Travel Guide和Nearest Tube般,早期的AR应用仅限于指引地理方位或者介绍历史信息,过于平面,无法将周围环境的有用信息完整呈现,难以形成商业价值。
而自2009年兴起的基于地理位置信息(LBS)的商业信息服务,已经与AR技术迅速地结合在一起。这种结合的逻辑显得一目了然:当你在街上游荡想找到一家吃晚餐的地方,你愿意查完大众点评再查谷歌地图吗?
著名消费点评网站Yelp是第一个采用AR+LBS技术的客户端,它使得用户打开手机摄像头就可以查看周围商户的信息。比Foursquare还早的Brightkite公司是美国一家基于地理定位服务的社交网站,它与麦当劳在去年年末进行合作,开发了基于AR的项目——用户拿出手机对着街景,即可以显示当前多少米范围内(用户自己设定,范围可以大到一个大城市)有麦当劳门店。此外,结合Brightkite用户系统,用户可以看到有多少好友在这里上传了照片、添加了评论等。Foursquare也在随后支持其客户端用AR的方式呈现出Tips,而不仅仅是最初的check-in。
建立于2009年的荷兰Layar公司的业务全部是研发AR+LBS的应用,它在2010年4月发布了扩增内容商店,成为了这一领域的平台性公司。截至今年3月26日,在其商店内的1900余个应用场景之中,如果不计入大部分应用场景与他者重叠的旅行者信息,分类排名前三位的分别为饮食信息(171个)、娱乐信息114个、购物信息(111个)。
由此可见,基于AR+LBS的商业信息服务,是AR商业化的最重要的表现形式。
被业界普遍看好的另一个AR应用场景是基于AR+LBS的社交服务,这种应用场景可以看成AR+LBS+SNS。
开发者Johannes la Poutré在Layar 上开发的Tweeps Around应用是这类应用的杰出代表。用户可以向Twitter发布关于地理位置和商业信息的询问,之后返回的答案会以AR的方式反映在Layar浏览器里面。
业界很多人认为,AR、LBS和SNS三者的结合,将实现一场商业模式的革命,但遗憾的是,目前的这种革命形式还不甚乐观。
它们要么因为SNS端不够强大(比如Foursquare、盛大切客等),要么因为对接商业资源有限(如Tweeps Around ),或者因为隐私问题而畏首畏尾(比如Facebook的places服务)。但可以下结论,除了游戏之外,AR技术必须和基于LBS的广告、搜索、社交应用场景相结合,才能创造出商业价值。
产业瓶颈
虽然商业前景光明,但AR应用现在难以普及,最主要的还是由于技术层面问题。
AR应用背后的核心技术就是图像渲染技术和后台数据库建设,而目前来看,这两方面的标准难以确立、数据分享难以实现,使得AR的产业化又充满了许多变数。
曾在苹果公司供职8年、近期加入盛大创新院的多媒体专家路坚对《商业价值》表示,目前的AR有些像云计算产业,产业中各方的表述都不太一样,SDK不统一,这是影响AR产业化的最大瓶颈。路坚同时认为,底层技术的好坏并非是AR应用质量的决定性因素,比如OpenGL是早就出现的视频技术,但市场上出色的图形作品并不多。
而数据库的分享则是更难解决的问题。将现实数据化到信息联网、再到开放数据库,这是最可能产生商业价值的AR应用——AR与LBS结合应用付诸实现的前提,然而究竟有多少现实环境的数据能够向开发者开放,还是一个未知数。Layar在欧洲以外的各国落地十分缓慢就是由于此原因,这一瓶颈在国内则显得更为明显。
不过,也有人士认为,Layar的内容商店模式为数据库的分享提供了一种思路,现实数据的持有方可以尝试用封装的方式向开发者销售数据。
在不久前结束的主题为“美梦成真”的巴塞罗那移动通信大会上,Layar、高通等AR产业中的各方势力都展出了自己夺人眼球的崭新应用,然而领跑AR产业的两者能在多大程度上打破瓶颈,而非施行资源独占,恐怕决定着AR走进大众日常生活的时间表。


 

 

posted @ 2011-06-17 14:32 大树2 阅读(184) 评论(2) 编辑

2011年6月16日 #

1》MeidaPlayer播放指定路径下的MP3文件;

2》MeidaPlayer播放网络上的MP3文件;

3》VideoView 视频播放;

4》MediaRecorder 录音;

 

1》MeidaPlayer播放指定路径下的MP3文件;

MediaPlayer mp=new MediaPlayer();

mp.setDataSource("path");

mp.prepare();

mp.start();

 mp.isLooping;

mp.pause();

mp.reset();

mp.release();

 

MediaPlayer mp=new MediaPlayer();

mp=MediaPlayer.create(demomdplayer01.this,R.Raw.test);    //res/Raw/test.mp3

mp.prepare();

mp.start();

 

 

2》MeidaPlayer播放网络上的MP3文件;

MediaPlayer mp=new MediaPlayer();

Uri uri=Uri.parse(www.cnblogs.com/team/ShenzhenAndroidClub/android.mp3);

mp=MediaPlayer.create(demomdplayer01.this,uri);  

mp.prepare();

mp.start();

 

 

3》VideoView 视频播放

 

VideoView mvd=new VideoView();

  mvd.setVideopath("path");//这两种方法都可以 mvd.setVideoPath("file:///sdcard/love_480320.mp4");

                         //mvd.setVideoURI(Uri.parse("/sdcard/love_480320.mp4"));

 //定义MediaController对象 

 MediaController mediaController = new MediaController(this); 

//把MediaController对象绑定到VideoView上 

 mediaController.setAnchorView(mvd); 

//设置VideoView的控制器是mediaController 

 mvd..setMediaController(mediaController); 

  mvd.requestFocus();

  mvd.start();

  mvd.pause();

   

4> MediaRecorder 录音;

MediaRecorder mr = new MediaRecorder(); 

 mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT); 

 mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); 

 mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);  
 mr.setOutputFile(file.getAbsolutePath()); 

                    mr.prepare(); 

                    mr.start(); 

                    mr.stop(); 

                    mr.release(); 

 

// 创建录音对象 

    MediaRecorder mr = new MediaRecorder(); 

        // 从麦克风源进行录音 
              mr.setAudioSource(MediaRecorder.AudioSource.DEFAULT); 

             // 设置输出格式 
               mr.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); 

                // 设置编码格式 

                 mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);  
                 // 设置输出文件 

                 mr.setOutputFile(file.getAbsolutePath()); 

               try { 

                     // 创建文件 

                   file.createNewFile(); 

                  // 准备录制 

                   mr.prepare(); 

                } catch (IllegalStateException e) { 

                     e.printStackTrace(); 

                } catch (IOException e) { 

                   e.printStackTrace(); 

                } 

                // 开始录制 

               mr.start(); 
               recordButton.setText("录音中……"); 

             } 

        }); 
   

        // 停止按钮点击事件 
         stopButton.setOnClickListener(new View.OnClickListener() { 

            @Override

             public void onClick(View v) { 

                if (mr != null) { 

                    mr.stop(); 

                    mr.release(); 
                    mr = null; 

                   recordButton.setText("录音"); 

                     Toast.makeText(getApplicationContext(), "录音完毕", Toast.LENGTH_LONG).show(); 

                } 

             } 

        });

 

posted @ 2011-06-16 17:39 大树2 阅读(389) 评论(0) 编辑

摘要: 一培训机构设计的学习android课程内容:供大家参考第一阶段:Linux操作系统及C语言编程课程目标:熟练Linux操作系统、熟练C语言编程模块名称阶段目标Ubuntu安装与配置掌握Ubuntu的安装与配置Linux 基本命令讲解熟练Linux系统的常用命令,并能使用其操作该系统Linux下的C编程环境配置学习Linux下C编程环境的配置和应用C基础入门C基础入门,熟练基本语法,程序基础函数与程序结构熟练C语言的核心编程单位函数的使用指针与数组熟练C语言中的难点指针和数组结构体与联合体熟练结构体和联合体的使用第二阶段:核心Java +Java数据库+Java Web开发课程目标:精通Java阅读全文
posted @ 2011-06-16 14:46 大树2 阅读(301) 评论(0) 编辑