0%

这里只是记录java使用正则表达式提取字符串的方法,并不是正则表达式的教程,所以,不详细讲正则表达式的语法.下面以提取网址中的域名为例:

        String s="http://www.pocketdigi.com/index.php";
        Pattern p = Pattern.compile("http://([^\\/]+)");
        //匹配http://开头,不包含/的内容
        Matcher match = p.matcher(s);
        String domain = "";
        if (match.find()) {
            domain = match.group(1);
            System.out.println(domain);
        }

进度条在应用中的作用非常大,可以告诉用户当前操作执行的进度,以免用户在等待中失去耐心,进而关闭应用.Windows Phone 7的进度条有两种样式,一种是从左往右循环滚动的小点点,这种进度条并不能显示当前进度,类似于Android进度条的转圈风格;另一种就是能显示进度的普通进度条,两种样式效果如下图: 介绍一下这个实例,页面上三个控件,两个ProgressBar分别显示两种风格的进度条,一个按钮,用于开启新线程更新ProgressBar的进度,这里用于了委托,如有不明白,参考: 几个控件的XAML代码:

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" Background="{x:Null}">
            <ProgressBar Height="54" HorizontalAlignment="Left" Margin="17,27,0,0" Name="progressBar1" VerticalAlignment="Top" Width="390" IsIndeterminate="True" />
            <!--IsIndeterminate是关键,这个属性确定了ProgressBar的样式,默认是false,就是普通的能显示进度的进度条,true就是不能显示进度的进度条-->
            <ProgressBar Height="59" HorizontalAlignment="Left" Margin="31,107,0,0" Name="progressBar2" VerticalAlignment="Top" Width="374"  />
            <Button Content="更新progressBar2" Height="82" HorizontalAlignment="Left" Margin="63,199,0,0" Name="button1" VerticalAlignment="Top" Width="260" Click="button1_Click" />
        </Grid>

C#程序代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Threading;

namespace PhoneApp3
{
    public partial class MainPage : PhoneApplicationPage
    {
        delegate void ProgressDelegate(int i);
        //声明委托类型
        //委托的内容如有不明白,见http://www.pocketdigi.com/20110916/476.html 有详细注解
        ProgressDelegate progressDelegate;
        //声明委托
        public MainPage()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            progressDelegate = SetProgress;
            //把更新进度方法添加进委托
            new Thread(new ThreadStart(ThreadProc)).Start();
            //开启新线程

        }
        private void SetProgress(int i)
        {
            //这是更新进度条的方法
            progressBar2.Value = i;
            if (i == 100)
            {
                //如果达到100,则隐藏进度条
                progressBar2.Visibility = Visibility.Collapsed;
                //显示方法Visibility.Visibl
            }
        }
        private void ThreadProc()
        {//新线程执行的方法
            for (int i = 0; i <= 100; i++)
            {
                this.Dispatcher.BeginInvoke(progressDelegate,i);
                //线程中调用委托来更新UI,参数是委托,以及委托的参数
                Thread.Sleep(1000);
            }

        }
    }
}

在C#中,非主线程(即非UI线程,就是通过new Thread创建的线程)是不能直接操作UI元素的,Android中也一样,必须通过Handler与UI线程通讯,通知UI线程更新.而C#则采用委托的方式更新UI.下面用一个简单的实例来说明.这是一个WPF项目,只有一个名为textBlock1的TextBlock用于显示,一个名为button1的Button用于开启新线程来更新textBlock1.新线程执行的内容是0-100循环,而让textBlock1显示当前循环的进度.Windows Phone 7开发中,也通用,参考 上代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;

namespace WpfApplication2
{
    /// 
    /// MainWindow.xaml 的交互逻辑
    /// 
    public partial class MainWindow : Window
    {
        delegate void DelegateTest(int i);
        //使用delegate关键字,声明委托类型,参数和返回值都有要求,见下面说明
        DelegateTest delegateTest;
        //声明委托类型所对应的委托
        public MainWindow()
        {
            InitializeComponent();
        }


