第一篇:android實驗報告
移動應(yīng)用開發(fā)實驗報告
實驗名稱
音樂播放器
班
級
學(xué)
號
姓
名
指導(dǎo)教師
實驗成績
2016 年04月
一、實驗?zāi)康?/p>
本項目是一款基于Android手機平臺的音樂播放器,使Android手機擁有個性的多媒體播放器,使手機顯得更生動靈活化,與人們更為接近,讓手機主人隨時隨地處于音樂視頻的旋律之中。使人們的生活更加多樣化。也使設(shè)計者更加熟練Android的技術(shù)和其它在市場上的特點。
二、實驗內(nèi)容及要求
在其中寫清楚這個實驗具體要你做什么,怎么做,要達(dá)到什么樣的效果等。本設(shè)計實現(xiàn)的主要功能是播放Mp3,Wav多種格式的音樂文件,并且能夠控制播放,暫停,停止,下一首,上一首播放列等基本播放控制功能,界面簡明,操作簡單。
三、實驗方案設(shè)計
在其中寫清楚你的程序的詳細(xì)設(shè)計,用流程圖配文字的形式描述。如果其中涉及到算法,一定要把算法闡述清楚。
3.1.1假設(shè)安裝了音樂播放器的用戶是系統(tǒng)的主要設(shè)計對象,其擁有以下操作,啟動軟件、播放音樂、暫停播放、停止播放、退出軟件,其用例圖如下
圖2.1 播放器基本用例圖
3.1.2用例分析 ?用例名稱:啟動軟件 參與者:用戶
目標(biāo):使得用戶啟動軟件并加載手機和sd卡上的音頻文件到播放列表 前置條件:無
基本事件流:1.用戶啟動軟件
2.播放器將播放列表中的當(dāng)前的歌曲
?用例名稱:播放 參與者:用戶
目標(biāo):使得用戶可以播放在播放列表中選中的歌曲 前置條件:播放器正在運行
基本事件流:1.用戶單擊“播放”按鈕
2.播放器將播放列表中的當(dāng)前的歌曲
?用例名稱:暫停 參與者:用戶
目標(biāo):使得用戶可以暫停正在播放的歌曲 前置條件:歌曲正在播放且未停止和暫停 基本事件流:1.用戶單擊“暫停”按鈕
2.播放器將暫停當(dāng)前的歌曲
④用例名稱:停止 參與者:用戶
目標(biāo):使得用戶可以停止正在播放的歌曲 前置條件:歌曲正在播放或暫停 基本事件流:1.用戶單擊“停止”按鈕
2.播放器將停止當(dāng)前播放的歌曲
⑤用例名稱:推出 參與者:用戶
目標(biāo):使得用戶退出或者后臺播放音樂 前置條件:程序在運行
基本事件流:1.用戶按返回鍵
2.播放器退出或者進(jìn)入后臺播放
四、實驗測試
Step1.啟動軟件后,軟件自動檢索手機和sd卡的音頻文件,并組織顯示成列表.Step2.點擊列表的歌曲名字。
Step3.播放音樂。
Step4.點擊暫停,音樂暫停
Step5.點擊播放 轉(zhuǎn)到step3 Step6.點擊停止 停止播放音樂
Step7.點擊退出,若音樂處于播放狀態(tài),則音樂轉(zhuǎn)向后臺播放,界面退出。
Step8.點擊退戶,若音樂處于暫停或者停止?fàn)顟B(tài),直接退出。
音樂播放器流程圖
4.1MusicInfoController類
這個類繼承于service,是播放音樂的服務(wù)類。播放音樂,暫停音樂,停止播放等操作都封裝在這個類中。
主要的執(zhí)行動作有:
4.1.1.類啟動 onCreate(){
mMediaPlayer = new MediaPlayer();//分配一個播放對象
mMediaPlayer.setOnPreparedListener(mPrepareListener);//綁定之前
mMediaPlayer.setOnCompletionListener(mCompleteListener);//綁定之 后
}
4.1.2.服務(wù)綁定activity
MediaPlayer.OnCompletionListener mCompleteListener = new
MediaPlayer.OnCompletionListener()//實例化一個綁定監(jiān)聽器的匿名類
{
public void onCompletion(MediaPlayer mp)//完成綁定后
{
broadcastEvent(PLAY_COMPLETED);//廣播消息
}
};
4.2MusicInfoController類
這個類主要用于獲取android系統(tǒng)中的音頻文件,并提供訪問接口,它是一個單例類。
4.2.1獲得播放文件列表
private Cursor query(Uri uri, String[] prjs, String selections, String[] selectArgs, String order){ ContentResolver resolver = pApp.getContentResolver();//取得一個連接對象if(resolver == null){
return null;
}
return resolver.query(uri, prjs, selections, selectArgs, order);} public Cursor getAllSongs(){
return query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);//查詢ContentResolver 的所有音頻文件
} 4.3MusicList類
改類繼承于ListActivity,主要用于顯示歌曲列表,并且封裝部分操作,以及與父級目標(biāo)通信。
4.3.1播放
protected void onListItemClick(ListView l, View v, int position, long id){ //歌曲列表的某項被點擊
super.onListItemClick(l, v, position, id);
if(mCursor == null ||mCursor.getCount()== 0){
return;
}
mCursor.moveToPosition(position);//游標(biāo)移動到當(dāng)前路徑
String url = mCursor.getString(mCursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));//取得絕對路徑
mMusicPlayerService.setDataSource(url);//傳遞絕對路徑
mMusicPlayerService.start();//播放音樂
}
4.3.2暫停/播放
mPlayPauseButton.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
if(mMusicPlayerService!= null &&
mMusicPlayerService.isPlaying()){
mMusicPlayerService.pause();//音樂播放的服務(wù)暫停
mPlayPauseButton.setText(R.string.play);//改變按鈕文字
} else if(mMusicPlayerService!= null){
mMusicPlayerService.start();//如果已經(jīng)是暫停,則播放音樂
mPlayPauseButton.setText(R.string.pause);//改變文字
}
}
});
4.3.3停止
mStopButton.setOnClickListener(new Button.OnClickListener(){
public void onClick(View v){
// Perform action on click
if(mMusicPlayerService!= null){
mTextView.setVisibility(View.VISIBLE);//改變文字狀態(tài)
mPlayPauseButton.setVisibility(View.INVISIBLE);//隱藏按鈕
mStopButton.setVisibility(View.INVISIBLE);//隱藏停止按鈕
mMusicPlayerService.stop();//后臺音樂停止播放
}
}
});4.4MusicPlayerApp類
該類繼承與Application,是程序的生存類。可以標(biāo)識音樂播放器的生命周期,包括音樂在后臺播放等。
4.4.1單例模式
public void onCreate(){
super.onCreate();
mMusicInfoController = MusicInfoController.getInstance(this);//返回該類的一個唯一實例
}
public MusicInfoController getMusicInfoController(){
return mMusicInfoController;}
五、程序的使用手冊
系統(tǒng)編譯生成apk文件,將apk文件拷到手機或者sd卡中,直接打開即可安裝,或者安裝360手機助手通過usb調(diào)試的方式進(jìn)行安裝。
啟動軟件后,加載歌曲列表現(xiàn)在這個界面上,如01表示歌曲名,unknown表示歌曲的演唱者
軟件啟動界面
從加載的歌曲列表中點擊要播放的歌曲,開始播放
音樂播放界面
六、心得體會
通過對Android手機平臺的音樂播放器軟件的開發(fā),使我對Android音樂播放器系統(tǒng)的整體設(shè)計有一個深入的了解,對整個流程也會有一個清晰的認(rèn)識。開發(fā)Android音樂播放器,要抓住開發(fā)的核心部分,音樂播放器大體由播放主界面、播放列表、菜單、播放設(shè)置、文件瀏覽、歌曲搜索六大核心組成,只要掌握了這六部分的開發(fā),音樂播放器就能初具規(guī)模。而其它的功能都是在這六個功能的基礎(chǔ)上去補充添加的,但是這是功能的確是必不可少的功能,否則就不能算是音樂播放器了。
第二篇:Android實驗報告—網(wǎng)絡(luò)通信
實驗三
Android網(wǎng)絡(luò)通信
實驗?zāi)康模?/p>
本實驗的目的是使學(xué)生深入了解利用Intent實現(xiàn)進(jìn)程間的通信過程。學(xué)會利用Intent進(jìn)行Activity的跳轉(zhuǎn),以及鏈接網(wǎng)頁信息;學(xué)會利用Intent將其他Activity的信息返回到Activity中的方法。體會Activity間通信的過程。
實驗要求:
編程實現(xiàn)下述功能:主界面上有一個“登錄”按鈕和“鏈接網(wǎng)頁”按鈕,點擊“登錄”按鈕后打開一個新的Activity;新的Activity上面有輸入用戶名和密碼的控件(如下圖所示)點擊“鏈接網(wǎng)頁”按鈕,新的Activity上面有輸入Uri信息的控件,可以鏈接到相應(yīng)的網(wǎng)站,在用戶關(guān)閉這個Activity后,返回到主界面中
程序界面如下圖所示:
[實現(xiàn)提示]
1、建立Android工程,其中 工程名稱:WebCommunication579
包名稱:cn.edu.bistu.dj1001.WebCommunication579 Activity名稱:WebCommunication579
2、工程建立完畢后,首先進(jìn)行界面設(shè)計,建立相應(yīng)的子Layout界面
3、在工程中添加相應(yīng)的.java文件,處理各個Activity的事件響應(yīng)
4、在Manifest中添加新建的Activity信息,進(jìn)行注冊。
程序源碼:
主界面java文件代碼: package cn.deu.bistu.dj1001.WebCommunication579;
import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;
public class WebCommunication579 extends Activity { private Button btnLogin,btnGoToWeb;private TextView show;private static final int SUBACTIVITY1 = 1;@Override
public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);setContentView(R.layout.main);btnLogin=(Button)findViewById(R.id.btnLogin);btnGoToWeb=(Button)findViewById(R.id.btnGoToWeb);show=(TextView)findViewById(R.id.A1show);
btnLogin.setOnClickListener(new OnClickListener(){ public void onClick(View v){ Intent intent = new Intent(WebCommunication592.this, activity1.class);
startActivityForResult(intent, SUBACTIVITY1);
}});btnGoToWeb.setOnClickListener(new OnClickListener(){ public void onClick(View v){ Intent intent = new Intent(WebCommunication592.this, activity2.class);startActivity(intent);}});} protected void onActivityResult(int requestCode, int resultCode, Intent data){ super.onActivityResult(requestCode, resultCode, data);switch(requestCode){ case SUBACTIVITY1: if(resultCode == RESULT_OK){Uri uriData = data.getData();show.setText(uriData.toString());} break;}};} 界面一java文件代碼:
package cn.deu.bistu.dj1001.WebCommunication579;
import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;
public class activity1 extends Activity { private Button btnOK,btnCancel;private EditText edtInput;public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);setContentView(R.layout.activity1);edtInput=(EditText)findViewById(R.id.edtA1Input);btnOK=(Button)findViewById(R.id.btnA1OK);btnCancel=(Button)findViewById(R.id.btnA1Cancel);btnOK.setOnClickListener(new OnClickListener(){
public void onClick(View v){ String uriString = edtInput.getText().toString();Uri data = Uri.parse(uriString);Intent result = new Intent(null, data);setResult(RESULT_OK, result);finish();}});btnCancel.setOnClickListener(new OnClickListener(){ public void onClick(View view){ finish();}});}} 界面二java文件代碼:
package cn.deu.bistu.dj1001.WebCommunication579;
import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;
import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;
public class activity2 extends Activity { private EditText edtInput;private Button btnOK,btnCancel;public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);setContentView(R.layout.activity2);edtInput=(EditText)findViewById(R.id.edtA2Input);btnOK=(Button)findViewById(R.id.btnA2OK);btnCancel=(Button)findViewById(R.id.btnA2Cancel);btnOK.setOnClickListener(new OnClickListener(){ public void onClick(View v){ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(edtInput.getText().toString()));startActivity(intent);}});btnCancel.setOnClickListener(new OnClickListener(){
public void onClick(View v){
finish();
}});}} 主界面的xml文件代碼:
xmlns:android=“http://schemas.android.com/apk/res/android” android:orientation=“Horizontal” android:layout_width=“fill_parent” android:layout_height=“fill_parent”> android:text=“" android:id=”@+id/A1show“ android:layout_width=”wrap_content“ android:layout_height=”wrap_content“>
界面一的xml文件代碼:
android:orientation=”Horizontal“ android:layout_width=”fill_parent“ android:layout_height=”fill_parent“ xmlns:android=”http://schemas.android.com/apk/res/android“> android:layout_width=”wrap_content“ android:layout_height=”wrap_content“> android:text=”用戶名和密碼:“ android:layout_width=”wrap_content“ android:layout_height=”wrap_content“> android:text=”“ android:id=”@+id/edtA1Input“ android:layout_width=”wrap_content“ android:layout_height=”wrap_content“> android:layout_width=”wrap_content“ android:layout_height=”wrap_content“>
界面二的xml文件代碼: xmlns:android=”http://schemas.android.com/apk/res/android“> android:text=”“ android:id=”@+id/edtA2Input“ android:layout_width=”match_parent“ android:layout_height=”wrap_content“>
程序運行結(jié)果:
程序包:
主界面:
點擊登錄按鈕后:
點擊確定按鈕后:
點擊鏈接網(wǎng)頁按鈕后:
點擊確定按鈕后:
實驗心得體會:
通過本次實驗深入了解了Intent實現(xiàn)進(jìn)程間的通信過程。熟悉了利用Intent將其他Activity的信息返回到Activity中的方法,可以更熟練的使用安卓編程軟件。
第三篇:Android實驗報告—UI設(shè)計(定稿)
Android UI設(shè)計
實驗?zāi)康模?/p>
本實驗的目的是使學(xué)生深入了解Android程序框架結(jié)構(gòu)、了解和掌握Android界面設(shè)計和界面編程。通過程序設(shè)計,掌握常用界面控件、菜單、以及界面事件的響應(yīng)。
實驗要求:
設(shè)計程序?qū)崿F(xiàn)一個電子菜單,應(yīng)具有顯示菜單功能和選菜功能。通過選擇,將選中的菜單選項在界面做顯示,如下圖:
[實現(xiàn)提示]
1、建立Android工程,其中 工程名稱:MenuSelect579 應(yīng)用名稱:MenuSelect579 包名稱:cn.edu.bistu.dj1001.MenuSelect579 Activity名稱:MenuSelect579
2、工程建立完畢后,進(jìn)行相應(yīng)界面設(shè)計,再編寫Java文件
程序源碼
package cn.edu.bistu.dj1001.MenuSelect579;import android.app.Activity;
import android.os.Bundle;import android.view.ContextMenu;import android.view.ContextMenu.ContextMenuInfo;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.TextView;public class MenuSelect579 extends Activity {
/** Called when the activity is first created.*/
TextView LabelView = null;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LabelView =(TextView)findViewById(R.id.label);registerForContextMenu(LabelView);
}
final static int CONTEXT_MENU_1 = Menu.FIRST;
final static int CONTEXT_MENU_2 = Menu.FIRST+1;
final static int CONTEXT_MENU_3 = Menu.FIRST+2;
@Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo){
menu.setHeaderTitle(“今日菜單”);
menu.add(0, CONTEXT_MENU_1, 0,“宮保雞丁”);
menu.add(0, CONTEXT_MENU_2, 1,“干煸豆角”);
menu.add(0, CONTEXT_MENU_3, 2,“魚香肉絲”);
}
@Override
}
public boolean onContextItemSelected(MenuItem item){
} switch(item.getItemId()){
case CONTEXT_MENU_1: LabelView.setText(“宮保雞丁”);return true;case CONTEXT_MENU_2: LabelView.setText(“干煸豆角”);return true;case CONTEXT_MENU_3: LabelView.setText(“魚香肉絲”);return true;} return false;
程序運行結(jié)果:
實驗心得體會:(可選)
通過本次實驗熟悉了android的界面設(shè)計簡單方法和界面編程,鍛煉了實際動手能力,熟悉了 Android程序框架結(jié)構(gòu)、Android界面設(shè)通過程序設(shè)計,掌握了常用界面控件、菜單、以及界面事件的響應(yīng)。
第四篇:Android實驗格式簡易計算器實驗報告
實驗報告
2013-2014 學(xué)年第2學(xué)期
課程名稱:嵌入式操作系統(tǒng)
實驗題目:簡易計算器的設(shè)計與實現(xiàn)
專業(yè):計算機科學(xué)與技術(shù)、信息處理(是什么專業(yè),寫什么專業(yè))班級:計算本1101(按自己班級填寫)
日期填寫 2014年4月 8日
實驗題目:簡易計算器的設(shè)計與實現(xiàn)
實驗類型:上機實驗
一、實驗?zāi)康募耙?/p>
1.掌握線性布局的應(yīng)用;
2.掌握表格布局的應(yīng)用;
3.掌握數(shù)組的應(yīng)用;
4.掌握如何Button組件的使用;
5.掌握代碼中訪問布局組件的方法;
6.掌握特定組件的事件設(shè)計方法。
二、實驗儀器設(shè)備與軟件環(huán)境
1、電腦。
2、Android集成開發(fā)工具adt-bundle。
三、實驗過程
1、布局設(shè)計
…這部分自己填
2.程序設(shè)計
…這部分自己填
第五篇:Android 3D相冊實驗報告
中原工學(xué)院計算機學(xué)院 軟件平臺開發(fā)技術(shù)
大作業(yè)
專 業(yè): 軟件工程 班 級: 軟件121 作品名稱: 3D相冊 姓 名: 辛俊閃 學(xué) 號: 201200834101 指導(dǎo)教師: 劉鳳華
2015年 6 月 15 日
一、設(shè)計目的
奔著讓二維的手機照片能夠顯示出3D的立體效果,讓我們的相冊更加炫的目的,我初步的想法是開發(fā)一個基于android平臺的手機相冊小應(yīng)用。
二、作品簡介
該應(yīng)用是基于android開發(fā),將相冊置于立體空間中呈現(xiàn),并且可以通過用手指橫向滑動手機屏幕的方式來選擇所有瀏覽的圖片,在滑動過程中相冊的旋轉(zhuǎn)同時帶有慣性因素,使場景效果更自然、更人性化,手指點擊一張照片可以進(jìn)入單獨顯示對應(yīng)照片界面,在該界面操作左滑右滑可以切換照片下一張上一張。在瀏覽完成后,可以按返回鍵跳轉(zhuǎn)回相冊顯示。
三、設(shè)計思路
3.1 用到的主要技術(shù)
本項目開發(fā)過程中,用到了OpenGL ES中的圖形繪制技術(shù),包括紋理映射技術(shù)、物體旋轉(zhuǎn)技術(shù)glRotatef()、物體的平移技術(shù)glTranslatef(),并且應(yīng)用到了屏幕觸控技術(shù)。
3.2 相關(guān)技術(shù)難點學(xué)習(xí)
(1)android開發(fā)中關(guān)于GLSurfaceView簡介
SDK 中的 android.opengl.GLSurfaceView 類提供如下功能: 在 OpenGL ES 和 View 系統(tǒng)之間建立聯(lián)系;
使得 OpenGL ES 可以工作在 Activity 生命周期中; 可選擇合適的 frame buffer 像素格式;
創(chuàng)建并管理一個單獨的渲染線程,可以實現(xiàn)平滑的動畫; 提供 debugging 工具和 API。
GLSurfaceView.Render 接口有三個方法:
onSurfaceCreated():該方法在渲染開始前調(diào)用,OpenGL ES 的繪制上下文被重建時也會被調(diào)用。當(dāng) activity 暫停時繪制上下文會丟失,當(dāng) activity 繼續(xù)時,繪制上下文會被重建。另外,創(chuàng)建長期存在的 OpenGL 資源(如 texture)往往也在這里進(jìn)行。
onSurfaceChanged():當(dāng) surface 的尺寸發(fā)生改變時該方法被調(diào)用。往往在這里設(shè)置 viewport。若你的 camera 是固定的,也可以在這里設(shè)置 camera。
onDrawFrame():每幀都通過該方法進(jìn)行繪制。繪制時通常先調(diào)用 glClear 函數(shù)來清空 framebuffer,然后在調(diào)用 OpenGL ES 的起它的接口進(jìn)行繪制。
(2)初始化GLSurfaceView
初始化過程其實僅需要你使用setRenderer(Renderer)設(shè)置一個渲染(render)。當(dāng)然,你也可以修改GLSurfaceView一些默認(rèn)配置。
* setDebugFlags(int)* setEGLConfigChooser(boolean)* setEGLConfigChooser(EGLConfigChooser)* setEGLConfigChooser(int, int, int, int, int, int)* setGLWrapper(GLWrapper)
(3)定制android.view.Surface
GLSurfaceView默認(rèn)會創(chuàng)建像素格式為PixelFormat.RGB_565的surface。如果需要透明效果,調(diào)用 getHolder().setFormat(PixelFormat.TRANSLUCENT)。透明(TRANSLUCENT)的surface的像 素格式都是32位,每個色彩單元都是8位深度,像素格式是設(shè)備相關(guān)的,這意味著它可能是ARGB、RGBA或其它。
(4)選擇EGL配置
Android設(shè)備往往支持多種EGL配置,可以使用不同數(shù)目的通道(channel),也可以指定每個通道具有不同數(shù)目的位(bits)深度。因此,在渲染器工作之前就應(yīng)該指定EGL的配置。GLSurfaceView默認(rèn)EGL配置的像素格式為RGB_656,16位的深度緩存(depth buffer),默認(rèn)不開啟遮罩緩存(stencil buffer)。如果你要選擇不同的EGL配置,請使用setEGLConfigChooser方法中的一種。
(5)調(diào)試行為
你可以調(diào)用調(diào)試方法setDebugFlags(int)或setGLWrapper(GLSurfaceView.GLWrapper)來自定義 GLSurfaceView一些行為。在setRenderer方法之前或之后都可以調(diào)用調(diào)試方法,不過最好是在之前調(diào)用,這樣它們能立即生效。
(6)設(shè)置渲染器
總之,你必須調(diào)用setRenderer(GLSurfaceView.Renderer)來注冊一個GLSurfaceView.Renderer渲染器。渲染器負(fù)責(zé)真正的GL渲染工作。
(7)渲染模式
渲染器設(shè)定之后,你可以使用setRenderMode(int)指定渲染模式是按需(on demand)還是連續(xù)(continuous)。默認(rèn)是連續(xù)渲染。
(8)Activity生命周期
Activity窗口暫停(pause)或恢復(fù)(resume)時,GLSurfaceView都會收到通知,此時它的onPause方法和 onResume方法應(yīng)該被調(diào)用。這樣做是為了讓GLSurfaceView暫停或恢復(fù)它的渲染線程,以便它及時釋放或重建OpenGL的資源。
(9)事件處理
為了處理事件,一般都是繼承GLSurfaceView類并重載它的事件方法。但是由于GLSurfaceView是多線程操作,所以需要一些特殊的處 理。由于渲染器在獨立的渲染線程里,你應(yīng)該使用Java的跨線程機制跟渲染器通訊。queueEvent(Runnable)方法就是一種相對簡單的操 作
四、主要實現(xiàn)
4.1Activity類的開發(fā)過程
(1)重寫onCreate()方法
//設(shè)置全屏顯示
requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//橫屏顯示設(shè)置
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//設(shè)置屏幕分辨率
DisplayMetrics dm=new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(dm);mGLSurfaceView=new MySurfaceView(this);mGLSurfaceView.screenHeight=dm.heightPixels;mGLSurfaceView.screenWidth=dm.widthPixels;//獲取屏幕焦點并使其可觸控顯示
mGLSurfaceView.ratio=mGLSurfaceView.screenWidth/mGLSurfaceView.screenHeight;mGLSurfaceView.requestFocus();mGLSurfaceView.setFocusableInTouchMode(true);(2)重寫onResume()方法
//Activity恢復(fù)(resume)時,GLSurfaceView都會收到通知,此時它的onResume方法應(yīng)該被調(diào)用。這樣做是為了讓GLSurfaceView恢復(fù)它的渲染線程,以便它及時重建OpenGL的資源。
Constant.threadWork=false;mGLSurfaceView.onPause();
(3)重寫onPause()方法
//Activity窗口暫停(pause)時,GLSurfaceView都會收到通知,此時它的onPause方法應(yīng)該被調(diào)用。這樣做是為了讓GLSurfaceView暫停它的渲染線程,以便它及時釋放OpenGL的資源。
Constant.threadWork=true;
mGLSurfaceView.onResume();4.2界面實現(xiàn)類的開發(fā)過程
(1)界面類的構(gòu)造器部分
public MySurfaceView(Context context){ super(context);mRenderer = new SceneRenderer();//創(chuàng)建場景渲染器
setRenderer(mRenderer);
//設(shè)置渲染器
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//設(shè)置渲染模式為主動渲染連續(xù)渲染
//啟動一個線程根據(jù)當(dāng)前的角速度旋轉(zhuǎn)場景
threadWork=true;new Thread(){ public void run(){
while(threadWork)
{
.....} } }.start();}(2)按鍵單擊事件
public boolean onKeyDown(int keyCode, KeyEvent e){ if(keyCode==4)
} {//若按下的是返回鍵
if(isCheck)
{//若在detail場景中則回主場景
isCheck=false;} else
{//若在主場景中則退出程序
System.exit(0);} } return true;(3)屏幕觸控事件回調(diào)方法
public boolean onTouchEvent(MotionEvent e){
if(isCheck){//若在detail中
float bx = e.getX();//獲取觸控點X坐標(biāo)
dbx = bxmPreviousX;//計算X向觸控位移
float dy = y-mPreviousY;//計算Y向觸控位移
long currTime=System.currentTimeMillis();//獲取當(dāng)前時間戳 單位為毫秒
long timeSpan=(currTime-previousTime)/10;//計算兩次觸控事件之間的時間差
switch(e.getAction()){ case MotionEvent.ACTION_DOWN: isMove=false;break;case MotionEvent.ACTION_MOVE:
if(Math.abs(dx)>5||Math.abs(dy)>5){//觸控位移大于閾值則進(jìn)入移動狀態(tài)
isMove=true;} if(isMove){//若在移動狀態(tài)則計算角度變化速度
if(timeSpan!=0){
yAngleV=dx * TOUCH_SCALE_FACTOR/timeSpan;} } break;case MotionEvent.ACTION_UP:
//若在非移動狀態(tài)且角度速度為0則看選中的是哪幅照片來顯示 if(!isMove&&yAngleV==0){ //折算出觸控點在NEAR面上的位置
float nearX=(x-screenWidth/2)*ratio/(screenWidth/2);float nearY=(screenHeight/2-y)/(screenHeight/2);
//先判斷點下去的是左邊還是右邊 if(x>screenWidth/2)
{//右邊
ArrayList
for(int i=0;i
{
//計算此幅照片的角度
float tempAngle=(i*PHOTO_ANGLE_SPAN+yAngle)%360;
//若角度在270到360范圍內(nèi)則在右邊的前面
if(tempAngle>270&&tempAngle<360)
{
al.add(new
CandidataDis(tempAngle-270,tempAngle,i));
}
} //根據(jù)與270度的夾角排序,夾角小的排在前面 Collections.sort(al);
//遍歷候選列表誰在X范圍內(nèi)誰單獨顯示
currIndex=-1;
for(CandidataDis cd:al)
{
if(cd.isInXRange(nearX,nearY))
{
currIndex=cd.index;
break;
}
}
}
else
{
ArrayList
for(int i=0;i
{
//計算此幅照片的角度
float tempAngle=(i*PHOTO_ANGLE_SPAN+yAngle)%360;//若角度在180到270范圍內(nèi)則在左邊的前面 if(tempAngle>180&&tempAngle<270){
al.add(new CandidataDis(270-tempAngle,tempAngle,i));
}
}
//根據(jù)與270度的夾角排序,夾角小的排在前面 Collections.sort(al);//遍歷候選列表誰在X范圍內(nèi)誰單獨顯示
currIndex=-1;for(CandidataDis cd:al){ if(cd.isInXRange(nearX,nearY)){
currIndex=cd.index;
break;} } }
//若有選中照片,則設(shè)置進(jìn)入detail顯示狀態(tài)
if(currIndex!=-1)
{
isCheck=true;
}
} isMove=false;break;} mPreviousX = x;//記錄觸控筆位置
mPreviousY = y;//記錄觸控筆位置
previousTime=currTime;//記錄此次時間
return true;}(4)渲染器內(nèi)部類開發(fā)
private class SceneRenderer implements GLSurfaceView.Renderer { Board tp=new Board();//用于顯示照片的紋理矩形
@Override
public void onDrawFrame(GL10 gl){.....} }(5)初始化紋理
public int initTexture(GL10 gl,int drawableId)//textureId
{
....}
五、作品展示
(1)應(yīng)用主界面
通過滑動手機屏幕的方式改變照片的呈現(xiàn)角度。
(2)detail界面
通過單擊主界面的照片進(jìn)入detail界面,左右滑動查看上一張下一張。
六、心得體會
一直都很喜歡3D做成的軟件,但是對于android的3D開發(fā)卻從來沒有接觸過,本來是想著做一個3D游戲的,但是在學(xué)習(xí)的過程中發(fā)現(xiàn)對于一個初學(xué)者來說想在短時間內(nèi)做好一個3D游戲開發(fā)是非常困難,于是就選擇了一個相對簡單的3D相冊練練手。
在做這個小應(yīng)用的過程中也遇到了很多問題,比如說GLSurfaceView的應(yīng)用問題,渲染器的使用問題,緩沖區(qū)的分配回收問題等等,曾經(jīng)也為了這些新知識頭痛了很久,查找了很多網(wǎng)上的資料也專門從圖書館借了幾本關(guān)于3D開發(fā)的書,最后總算是把問題都解決了,雖然不能說完全理解,但是能夠靈活運用。