Android实战——Mp3播放器

原创内容,转载请注明出处

1、介绍

学习Android已经有一段时间了,但是都是一些零零散散的知识点,还需要能够将这些知识点串起来,以便加深对Android的了解。下面将通过一个小项目来将最近所学的知识串起来,在该项目中会涉及到Activity、Service、BroadCast Recevier三大组件;还有ListActivity、TabActivity;使用Android的MediaPlayer类播放音频文件;Android的多线程类HandlerThread和Handler处理类使用;Java文件下载、输入输出流的使用;SAX基于事件驱动解析XML文件;Properties文件的处理;Tomcat服务的简单搭建等知识点。

2、分析

 首先该Mp3播放器的主要功能如下:Mp3文件播放暂停,Mp3文件下载,本地Mp3文件展示,服务器Mp3文件展示。首先用户进入Mp3播放器,查看目前服务器上有哪些Mp3歌曲,将需要的Mp3文件下载下来,然后在本地文件列表中播放Mp3歌曲。

功能分析

1、在该项目中主要有四个界面:服务器Mp3歌曲文件列表,本地歌曲文件列表,设置界面,关于界面。

2、服务器歌曲文件列表页面,包含获取服务器Mp3文件列表、下载服务器Mp3文件、列表更新。

3、本地歌曲列表,包含本地Mp3文件展示、歌曲文件播放暂停等操作、列表更新。

4、设置界面,提供系统的通用设置给用户,像本地文件路径等。

5、关于界面,展示系统介绍。

6、考虑到操作方便,将服务器文件列表和本地文件列表合并在一个切换标签页中展示。

3、项目主要说明

3.1、使用Tomcat搭建mp3 Web工程

1.在tomcat目录下的webapps中新建文件夹mp3,即创建mp3简单应用工程。

2.在mp3下创建WEB-INF文件夹,并在WEB-INF文件夹下创建web.xml文件,此时完成mp3 web工程的搭建。

<?xml version="1.0" encoding="ISO-8859-1"?>


<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5"> 

  
</web-app>

3.进入doc命令,启动tomcat服务。

4.在mp3目录下添加mp3歌曲和配置文件resources.xml。resources.xml文件代表服务器上所有文件列表信息,由Android客户端来获取

<?xml version="1.0" encoding="utf-8"?>
<resources>
	<resource>
		<id>00001</id>
		<mp3Name>chunni.mp3</mp3Name>
		<mp3Size>4122018</mp3Size>
		<mp3Path>http://192.168.2.115:8080/mp3</mp3Path>
		
	</resource>
	<resource>
		<id>00002</id>
		<mp3Name>17sui.mp3</mp3Name>
		<mp3Size>3856845</mp3Size>
		<mp3Path>http://192.168.2.115:8080/mp3</mp3Path>
	</resource>
	<resource>
		<id>00003</id>
		<mp3Name>jintian.mp3</mp3Name>
		<mp3Size>3623184</mp3Size>
		<mp3Path>http://192.168.2.115:8080/mp3</mp3Path>
	</resource>
</resources>

 

 

3.2、构建服务器文件列表页面

1.使用eclipse开发工具创建Mp3RemoteActivity类和对应布局文件activity_mp3_remote.xml。由于使用ListView控件,这里我使用自定义的ListView内容布局list.xml。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/mp3Name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true" />

    <TextView
        android:id="@+id/mp3Size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true" />

    <TextView
        android:id="@+id/mp3Path"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="invisible" />

</RelativeLayout>

2.修改activity_mp3_remote.xml布局文件,增加ListView控件,id值设为系统自带andorid.R.id.list。

<ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

3.修改Mp3RemoteActivity类,让它去继承ListActivity类。重写onCreate方法,首先在该方法中注册自定义下载广播接收器,然后在该读取服务器文件列表,并更新ListView控件的数据。

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_mp3_remote);
		
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(Mp3Contant.downloadaction);
		//注册下载文件广播接收
		registerReceiver(new DownloadReceiver(), intentFilter);
		//更新ListView数据
		update();
	}
	

