当前位置:  编程技术>移动开发
本页文章导读:
    ▪【挪动开发】ido手机阅读器        【移动开发】ido手机阅读器看到CSDN的征文活动“移动开发那点事”想起自己也做过几次移动项目,特此更文~ 本科课程项目索引:http://blog.csdn.net/xiaowei_cqu/article/details/7747205 ido是我除课程设.........
    ▪ 一段混音代码,留着避免往后用        一段混音代码,留着避免日后用很忙,废话不多说。 将mic录音和伴奏混合成wav。 public class MixRunnable implements Runnable { private MixRecorder context; /** * AudioRecord创建参数类 .........
    ▪ Activity加载形式和Task的关系       Activity加载模式和Task的关系 Activity的lanuchMode有四种standard(默认),singleTop,singleTask,singleInstance.   standard:每次都创建一个实例,默认将Activity加入到当前Task。   singleTop:启动的不是当前的Activity的.........

[1]【挪动开发】ido手机阅读器
    来源: 互联网  发布时间: 2014-02-18
【移动开发】ido手机阅读器

看到CSDN的征文活动“移动开发那点事”想起自己也做过几次移动项目,特此更文~

本科课程项目索引:http://blog.csdn.net/xiaowei_cqu/article/details/7747205

ido是我除课程设计外第一个完整的项目,现在看来很简单,但对当时大二的我来说感觉是很“大”的项目。项目起因是参加学校组织的软件设计比赛,战线略微有点长,过程也挺纠结的,中间几次都有犹豫“要不要做下去”的问题——主要因为不够自信,毕竟第一次参赛而且队伍里全是女生。幸运是最终还是坚持下来了,也一定程度成了我大学生活的分水岭。至少从那之后,心态好了很多。再次感谢最最靠谱儿的小鹿,当然还有翠翠,董姐。

先晒个视频~

ido手机阅读器

http://v.youku.com/v_show/id_XNDYwOTk4OTE2.html


项目简介
“i do”手机阅读器是应用于微软windows mobile6.0移动设备操作系统,基于.NET Compact Framework编程架构,c#编程语言支持的移动应用软件。旨在方便的进行手机阅读以及公务文章的阅读(doc格式的支持),方便windows mobile 用户随时读其所想,读其所需,随时随地可以看见自己所钟爱的小说或是所急需处理的文档文件,并且可以利用互联网上的海量资源进行搜索,随时下载随时阅读。
本软件几乎提供了手机阅读需要的所有功能,支持txt,doc等各种格式文本阅读,海量在线书城搜索下载,特效翻页,文本百分比跳转,字体无级缩放,颜色背景自定义设置,自动标签记录,快捷键设置,以及本地图书文本分类管理等。此外,本软件还提供了许多极为人性化的功能,包括最后阅读记录,切换阅读文本,显示系统时间,字典查询等,让用户尽享豪华读书体验!同时在界面设计上本软件也充分为用户考虑,简洁明了易于操作,并支持用户个人风格设置。

需求分析 系统用例如下:

最终根据用例确定了五大功能:
  • 阅读及文本处理:.txt格式文本阅读、.txt格式文本处理、文本跳转、成熟电子格式(.doc等)阅读
  • 图书管理:本地图书管理、本地图书分类、书签管理、阅读文本切换
  • 在线图书下载:在线书城连接、海量图书下载、下载图书分类管理
  • 人性化拓展功能:快捷键设置、显示系统时间、备忘录、蓝牙传送
  • 使用帮助:dodo帮助、dodo知道
具体功能模块图:


详细设计
设计时采用了所谓的“三层构架”,由上至下依次为表示层、业务逻辑层和数据访问层。(其实不太有必要,当时只是学习。。。)
  • 表示层提供项目的操作界面,用作隔离层,将用户界面与业务功能的实现分开;
  • 业务逻辑层包含各种业务规则和逻辑的实现;
  • 数据访问层包括数据实体并提供对数据实体操作的服务。
业务层
数据访问层用以完成数据的处理。包括图书、书签、网页书签、Rss订阅源、类型等的增删。数据以表的形式直接存储在本地XML文件中。

类图:


命名规则:

类名:“资源名Manager”,如BookManager类管理图书(Book)的类;以大写字母开头,包含多个单词的类名,所有单词连接在一起,每个单词首字母大写
属性:小写字母开始,第二个单词开始首字母大写
方法:首字母大写,多个单词租出的方法每个单词首字母大写

业务层

业务层用以完成程序的内部逻辑;业务规则及逻辑全部封装到类中以类方法的形式实现。

类图:


命名规则:

类名:“资源名Manager”,如BookManager类管理图书(Book)的类;以大写字母开头,包含多个单词的类名,所有单词连接在一起,每个单词首字母大写
属性:小写字母开始,第二个单词开始首字母大写
方法:首字母大写,多个单词租出的方法每个单词首字母大写

表示层
表现层最终呈现给用户。共有21个窗体,主窗体Form1引入自定义控件FlexStartMenu;函数重绘窗体使窗体最大化;通过静态变量Cstyle表示皮肤。

窗体导航图:



命名规则:

窗体名:“Form资源名”,如FormBooks为“图书管理”模块打开的窗体。所有单词首字母大写,
子模块打开的窗体为区分加The。如阅读时打开书签为FormTheBookmarks

界面设计
考虑到我们的用户面向的使广大的学生以及商务用户,此类用户对于用户的界面要求显然是简单易行,较容易操作,所以本电子阅读器采用的是GUI,方便商务用户可以快速的进行操作以节省时间,同时界面颜色简洁、明快、大方,对于学生用户也有一定的吸引力。

同时支持旋转


并有强大的更换皮肤功能——五套风格皮肤任你挑选

在阅读时可以进行其他的操作,如更改阅读设置,记录读书笔记等等,此处是在阅读时进行的设置,同样提供简单易行的图形界面,方便用户直观地进行各项设置。

项目阶段

第一阶段:需求分析及基本功能实现阶段

2010.4.22~2010.5.22 (五次例会)
选择windows moblie平台;学习C#、microsoft “How Can I ”系列;每周例会交流学习进度;模拟用户,收集需求;按模块分工,以实现功能为主

完成V1.1版本


实现阅读、字体设置等基本功能,实现背景更换、显示时间等,实现“网上书城”、手机红外线发送;完成《需求规格说明书》、《第一阶段报告》

第二阶段:详细设计及编码测试阶段 2010.5.23~2010.6.23 (三次例会)
概要设计,完成基本功能点;规范文档;幸运通过初赛

完成V1.2版本

实现添加书签、Word文件阅读规定功能;改进“网上书城”模块;增加RSS订阅;编写《概要设计说明书》《周例会纪要》

2010.6.23~2010.8.8 (四次例会)
暑假,实验室;请教老师,学长;从“手机项目”角度出发,增添更多功能

完成V2.1版本

实现XML存储,完成“图书管理”模块,实现word阅读;细化功能模块;升级《需求规格说明书》继续《周例会纪要》
第三阶段:用户调查反馈及产品版本升级
2010.9.1~2010.9.25(四次例会)
黑盒测试,软件升级;小范围发布,收集反馈信息;总结报告

完成V2.2版本

再次迭代,优化代码;调整页面,增加多种皮肤,完善帮助说明;完成《用户使用手册》《第三阶段报告》继续《周例会纪要》

项目总结

这是我们第一次完整的运用软件工程思想完成一个项目,也是第一次接触移动平台的应用软件开发。尤其是针对windows mobile系统的开发,虽然起初仅仅是因为习惯C#语言而选择了它,但真正接触后才发现,我们对windows系列产品的了解少之又少,我们掌握的软件开发的技能也贫乏有限。这次开发过程不仅仅让我们清楚地认识了自己的不足,更让我们借此机会进一步提高了软件开发的素养与技能。或许我们的成果在高手眼中很粗糙,但他凝结着我们的汗水与努力,记录着我们的进步与成长,更承载着我们的对未来自己能更强的期望!
最后附上答辩PPT的最后一页做为结束吧。


转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/8065769


4楼ruan_xiao23分钟前峥嵘岁月~n大腿一直照耀小弟前进的道路~3楼uehang2小时前个人觉得本次征文主题是“展现不同人不同的移动开发经历”,而你这篇估计是以前就有写过的项目文档吧,也许酸甜苦辣尽在这一份文档中,但我还是希望,你能写下如今自己对那次竞赛的回忆和感想,也给一些新人一点参考2楼harrygrs3小时前真的很不错的分析报告。1楼jonny_super3小时前[code=html]n大二能做成这样。膜拜。n[/code]

    
[2] 一段混音代码,留着避免往后用
    来源: 互联网  发布时间: 2014-02-18
一段混音代码,留着避免日后用

很忙,废话不多说。

将mic录音和伴奏混合成wav。

public class MixRunnable implements Runnable {
        private MixRecorder context;
 
        /**
         * AudioRecord创建参数类
         * 
         * @author christ
         */
        private static class RecorderParameter {
                // 音频获取源
                private static int audioSource = MediaRecorder.AudioSource.MIC;
                // 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
                private static final int sampleRateInHz = 44100;
                // 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
                private static final int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
                // 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
                private static final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
                // 缓冲区字节大小
                private static int bufferSizeInBytes;
        }
 
        // 设置运行状态
        private boolean isRunning = true;
        // AudioRecord对象
        private static AudioRecord recorder;
        // 设置MediaPlayer对象
        private static MediaPlayer mediaPlayer;
        // 伴奏文件
        private FileInputStream accompany;
        // 原唱文件
        private FileInputStream original;
        // 得分
        private int score;
        private boolean isFirst = true;
 
        /**
         * 混音评分线程的构造方法
         * 
         * @param accompany
         *                :伴奏文件路径
         * @param original
         *                :原唱文件路径
         * @throws FileNotFoundException
         */
        public MixRunnable(MixRecorder context, String accompany, String original) throws FileNotFoundException {
                this.context = context;
                this.accompany = new FileInputStream(accompany);
                this.original = new FileInputStream(original);
                creatAudioRecord();
                mediaPlayer = new MediaPlayer();
        }
 
        @Override
        public void run() {
                try {
                        // MediaPlayer准备
 
                        mediaPlayer.reset();
                        mediaPlayer.setDataSource("/sdcard/111.wav");
                        // mediaPlayer.setDataSource(accompany.getFD());
                        mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
 
                                @Override
                                public void onCompletion(MediaPlayer mp) {
                                        isRunning = false;
                                }
                        });
                        mediaPlayer.prepare();
                        // 跳过头
                        accompany.read(new byte[44]);
                        original.read(new byte[44]);
                        FileOutputStream fos = new FileOutputStream(new File("/sdcard/love.raw"));
                        // 开始读
                        byte[] sourceReader = new byte[RecorderParameter.bufferSizeInBytes * 2];
                        short[] sourceShortArray;
                        short[] audioReader = new short[sourceReader.length / 4];
                        mediaPlayer.start();
                        recorder.startRecording();
                        while (isRunning) {
                                int sourceReadSize = accompany.read(sourceReader, 0, sourceReader.length);
                                if (sourceReadSize < 0) {
                                        isRunning = false;
                                        continue;
                                }
                                sourceShortArray = byteToShortArray(sourceReader, sourceReadSize / 2);
                                recorder.read(audioReader, 0, audioReader.length);
                                short[] oneSecond = mixVoice(sourceShortArray, audioReader, sourceReadSize / 2);
                                byte[] outStream = new byte[oneSecond.length * 2];
                                for (int i = 0; i < oneSecond.length; i++) {
                                        byte[] b = shortToByteArray(oneSecond<i>);
                                        outStream[2 * i] = b[0];
                                        outStream[2 * i + 1] = b[1];
                                }
                                Log.d("mtime4", "" + System.currentTimeMillis());
                                fos.write(outStream);
                                // 评分
                                byte[] srcBuffer = new byte[outStream.length];
                                original.read(srcBuffer);
                                int x = score(byteToShortArray(srcBuffer, srcBuffer.length / 2), oneSecond);
                                System.out.println(x);
                        }
                        if (mediaPlayer.isPlaying()) {
                                mediaPlayer.stop();
                        }
                        recorder.release();
                        mediaPlayer.release();
                        fos.close();
                        copyWaveFile("/sdcard/love.raw", "/sdcard/haah.wav");
 
                } catch (Exception e) {
                        e.printStackTrace();
                }
 
        }
 
        /**
         * 创建AudioRecord对象方法
         */
        private void creatAudioRecord() {
                // 获得缓冲区字节大小
                RecorderParameter.bufferSizeInBytes = AudioRecord.getMinBufferSize(RecorderParameter.sampleRateInHz,
                                RecorderParameter.channelConfig, RecorderParameter.audioFormat) * 20;
                // 创建AudioRecord对象
                recorder = new AudioRecord(RecorderParameter.audioSource, RecorderParameter.sampleRateInHz,
                                RecorderParameter.channelConfig, RecorderParameter.audioFormat,
                                RecorderParameter.bufferSizeInBytes);
        }
 
        private short[] mixVoice(short[] source, short[] audio, int items) {
                short[] array = new short[items];
                for (int i = 0; i < items; i++) {
                        array<i> = (short) ((source<i> + audio[i / 2]) / 2);
                }
                return array;
        }
 
        /**
         * byte数组转换成short数组
         * 
         * @param data
         * @param items
         * @return
         */
        private short[] byteToShortArray(byte[] data, int items) {
                short[] retVal = new short[items];
                for (int i = 0; i < retVal.length; i++)
                        retVal<i> = (short) ((data[i * 2] & 0xff) | (data[i * 2 + 1] & 0xff) << 8);
                return retVal;
        }
 
        /**
         * short转byte数组
         * 
         * @param s
         * @return
         */
        private byte[] shortToByteArray(short s) {
                byte[] shortBuf = new byte[2];
                for (int i = 0; i < 2; i++) {
                        int offset = (shortBuf.length - 2 + i) * 8;
                        shortBuf<i> = (byte) ((s >>> offset) & 0xff);
                }
                return shortBuf;
        }
 
        /**
         * <a href="/index.html"http://www.eoeandroid.com/home.php?mod=space&uid=7300\"" target="\"_blank\"">@return</a> the recorder
         */
        public static AudioRecord getRecorder() {
                return recorder;
        }
 
        public static MediaPlayer getMediaPlayer() {
                return mediaPlayer;
        }
 
        /**
         * 设置线程运行状态
         * 
         * @param isRunning
         */
        public void setIsRunning(boolean isRunning) {
                this.isRunning = isRunning;
        }
 
        /**
         * 获取线程运行状态
         * 
         * @return
         */
        public boolean IsRunning() {
                return isRunning;
        }
 
        public int getScore() {
                return score;
        }
 
        private void copyWaveFile(String inFilename, String outFilename) {
                FileInputStream in = null;
                FileOutputStream out = null;
                long totalAudioLen = 0;
                long totalDataLen = totalAudioLen + 36;
                long longSampleRate = RecorderParameter.sampleRateInHz;
                int channels = 2;
                long byteRate = 16 * RecorderParameter.sampleRateInHz * channels / 8;
                byte[] data = new byte[RecorderParameter.bufferSizeInBytes];
                try {
                        in = new FileInputStream(inFilename);
                        out = new FileOutputStream(outFilename);
                        totalAudioLen = in.getChannel().size();
                        totalDataLen = totalAudioLen + 36;
                        WriteWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate);
                        while (in.read(data) != -1) {
                                out.write(data);
                        }
                        in.close();
                        out.close();
                } catch (FileNotFoundException e) {
                        e.printStackTrace();
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }
 
        /**
         * 这里提供一个头信息。插入这些信息就可以得到可以播放的文件。 为我为啥插入这44个字节,这个还真没深入研究,不过你随便打开一个wav
         * 音频的文件,可以发现前面的头文件可以说基本一样哦。每种格式的文件都有 自己特有的头文件。
         */
        private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen,
                        long longSampleRate, int channels, long byteRate) throws IOException {
                byte[] header = new byte[44];
                header[0] = 'R'; // RIFF/WAVE header
                header[1] = 'I';
                header[2] = 'F';
                header[3] = 'F';
                header[4] = (byte) (totalDataLen & 0xff);
                header[5] = (byte) ((totalDataLen >> 8) & 0xff);
                header[6] = (byte) ((totalDataLen >> 16) & 0xff);
                header[7] = (byte) ((totalDataLen >> 24) & 0xff);
                header[8] = 'W';
                header[9] = 'A';
                header[10] = 'V';
                header[11] = 'E';
                header[12] = 'f'; // 'fmt ' chunk
                header[13] = 'm';
                header[14] = 't';
                header[15] = ' ';
                header[16] = 16; // 4 bytes: size of 'fmt ' chunk
                header[17] = 0;
                header[18] = 0;
                header[19] = 0;
                header[20] = 1; // format = 1
                header[21] = 0;
                header[22] = (byte) channels;
                header[23] = 0;
                header[24] = (byte) (longSampleRate & 0xff);
                header[25] = (byte) ((longSampleRate >> 8) & 0xff);
                header[26] = (byte) ((longSampleRate >> 16) & 0xff);
                header[27] = (byte) ((longSampleRate >> 24) & 0xff);
                header[28] = (byte) (byteRate & 0xff);
                header[29] = (byte) ((byteRate >> 8) & 0xff);
                header[30] = (byte) ((byteRate >> 16) & 0xff);
                header[31] = (byte) ((byteRate >> 24) & 0xff);
                header[32] = (byte) (2 * 16 / 8); // block align
                header[33] = 0;
                header[34] = 16; // bits per sample
                header[35] = 0;
                header[36] = 'd';
                header[37] = 'a';
                header[38] = 't';
                header[39] = 'a';
                header[40] = (byte) (totalAudioLen & 0xff);
                header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
                header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
                header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
                out.write(header, 0, 44);
        }
 
        private int score(short[] src, short[] user) {
                int srcZ = 0, userZ = 0;
                boolean isAsc = false;
                boolean uisAsc = false;
                for (int i = 1; i < src.length; i++) {
                        if (isAsc) {
                                if (src[i - 1] > src<i>) {
                                        isAsc = false;
                                }
                        } else {
                                if (src[i - 1] < src<i>) {
                                        isAsc = true;
                                        srcZ += 1;
                                }
                        }
                        if (uisAsc) {
                                if (user[i - 1] > user<i>) {
                                        uisAsc = false;
                                }
                        } else {
                                if (user[i - 1] < user<i>) {
                                        uisAsc = true;
                                        userZ += 1;
                                }
                        }
                }
                return Math.abs(srcZ - userZ);
        }
 
}




    
[3] Activity加载形式和Task的关系
    来源: 互联网  发布时间: 2014-02-18
