0%

为了能让更多的人用上我们的程序,程序必须有各种语言的版本(英语是必须的)。原来我的想法是先判断Android系统当前设置的语言,再加载相应的layout,或是String,但是网络上搜索了一下发现,其实Google早就已经帮我们考虑这个问题了,我们根本就不需要自己判断机器语言,只要写不同语言的xml文件,并放到指定目录,系统会自动识别调用。

一般来讲,我们都把string先放到values/strings.xml文件里,然后在程序里需要显示文字的地方调用,所以我们只要多建几个strings.xml,对应不同的语言就OK,下面一步一步来:

打开新建Android XML File对话框,

lang

添加列表里的,Region和Language,Region值填写两位地区代码(美国为US,中国为CN,台湾(繁体)为TW),Language填写两位语言代码(英语en,中文zh)。有一点要注意,简繁体中文并不是由Language识别的,不管是简体还是繁体,Language都填zh,如果要显示繁体,Region填为TW就可以了

获取屏幕硬件分辨率方法:

        TextView tv=(TextView)findViewById(R.id.tv);
        DisplayMetrics dm=new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        float width=dm.widthPixels*dm.density;
        float height=dm.heightPixels*dm.density;
        tv.setText(width+"X"+height);

其中dm.withPixels和dm.heightPixels得到的宽度和高度值都是以宽度为320为标准的,也就是说,不管你的屏幕是什么分辨率,宽度都会得到320,而高度就根据比例宽高比例计算,所以在我的Milestone上(480X854)得到的宽高为320X569,如果要得到真实的分辨率,就必须乘以dm.density,这个值是因硬件分辨率而异的,如果是屏幕硬件宽为320像素,那么这个值就是1,如果是480,这个值就是480/320,就是1.5。 2011.11.26注:今天发现dm.widthPixels,和dm.heightPixels就是物理分辨率,不用再乘以dm.density,但做这个笔记的时候,确实需要乘上dm.density,暂时不知原因。

在Android中,修改图片大小是件很简单的事,只需要一个函数

Bitmap.createScaledBitmap(Bitmap,width,height,true);

第一个参数是待修改的Bitmap,第二第三个参数分别为修改后的宽、高,最后一个Boolean参数暂时不知什么作用。

当处理软件升级时,需要获取当前软件版本号,再和服务器上的软件版本对比,而版本号在AndroidManifest.xml中有设置,用以下方法可以读取到版本号,版本名,以及包名。