4.更新MP3列表使用多线程去获取服务器上的数据,因为该过程可能会由于网络等原因导致Activity无响应,影响用户的体验度。

	/**
	 * 更新MP3列表
	 * 
	 * @author Alan
	 * @time 2015-7-21 下午3:53:24
	 */
	private void update(){
		//创建线程
		HandlerThread handlerThread = new HandlerThread("updateUI");
		handlerThread.start();
		//创建Handler
		Handler handler = new Handler(handlerThread.getLooper());
		//将Runnable加到Handler队列中
		handler.post(runnable);
	}

获取服务器文件列表后,并更新ListView控件的数据。由于在Android的UI是线程不安全,故而在Android4.0版本及以上规定,更新UI不能通过其他线程来更新,只能调用主线程更新UI。对于更新UI的问题,Android提供了多种处理方式,第一Activity类中有一个runOnUiThread()方法,该方法中的内容将在UI线程执行,故而可将UI更新的方法放置在该方法中;第二种是使用多线程HandlerThread和Handler处理类的回调函数处理;第三种是通过广播机制也可实现,目前只了解过这三种方式,亲测都ok,本案例将使用runOnUiThread方法来完成。

		@Override
		public void run() {
			//获取下载内容
			String content = DownloadUtil.readFile(Mp3Contant.serverDefaultMp3Path,Mp3Contant.serverDefaultResourceName);
			//将下载内容包装成InputSource对象
			InputSource inputSource = new InputSource(new StringReader(content));
			//解析MP3内容列表
			List<Mp3> mp3s = XParse.parse(inputSource);
			//创建ListAdapter适配器
			adapter = convertListAdapterByMp3s(mp3s);
			
			//更新UI处理必须在UI线程上
			runOnUiThread(new Runnable() {
				
				@Override
				public void run() {
					// 更新ListView的ListAdapter适配器
					Mp3RemoteActivity.this.setListAdapter(adapter);
				}
			});
		}
	};

还有下载文件代码和解析Xml文件的代码未列出这些都属于Java Se部分的内容,具体可看源代码。

5.重写onListItemClick方法(listview点击事件),在该方法中使用多线程来下载服务器上的mp3文件。

	/**
	 * listview点击事件
	 * @param l
	 * @param v
	 * @param position
	 * @param id
	 * @author Alan
	 * @time 2015-7-21 下午4:11:54
	 */
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		HashMap<String, String> hashMap = (HashMap<String, String>) l.getItemAtPosition(position);
		String mp3Name = hashMap.get("mp3Name");//获取MP3名称
		String mp3Path = hashMap.get("mp3Path");//获取MP3路径
		
		//Mp3下载采用多线程进行
		HandlerThread thread  = new HandlerThread("downloadFile");
		thread.start();
		Handler handler = new Handler(thread.getLooper());
		//开始处理Mp3文件下载
		handler.post(new MyRunnable(mp3Path, mp3Name));
	}

下载文件成功后,通过Android的广播机制,发布广播,在页面上提示下载成功。

	class MyRunnable implements Runnable{

		private String mp3Name;
		private String mp3Path;
		
		public MyRunnable(String mp3Path,String mp3Name){
			this.mp3Path = mp3Path;
			this.mp3Name = mp3Name;
		}
		
		@Override
		public void run() {
			//下载文件
			DownloadUtil.downloadFile(mp3Path, mp3Name,Mp3Contant.defaultMp3Path,mp3Name);
			//发送广播
			Intent intent = new Intent();
			intent.setAction(Mp3Contant.downloadaction);
			intent.putExtra("msg", mp3Name+"下载成功");
			sendBroadcast(intent);
		}
		
	}

以下是广播接收器的代码,主要是提示最终下载结果的消息。

        @Override
	public void onReceive(Context context, Intent intent) {
		Bundle bundle = intent.getExtras();
		String msg = (String) bundle.get("msg");
		//提示消息
		Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
	}