        public void SetText(int i)
        {
            //更新UI的方法
            textBlock1.Text = i.ToString();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            delegateTest = SetText;
            //实例化委托,就是添加委托要执行的方法,
            //可以用+=添加多个方法,如下面再增加 delegateTest +=方法名;
            //添加的方法,返回值和参数列表 必须与委托类型结构相同
            //即这里DelegateTest与SetText参数都为int,返回值都为void

            Thread t = new Thread(new ThreadStart(ThreadProc));
            //开线程方法与Java有些不同
            t.Start();  
            //执行一个新线程

        }
        public void ThreadProc()
        {
            for (int i = 0; i < 100; i++)
            {
                this.Dispatcher.BeginInvoke(delegateTest, i);
                //创建Dispatcher,使用BeginInvoke方法进行委托
                Thread.Sleep(1000);
                //睡眠1秒
            }

        }
    }
}

装了WP7的SDK,会自动安装Visual Studio Express 2010 For Windows Phone,相当于免费的Visual Studio.遗憾的是,这个Express版本的Visual Studio只有英文版.而国内的用户一般都同时安装了Visual Studio的其他中文版本(专业版/旗舰版),我这里安装了VS 2010 中文专业版.但是即使安装了WP7 SDK,专业版在新建项目的时候还是没有增加Windows Phone 7应用程序的模板,我们这里需要自动手动添加一下. 首先打开D:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplates\CSharp\Silverlight for Windows Phone (我的装D盘),里面只有一个1033目录,复制一个,重命名为2052 执行:D:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat 在运行里输入:devenv /setup,稍等片刻,等鼠标旁的圈圈转完,再打开VS中文专业版,新建项目,可以看到多了Silverlight for Windows Phone,如图:

在网络程序开发中,经常要与网页源码打交道,因为与服务器交互,直接使用HTTP协议是最简单的。下面的方法解决了在下载UTF8编码的源码时乱码的问题。

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            WebClient webClient = new WebClient();
            webClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(webClient_DownloadDataCompleted);
            //添加下载完成事件处理器,在异步数据下载完成时触发
            webClient.DownloadDataAsync(new Uri("http://www.pocketdigi.com"));
            //异步下载,得到的是byte数组,不会卡UI
            //如果用DownloadString方法,在目标页面是UTF-8编码时会乱码,而且即使用Encoding类转换,也会丢失字符
        }
        private void webClient_DownloadDataCompleted(Object sender, DownloadDataCompletedEventArgs e)
        {
            //异步下载完成时触发
            String html = Encoding.UTF8.GetString(e.Result);
            //使用utf8编码转换成String
            textBox1.Text = html;
            //显示在 TextBox上
        }