PackageManager manager = this.getPackageManager();
try {
        PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
String packageName = info.packageName;  //包名
int versionCode = info.versionCode;  //版本号
String versionName = info.versionName;   //版本名
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

Android系统在开启自动切换横竖屏的情况下,转动手机就会自动切换横竖屏,或者在推开键盘时也会自动切换到横屏。但是有时我们的程序只针对竖屏做了优化,在横屏时显示就会乱,影响用户体验,所以我们必须禁止系统自动切换。要达到这个目标,其实很简单。

在AndroidManifest.xml中,所有的Activity标签都加上android:screenOrientation属性,横屏值为landscape,竖屏值为portrait。这样基本实现了锁定横屏或竖屏,但是在一些有侧滑键盘的手机上(比如说我的Milestone),推开键盘的时候,Activity会自动重启,要避免在这种情况下重启Activity,可以在androidmanifest.xml文件中的每个activity加上android:configChanges=”keyboardHidden|orientation”属性,然后重写onConfigurationChanged方法

Override
    public void onConfigurationChanged(Configuration newConfig) {
        // TODO Auto-generated method stub
        super.onConfigurationChanged(newConfig);
        setContentView(R.layout.main);
    }

不过,这样载入的只是main.xml默认设置,如果在程序代码中修改过布局(改过TextView的Text之类),是不会显示修改后的结果的。

TextView并不能解析HTML代码,所以HTML中的A标签无法转换为链接,如果要在TextView上显示链接,需要在TextView上加个autoLink属性:

<TextView  android:id="@+id/tv"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="http://www.pocketdigi.com 
webmaster@pocketdigi.com 
15888922219 测试链接"
    android:autoLink="all"
    android:textColor="#FF0000"
    android:textColorLink="#000000"
/>

其中autoLink的值为 web时,只自动链接网页,为Email时只链接邮箱,为phone时只链接电话号码,为All时自动识别所有链接。还有一种为map,不知是否为地图?textColorLink设置的是链接的颜色,这里的#000000 是RGB编码,代表黑色,textColor设置的是字符颜色,就是没有被识别成链接的字体颜色,这里是测试链接四个字,定义为#FF0000,就是红色。所以这个TextView显示的效果如下图: 背景为白色是因为我之前在LinearLayout设置过background.TextView能识别换行符 还可以在程序中修改字体颜色:

 TextView tv=(TextView)findViewById(R.id.tv);
tv.setTextColor(this.getResources().getColor(R.color.gray));
tv.setTextColor(Color.GRAY);

第二行跟第三行是同样的功能,只不过两种不同的方式实现。R.color.gray事先在value目录的的xml文件中定义过:

<color name="gray">#999999</color>

Service翻译成中文是服务,熟悉Windows 系统的同学一定知道很熟悉了。Android里的Service跟Windows里的Service功能差不多,就是一个不可见的进程在后台执行,避免被用户误关闭。因为Android在某些情况下会自动关闭非前台显示的Activity,所以如果要让一个功能在后台一直执行,不被Android系统关闭,比如说闹钟、后台播放音乐,就必须使用Service. 之前开发音乐播放器的时候也没用Service,但是却可以后台播放,以为Service没什么用,但是经过一段时间后发现,没用Service的播放器在播放一段时间后会被系统自动关闭,而且就算还在后台播放,过一段时间后打开播放器,再点播放按钮,会出现两种声音,今天用Service写了个Demo,完美解决以上问题。 布局XML,就两个按钮:

<?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"
    >
<Button android:id="@+id/start"  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="开始"
    />
    <Button android:id="@+id/stop"  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="停止"
    />
</LinearLayout>

主程序main.java:

package com.pocketdigi.service;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class main extends Activity {
    /** Called when the activity is first created. */
    Button start,stop;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findView();
        start.setOnClickListener(startlis);
        stop.setOnClickListener(stoplis);
    }
    private OnClickListener startlis=new OnClickListener(){

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            startService(new Intent(main.this, Music.class));  
            //启动服务
        }
        
    };
    private OnClickListener stoplis=new OnClickListener(){

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            stopService(new Intent(main.this,Music.class));
            //停止服务
        }
        
    };
    public void findView(){
        start=(Button)findViewById(R.id.start);
        stop=(Button)findViewById(R.id.stop);
    }
}

服务 Music.java:

package com.pocketdigi.service;


import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;

public class Music extends Service {
    private MediaPlayer mp;
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        mp=MediaPlayer.create(this,R.raw.xrx);
        
    }
    @Override  
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        mp.start(); 
    } 
    @Override
    public void onDestroy() {
        super.onDestroy();
        mp.stop();
    }

}

服务还需要在AndroidManifest.xml注册后才能使用:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.pocketdigi.service"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".main"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    <service android:enabled="true" android:name=".Music" /> 
    </application>
</manifest>

Broadcast功能在于可以向手机中的其他程序发送消息,实现程序间互相通信。比如Android系统在启动,闹钟,来电等一些情况下,会广播一些消息给所有的接收者,其他程序在收到信息后可以做进一步动作。 今天的DEMO介绍一下,程序有两个Class。一个是主Activity,主要做界面显示,发送广播,另一个是广播接收器,用于收到主Activity广播后执行相应动作。 布局XML代码就不贴了,就一按钮。 main.java:

package com.pocketdigi.Broadcast;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class main extends Activity {
    /** Called when the activity is first created. */
    static final String action1="Broadcast_action1";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button b1=(Button)findViewById(R.id.b1);
        b1.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent it = new Intent(action1);
                sendBroadcast(it); 
                //点击按钮后广播一个Intent,内容是action1
                //action1这个字符串,相当于一个ID,接收广播识别用的
            }
            
        }
        );
    }
}

接收器Broadcastreceiver.java:

package com.pocketdigi.Broadcast;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class Broadcastreceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //接收到后执行以下内容
        //这里不用考虑接收到的是否就是我们要的广播
        //因为这一步已经放在AndroidManifest.xml里设置了
         Toast.makeText(context, "成功接收广播", Toast.LENGTH_LONG).show(); 

    }

}

在AndroidManifest.xml里注册一下接收器:

        <receiver android:name=".Broadcastreceiver"> 
             <intent-filter> 
              	<action android:name="Broadcast_action1" /> 
             </intent-filter>
         </receiver> 

这段代码的意思是,如果广播的action是”Broadcast_action1”,就通知Broadcastreceiver这个接收器,代码放在application标签内 本文源代码: [download id=”6”]