6.重写onCreateOptionsMenu方法去添加菜单按钮,并重写onOptionsItemSelected方法去处理菜单按钮的具体监听事件。

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		//添加设置按钮
		menu.add(1,SETTING,1,R.string.setting);
		//添加关于按钮
		menu.add(1,ABOUT,2,R.string.about);
		//添加更新按钮
		menu.add(1,UPDATE,3,R.string.update);
		
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == UPDATE) {
			//更新列表
			update();
		}else if(id == SETTING){
			//进入设置界面
			Intent intent = new Intent();
			intent.setClass(this, SettingActivity.class);
			startActivity(intent);
		}else if(id == ABOUT){
			//进入关于界面
			Intent intent = new Intent();
			intent.setClass(this, AboutActivity.class);
			startActivity(intent);
		}
		return super.onOptionsItemSelected(item);
	}

3.3、构建本地文件列表展示页面

1.创建Mp3LocalActivity类和对应的布局文件activity_mp3_local.xml。

2.修改布局文件内容,添加ListView控件,并添加播放、上一首、下一首三个按钮,具体布局如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.cygoat.mp3.activity.Mp3LocalActivity" >

    <LinearLayout
        android:id="@+id/linearlayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <ListView
            android:id="@android:id/list"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <Button
            android:id="@+id/prev"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/prev" />

        <Button
            android:id="@+id/play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="@string/start"/>

        <Button
            android:id="@+id/next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="@string/next" />
    </RelativeLayout>

</LinearLayout>

3.修改Mp3LocalActivity类,重写onCreate方法,在该方法中为按钮注册监听器,并更新ListView数据。

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_mp3_local);
		prev = (Button) findViewById(R.id.prev);
		play = (Button) findViewById(R.id.play);
		next = (Button) findViewById(R.id.next);
		//添加监听器
		prev.setOnClickListener(this);
		play.setOnClickListener(this);
		next.setOnClickListener(this);
		//更新ListView数据
		update();
	}

更新ListView数据主要从本地Mp3目录中搜索mp3文件,然后展示。

	/**
	 * 更新MP3列表
	 * 
	 * @author Alan
	 * @time 2015-7-21 下午3:53:24
	 */
	private void update(){
		//获取Properties对象
		Properties properties = PropertiesUtil.getProperties(Mp3Contant.settingFileName);
		//获取MP3路径
		String mp3Path = properties.getProperty(Mp3Contant.CharContant.mp3Path);
		//获取mp3文件
		File[] files = getMp3Files(mp3Path);
		//将MP3文件转换ListAdapter
		ListAdapter adapter = convertListAdapterByFiles(files);
		//为Activity设置adapter
		this.setListAdapter(adapter);
	}

4.考虑到当从播放器回到主页时,播放器的Activity处于不可见状态,该Activity可能会被Java垃圾回收器回收(在Android优先级顺序由高到低:处于可见的Activity>Service>不可见Activity)。因此为了避免播放音乐资源被垃圾回收器回收,导致播放中断,故而使用Service组件来完成音乐播放。

音乐播放操作事件主要在点击播放、上一首、下一首按钮,和点击ListView中的数据项触发。

重写onListItemClick方法,在该方法中实现音乐播放的操作。代码如下

	/**
	 * listview点击事件
	 * @param l
	 * @param v
	 * @param position
	 * @param id
	 * @author Alan
	 * @time 2015-7-21 下午4:11:54
	 */
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		//创建跳转Intent实例
		Intent intent = new Intent();
		//将文件名称设置到Intent实例中
		intent.putExtra("fileName", getFullFileName(position));
		if(currPosition != position){
			intent.putExtra("isNew", true);
		}else{
			intent.putExtra("isNew", false);
		}
		intent.setClass(this, PlayService.class);
		//开启mp3播放服务
		startService(intent);
		//设置当前播放mp3歌曲位置
		currPosition = position;
	}

5.创建播放音乐服务PlayService类,在该类中实现音乐播放功能处理。处理音乐播放主要使用MediaPlayer类,由于该类使用比较简单,具体查看源代码。PlayService代码如下

package com.cygoat.mp3.service;

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

public class PlayService extends Service {

	private MediaPlayer mediaPlayer;
	