现在越来越多的网站采用JSON来交换数据,在Json.org网站上,Java可以使用的解析Json的组件就有21种之多。这里以使用org.json解析JSON为例。在读本文之前,读者有必要了解一下JSON的结构,这里不作介绍。 首先下载org.json源码,下载地址:https://github.com/douglascrockford/JSON-java,点Downloads,Windows系统就选zip吧。当然你也可以用Git,只是我不太习惯那玩意。下载完后解压,在你的项目里新建一个名为org.json的包,把除README和Test.java以外的所有文件放入该包内(Eclipse只要拖进去就可以),现在我们就可以用org.json解析JSON.为了以后方便,你也可以把org.json这个包打成jar,在要用的项目上导入就行。 下面是程序中的使用方法:

        String s = "{\"person\":{\"name\":\"张三\",\"age\":20}}";
        JSONObject jsonObj = new JSONObject(s);
        JSONObject  result = jsonObj.getJSONObject("person");
        System.out.println("姓名:"+result.getString("name")+" 年龄:"+result.getInt("age"));
        //解析object形式
        s="{\"persons\":[\"张三\",\"李四\",\"王五\"]}";
        jsonObj = new JSONObject(s);
        JSONArray jsonarr=jsonObj.getJSONArray("persons");
        for(int i=0;i

在WP7程序中,与Android程序一样,如果一直按返回键,就是一直退回到上一个界面,直到退出程序,返回到Home界面。有时候,我们希望用户在按返回键的时候给出确认提示,以免用户误按而退出程序。要实现这个功能就需要重写返回PhoneApplicationPage类中的OnBackKeyPress方法:

        protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
        {
            //这里可以执行弹出对话框操作
            e.Cancel = true;  
        }

默认情况下,Visual Studio的ToolBox里没有任何下拉菜单的控件可供使用,虽然可以手工输入代码使用隐藏的ComboBox来实现下拉菜单,但是显示出来的菜单与Metro UI主题不匹配。Silverlight for Windows Phone Toolkit提供了多个系统默认没有的控件扩展,像AutoCompleteBox,ContextMenu,DatePicker,ListPicker等等,我们下载安装后就可以使用这些控件。要实现下拉菜单,用到了这里的ListPicker.下面详细介绍使用方法。 首先,要下载安装Silverlight for Windows Phone Toolkit,地址:http://silverlight.codeplex.com/releases. 然后,在工程中添加引用。点击Project–Add Reference–.Net选项卡,下拉,找到Microsoft.Phone.Controls.Toolkit,双击添加,如下图: 。这样就可以在XAML代码中使用所有Toolkit中包含的控件了。 接着添加控件:打开相应的XAML,在phone根元素添加命名空间,

xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"

在需要添加ListPicker的地方添加ListPicker代码,需要使用toolkit前缀,如:

            <toolkit:ListPicker Header="Categories">
                <toolkit:ListPickerItem Content="Johnny" />
                <toolkit:ListPickerItem Content="Tommy" />
                <toolkit:ListPickerItem Content="Alumi" />
            </toolkit:ListPicker>

保存后,即可在预览里看到如下效果: Windows Phone7的资料比较少,搞定下拉菜单就花了不少时间。 2011年9月21日注:可以在工具箱上点右键-选择项来添加默认没显示的控件,包括安装Toolkit后增加的ListPicker,这样就可以直接用鼠标拖动添加控件。

今天的这个例子是要利用android.hardware.Camera类实现类似Android系统自带相机的功能,可以动态预览摄像头拍到的画面,可以拍照并存到SD卡,支持自动对焦。暂时还没有实现录像功能。经真机测试,以下代码可以在关屏时正常拍照,但在Service中无法运行,即使亮着屏幕,原因未知。 布局:

<?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"
    android:weightSum="1">
    <SurfaceView android:id="@+id/surfaceView1" android:layout_width="320dp" android:layout_height="220dp"/>
    <LinearLayout android:layout_height="wrap_content" android:id="@+id/linearLayout1" android:layout_width="fill_parent">
        <Button android:text="拍照" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
    </LinearLayout>
    <ImageView android:layout_height="220dp" android:id="@+id/imageView1"  android:layout_width="320dp"></ImageView>
</LinearLayout>

一个 SurfaceView用于实时显示摄像头拍摄到的画面,一个控制拍照的按钮,还有一个ImageView,拍到照片后会把拍到的图片显示在这里。 Java代码:

package com.pocketdigi.camera;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class CameraActivity extends Activity implements SurfaceHolder.Callback {
    /** Called when the activity is first created. */
    SurfaceHolder surfaceHolder;
    SurfaceView surfaceView1;
    Button button1;
    ImageView imageView1;
    Camera camera;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        button1=(Button)findViewById(R.id.button1);
        //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        //设为横向显示。因为摄像头会自动翻转90度,所以如果不横向显示,看到的画面就是翻转的。
        //本例中不横向
        
        surfaceView1=(SurfaceView)findViewById(R.id.surfaceView1);
        imageView1=(ImageView)findViewById(R.id.imageView1);
        surfaceHolder=surfaceView1.getHolder();
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.addCallback(this);
        button1.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                camera.autoFocus(afcb);
                //自动对焦
                
            }});
        
    }
    PictureCallback jpeg =new PictureCallback(){

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO Auto-generated method stub
            Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length);
            //byte数组转换成Bitmap
            imageView1.setImageBitmap(bmp);
            //拍下图片显示在下面的ImageView里
            FileOutputStream fop;
            try {
                fop=new FileOutputStream("/sdcard/dd.jpg");
                //实例化FileOutputStream,参数是生成路径
                bmp.compress(Bitmap.CompressFormat.JPEG, 100, fop);
                //压缩bitmap写进outputStream 参数:输出格式  输出质量  目标OutputStream
                //格式可以为jpg,png,jpg不能存储透明
                fop.close();
                System.out.println("拍成功");
                //关闭流
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("FileNotFoundException");

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                System.out.println("IOException");
            }
            camera.startPreview();
            //需要手动重新startPreview,否则停在拍下的瞬间
        }
        
    };

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera=Camera.open();
        try {
            
            Camera.Parameters parameters=camera.getParameters();
            parameters.setPictureFormat(PixelFormat.JPEG);
                        //每台机器可用的PreviewSize不同,可以parameters.getSupportedPreviewSizes();获取支持的size
            parameters.setPreviewSize(320, 220);
            camera.setParameters(parameters);
            //设置参数
            camera.setPreviewDisplay(surfaceHolder);
            //摄像头画面显示在Surface上
            camera.startPreview();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        System.out.println("surfaceDestroyed");
        camera.stopPreview();
        //关闭预览
        camera.release();
        //释放资源
    }
    
    AutoFocusCallback afcb= new AutoFocusCallback(){

        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            // TODO Auto-generated method stub
            if(success){
                //对焦成功才拍照
                camera.takePicture(null, null, jpeg);
            }
        }
        
        
    };
}