Activity加载模式和Task的关系

Activity的lanuchMode有四种standard(默认),singleTop,singleTask,singleInstance.

 

standard:每次都创建一个实例,默认将Activity加入到当前Task。

 

singleTop:启动的不是当前的Activity的话,则创建一个实例,并加入当前Task,否则抛弃

 

              Intent不做任何反应

 

singleTask:只有一个Task,不会重新创建已存在的Activity。

 

singleInstance:一个Task里只有一个Activity。启动Acivity时,会重新创建一个Task,并

 

              把Activity加入新建的Task。

 

注意:当一个Activity的新实例被创建去处理新Intent时,用户总是可以按返回键返回到之前

 

的状态(之前的Activity)。但是当一个已存在的Activity实例去处理新的Intent时,用

 

户不可以返回键返回到Intent到达之前的状态。

 

清处任务栈:

alwaysRetainTaskState属性: 如果根活动此属性设为true,任务将保留在Task

 

                                                 中。即使离开很长一段时间,也不会被系统清除。

 

                 clearTaskOnLaunch属性:如果根活动此属性设为true,只要用户离开就清除根活

 

                                             动之外的活动。

 

                 finishOnTaskLaunch属性: 作用于单个活动。而且它能移除任何活动,包括根活

 

                                              动。当它被设置为true时,任务本次会话的活动的部

 

                                                             分还存在,如果用户离开并返回到任务,它将不再存在。

 

 

 

用户按下Home键后,再打开一个新的活动。默认重新启动一个Task,若打开一个已开启过

 

的活动,将跳到对应的Task中的对应栈顶。


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3