	//当前播放状态
	private static final int INIT_STATUS = 0;//初始化状态
	private static final int ACTIVE_STATUS = 1;//播放状态
	private static final int PAUSE_STATUS = 2;//暂停状态
	private static final int STOP_STATUS = 3;//停止状态
	//播放命令
	public static final int START_COMMAND = 1;//启动命令
	public static final int PAUSE_COMMAND = 2;//暂停命令
	public static final int STOP_COMMAND = 3;//停止命令
	
	private int playStatus = INIT_STATUS;
	
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		mediaPlayer = new MediaPlayer();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Bundle bundle = intent.getExtras();
		//取出文件名称变量和是否是切换歌曲播放变量
		String fileName = (String) bundle.get("fileName");
		boolean isNew = (Boolean) bundle.get("isNew");
		Integer command = (Integer) bundle.get("command");
		//播放
		play(fileName, isNew,command);
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}
	
	private void play(String fileName , boolean isNew , Integer command){
		//如果是切换新的歌曲,则直接播放
		if(isNew){
			active(fileName);
			return;
		}
		
		//同一首歌之间状态切换
		if((playStatus == INIT_STATUS || playStatus == STOP_STATUS) 
				&& ((command==null?START_COMMAND:command) ==START_COMMAND)){
			//当前歌曲是初始化和停止状态,如果此时下发播放命令,则开始播放
			active(fileName);
			return;
		}
		
		if(playStatus == ACTIVE_STATUS 
				&& ((command==null?PAUSE_COMMAND:command)==PAUSE_COMMAND)){
			//当前歌曲是播放状态,如果此时下发暂停命令,则暂停播放
			pause();
			return;
		}
		if(playStatus == PAUSE_STATUS 
				&& ((command==null?START_COMMAND:command)==START_COMMAND)){
			//当前歌曲是暂停状态,如果此时下发播放命令,则继续播放
			reActive();
			return;
		}
		
		if((playStatus == ACTIVE_STATUS || playStatus == PAUSE_STATUS) 
				&& ((command==null?STOP_COMMAND:command) ==STOP_COMMAND)){
			//当前歌曲状态是播放和暂停,如果此时下发停止命令,则停止播放
			stop();
			return;
		}
		
	}
	
	/**
	 * 播放歌曲
	 * @param fileName
	 * @author Alan
	 * @time 2015-7-21 下午7:31:24
	 */
	private void active(String fileName){
		try{
			mediaPlayer.reset();
			mediaPlayer.setDataSource(fileName);
			mediaPlayer.prepare();
			mediaPlayer.start();
			playStatus = ACTIVE_STATUS;
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	/**
	 * 暂停播放
	 * 
	 * @author Alan
	 * @time 2015-7-21 下午7:31:37
	 */
	private void pause(){
		mediaPlayer.pause();
		playStatus = PAUSE_STATUS;
	}
	
	/**
	 * 继续播放
	 * 
	 * @author Alan
	 * @time 2015-7-21 下午7:31:49
	 */
	private void reActive(){
		mediaPlayer.start();
		playStatus = ACTIVE_STATUS;
	}
	/**
	 * 停止播放
	 * 
	 * @author Alan
	 * @time 2015-7-21 下午8:20:49
	 */
	private void stop(){
		mediaPlayer.stop();
		playStatus = STOP_STATUS;
	}

}

6.重写onCreateOptionsMenu方法去添加菜单按钮,并重写onOptionsItemSelected方法去处理菜单按钮的具体监听事件。

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		//添加设置按钮
		menu.add(1,SETTING,1,R.string.setting);
		//添加关于按钮
		menu.add(1,ABOUT,2,R.string.about);
		//添加更新按钮
		menu.add(1,UPDATE,3,R.string.update);
		
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == UPDATE) {
			//更新列表
			update();
		}else if(id == SETTING){
			//进入设置界面
			Intent intent = new Intent();
			intent.setClass(this, SettingActivity.class);
			startActivity(intent);
		}else if(id == ABOUT){
			//进入关于界面
			Intent intent = new Intent();
			intent.setClass(this, AboutActivity.class);
			startActivity(intent);
		}
		return super.onOptionsItemSelected(item);
	}

3.4、构建切换标签主界面

1.创建MainActivity和对应布局文件activity_main.xml。