在AndroidManifest.xml中要添加拍照及写入存储卡权限:

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

以前写播放器都直接用VideoView,原因无它,简单。但是VideoView连播放暂停按钮给帮你写好了,不能自己控制,制定样式,效果千篇一律。今天学习用SurfaceView写个视频播放器。 布局:一个SurfaceView,三个按钮

<?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" android:weightSum="1">
    <SurfaceView android:layout_height="220dip" android:layout_gravity="center" android:id="@+id/surface" android:layout_weight="0.25" android:layout_width="320dip"></SurfaceView>
    <LinearLayout android:id="@+id/linearLayout1" android:layout_height="wrap_content" android:layout_width="fill_parent">
        <Button android:text="播放" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
        <Button android:text="暂停" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
        <Button android:text="停止" android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
    </LinearLayout>
</LinearLayout>

程序代码:

package com.pocketdigi.surface;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SurfaceActivity extends Activity implements SurfaceHolder.Callback {
    /** Called when the activity is first created. */
    MediaPlayer player;
    SurfaceView surface;
    SurfaceHolder surfaceHolder;
    Button play,pause,stop;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        play=(Button)findViewById(R.id.button1);
        pause=(Button)findViewById(R.id.button2);
        stop=(Button)findViewById(R.id.button3);
        surface=(SurfaceView)findViewById(R.id.surface);
        
        surfaceHolder=surface.getHolder();
        //SurfaceHolder是SurfaceView的控制接口
        surfaceHolder.addCallback(this);
        //因为这个类实现了SurfaceHolder.Callback接口,所以回调参数直接this
        surfaceHolder.setFixedSize(320, 220);
        //显示的分辨率,不设置为视频默认
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        //Surface类型
        
        play.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                player.start();
            }});
        pause.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                player.pause();
            }});
        stop.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                player.stop();
            }});
        
        
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        // TODO Auto-generated method stub
        //必须在surface创建后才能初始化MediaPlayer,否则不会显示图像
        player=new MediaPlayer();
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        player.setDisplay(surfaceHolder);
        //设置显示视频显示在SurfaceView上
            try {
                player.setDataSource("/sdcard/3.mp4");
                player.prepare();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        if(player.isPlaying()){
        player.stop();
        }
        player.release();
        //Activity销毁时停止播放,释放资源。不做这个操作,即使退出还是能听到视频播放的声音
    }
}