Notification可以在屏幕最顶部的状态栏上显示一个图标通知(QQ用的就是这个),通知的同时可以播放声音,以及振动提示用户,点击通知还可以返回指定的Activity. 今天例子的效果图: 下面我们来实现。 布局main.xml:

<?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"
    >
<Button android:id="@+id/bt1"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:text="Notification测试"
/>
<Button android:id="@+id/bt2"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:text="清除Notification"
/>
</LinearLayout>

就两个按钮,一个添加Notification,一个删除Notification java代码:

package com.pocketdigi.Notification;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class main extends Activity {
    /** Called when the activity is first created. */
    int notification_id=19172439;
    NotificationManager nm;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        nm=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        Button bt1=(Button)findViewById(R.id.bt1);
        bt1.setOnClickListener(bt1lis);
        Button bt2=(Button)findViewById(R.id.bt2);
        bt2.setOnClickListener(bt2lis);
        
    }
    OnClickListener bt1lis=new OnClickListener(){

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            showNotification(R.drawable.home,"图标边的文字","标题","内容");
        }
        
    };
    OnClickListener bt2lis=new OnClickListener(){

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            //showNotification(R.drawable.home,"图标边的文字","标题","内容");
            nm.cancel(notification_id);
        }
        
    };
    public void showNotification(int icon,String tickertext,String title,String content){
        //设置一个唯一的ID,随便设置
        
        //Notification管理器
        Notification notification=new Notification(icon,tickertext,System.currentTimeMillis());
        //后面的参数分别是显示在顶部通知栏的小图标,小图标旁的文字(短暂显示,自动消失)系统当前时间(不明白这个有什么用)
        notification.defaults=Notification.DEFAULT_ALL; 
        //这是设置通知是否同时播放声音或振动,声音为Notification.DEFAULT_SOUND
        //振动为Notification.DEFAULT_VIBRATE;
        //Light为Notification.DEFAULT_LIGHTS,在我的Milestone上好像没什么反应
        //全部为Notification.DEFAULT_ALL
        //如果是振动或者全部,必须在AndroidManifest.xml加入振动权限
        PendingIntent pt=PendingIntent.getActivity(this, 0, new Intent(this,main.class), 0);
        //点击通知后的动作,这里是转回main 这个Acticity
        notification.setLatestEventInfo(this,title,content,pt);
        nm.notify(notification_id, notification);
        
    }
}

AndroidManifest.xml加入权限:

<uses-permission android:name="android.permission.VIBRATE" /> 
<!-- 允许振动 -->

本文源代码下载: [download id=”5”]

今天学习Android通知 Toast的用法,Toast在手机屏幕上向用户显示一条信息,一段时间后信息会自动消失。信息可以是简单的文本,也可以是复杂的图片及其他内容(显示一个view)。 看效果图: 今天演示的有两种用法,如上图 main.xml:

<?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"
    >
<Button android:id="@+id/button1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Toast显示View"
/>
<Button android:id="@+id/button2"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Toast直接输出"
/>
</LinearLayout>

两个按钮,很简单 程序代码:

package com.pocketdgig.toast;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class main extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button button1=(Button)findViewById(R.id.button1);
        button1.setOnClickListener(bt1lis);
        Button button2=(Button)findViewById(R.id.button2);
        button2.setOnClickListener(bt2lis);
    }
    OnClickListener bt1lis=new OnClickListener(){

        @Override
        public void onClick(View v) {
            showToast();
        }
        
    };
    OnClickListener bt2lis=new OnClickListener(){
        @Override
        public void onClick(View v) {
            Toast.makeText(main.this,"直接输出测试", Toast.LENGTH_LONG).show();
        }
        
    };
    public void showToast(){
        LayoutInflater li=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view=li.inflate(R.layout.toast,null);
        //把布局文件toast.xml转换成一个view
        Toast toast=new Toast(this);
        toast.setView(view);
        //载入view,即显示toast.xml的内容
        TextView tv=(TextView)view.findViewById(R.id.tv1);
        tv.setText("Toast显示View内容");
        //修改TextView里的内容
        toast.setDuration(Toast.LENGTH_SHORT);
        //设置显示时间,长时间Toast.LENGTH_LONG,短时间为Toast.LENGTH_SHORT,不可以自己编辑
        toast.show();
    }
}

下面是toast.xml的内容:

<?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"
    >
<ImageView android:src="@drawable/toast"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
/>
<TextView android:id="@+id/tv1"
    android:text=""
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
/>
</LinearLayout>

源代码下载:[download id=”4”]