2.修改activity_main.xml布局文件,由于是使用TabActivity,该文件必须以TabHost作为根节点,根节点下必须包括TabWidget和FrameLayout。

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:padding="5dp" >

        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="5dp" />
    </LinearLayout>

</TabHost>

3.修改MainActivity继承TabActivity 。重写onCreate方法中将Mp3RemoteActivity和Mp3LocalActivity界面添加到主界面上的Tab切换页签上。

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//获取tabHost,即整个Tab
		TabHost tabHost = getTabHost();
		//创建Intent跳转对象
		Intent intent = new Intent();
		intent.setClass(this, Mp3LocalActivity.class);
		//新建一个标签页
		TabHost.TabSpec spec = tabHost.newTabSpec("mp3LocalActivity");
		//设置标签名称,还可设置图片
		spec.setIndicator("本地");
		//设置Intent跳转对象
		spec.setContent(intent);
		//添加标签页
		tabHost.addTab(spec);
		
		//创建Intent跳转对象
		intent = new Intent();
		intent.setClass(this, Mp3RemoteActivity.class);
		//新建一个标签页
		spec = tabHost.newTabSpec("mp3RemoteActivity");
		//设置标签名称,还可设置图片
		spec.setIndicator("远程");
		//设置Intent跳转对象
		spec.setContent(intent);
		//添加标签页
		tabHost.addTab(spec);
	}

3.4、构建设置界面

1.创建SettingActivity和对应布局文件activity_setting。

2.修改布局文件,在布局文件中主要添加Mp3文件目录的文本框。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <TextView
        android:id="@+id/mp3PathTextview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/mp3Path" />

    <EditText
        android:id="@+id/mp3Path"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/mp3PathTextview"
        android:hint="@string/mp3Path" />

    <Button
        android:id="@+id/save"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="@string/save" />

</RelativeLayout>

3.修改SettingActivity文件,在该类中主要是获取配置文件信息和保存设置信息到配置文件中。

package com.cygoat.mp3.activity;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;

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;
import android.widget.EditText;
import android.widget.Toast;

import com.cygoat.mp3.Mp3Contant;
import com.cygoat.mp3.R;
import com.cygoat.util.IOUtil;

public class SettingActivity extends Activity {

	private EditText mp3PathText;
	private Button save;
	private Properties properties = new Properties();
	
	private static final String MP3_PATH = "mp3Path";
	

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_setting);
		mp3PathText = (EditText) findViewById(R.id.mp3Path);
		save = (Button) findViewById(R.id.save);
		getSetting();
		showSetting();
		
		save.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				File file = new File(Mp3Contant.settingFileName);
				FileOutputStream fileOutputStream = null;
				try {
					fileOutputStream = new FileOutputStream(file);
					properties.put(MP3_PATH, mp3PathText.getText().toString());
					properties.store(fileOutputStream, "mp3Path");
					Toast.makeText(SettingActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
					Intent intent = new Intent();
					intent.setClass(SettingActivity.this, MainActivity.class);
					startActivity(intent);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					IOUtil.close(fileOutputStream);
				}
			}
		});
	}
	
	private void showSetting(){
		mp3PathText.setText(properties.getProperty(MP3_PATH));
	}

	private void getSetting() {
		File file = new File(Mp3Contant.settingFileName);
		FileInputStream fileInputStream = null;
		try {
			if (!file.exists()) {
				//文件不存在则创建文件
				file.createNewFile();
			}
			//构建文件输入流
			fileInputStream = new FileInputStream(file);
			//将文件流装载进Properties对象中
			properties.load(fileInputStream);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			IOUtil.close(fileInputStream);
		}
	}
}

3.5、构建关于界面

创建AboutActivity和对应布局文件activity_about.xml。由于该类比较简单,详情可见源代码。

以上可能有Java部分的源代码没有去说明,像xml文件解析、远程文件下载、Properties文件解析和保存等。这些代码都属于Java部分,有兴趣的读者查看Java相关内容。

运行效果如下



 



 



 



 
 
 

源代码如附件

猜你喜欢

转载自ylxy3058.iteye.com/blog/2229979