解决方案 »
- Android 删除文件
- 学习android时常需要翻阅手册,你们看得英文吗???
- 内存中的jpeg数据传输到jni中解码然后得到bitmap!!
- nbandroid插件和android sdk以后添加平台的时候不会看到Google Android Open Handled
- android xml 解析
- Eclipse下 Android系统如何实现双机的互联
- 用ViewPager 实现左右页,一引用首页上TextView就崩溃了?
- FragmentTabHost类找不到是怎么回事
- android 分享新浪微博4G版 失败 分享其他版本的新浪微博就可以
- 为什么我每次String转int时都有问题,文本框显示不出想要的数值?代码如下:
- ★★JQueryMobile开发移动网页★★
- 怎么让一个Spinner保存上次选择的结果啊?
import java.util.ArrayList;
import java.util.List;import Adapter.MyTextView;
import Util.CT;
import android.widget.TextView;public class TextReader {
/** 文件的显示控件 */
private TextView mTextView; /** 文件名 */
private String mFilePath = null; /** 默认的文件编码形式 */
private String mEncoding = "gb2312"; /** 文件末尾 */
private boolean mEndOfDoc = false; /** 文件开头 */
private boolean mBeforeOfDoc = true; /** 当前显示缓冲的显示行列表 */
private List<TxtLine> mCurrentList = new ArrayList<TxtLine>(); /** 读取文件的输入流工具类 */
private RandomAccessRead mRaf = null; /** 用于保存部分文件的缓冲区大小 */
private int mDataLengthOfOneDoc = 100 * 1024; /** 屏幕宽度和高度 */
private int mViewWidth, mViewHeight; /** 文件大小 */
private long mFileLength; /** 缓冲区中用于显示当前页面的第一行 */
private int mCurrentLine = 0; /** 缓冲区中用于显示当前页面的起始索引 */
private int mCurrentOffset = 0; /** 文件中用于显示当前页面的起始索引 */
private int mStartOffset = 0; /** 用于显示当前页面的数组的起始索引 */
private int mDataStartLocation = 0; /** 用于显示当前页面的数组的结尾索引 */
private int mDataEndLocation = 0; /** 当前显示的文件大小百分比 */
private int mPercent = 0; /** 文件中用于显示当前页面的结尾索引 */
private int mEndOffset = 0; /** 用于显示当前页面的数组 */
private byte[] mScreenData = null; /** 用于显示的缓冲数组 */
private byte[] mDisplayBuffer = null; /**
* 构造函数
*
* @param mTextView
* 显示控件
* @param mScreenWidth
* 屏幕宽度
* @param mScreenHeight
* 屏幕高度
* @param mFilePath
* 文件路径
* @param mEncoding
* 文件编码
*/
public TextReader(MyTextView mTextView, int mScreenWidth, int mScreenHeight,
String mFilePath, String mEncoding) {
this.mTextView = mTextView;
this.mFilePath = mFilePath;
this.mEncoding = mEncoding;
this.mViewWidth = mScreenWidth;
this.mViewHeight = mScreenHeight;
init();
} public void readFile() {
readNextBuffer();
analyzeDisplayBuffer();
displayNextScreen(0);
} /**
* 获取读取文件的输入流以及文件大小
*/
private void init() {
// TODO Auto-generated method stub
this.mRaf = new RandomAccessRead(mFilePath);
this.mFileLength = mRaf.length();
if (this.mFileLength == 0) {
mTextView.setText(Constant.NODATAINFILE);
return;
}
} /**
* 获取下一个缓冲区
*/
private void readNextBuffer() {
mRaf.openNewStream();
mRaf.locate(mStartOffset);
byte[] b = new byte[mDataLengthOfOneDoc];
mCurrentOffset = mStartOffset;
int actualLength = mRaf.readBytes(b);
if (mStartOffset == 0) {
mBeforeOfDoc = true;
} else {
mBeforeOfDoc = false;
}
if (actualLength < mDataLengthOfOneDoc) {
mEndOfDoc = true;
} else {
mEndOfDoc = false;
} if (actualLength == -1 && mScreenData.length == 0) {// 意外到了文件流的末尾或者
mTextView.setText("读取文件失或者文件缓冲区失败");
return;
} if (mEndOfDoc) {
mDisplayBuffer = new byte[actualLength];
System.arraycopy(b, 0, mDisplayBuffer, 0, actualLength);
b = null;
System.gc();
return;
}
/** 最后一个换行符的索引 */
int readDataLength = actualLength;
int nLocation = 0;
while (readDataLength > 0) {
if ((b[readDataLength - 1] & 0xff) == 10) {
nLocation = readDataLength;
break;
}
readDataLength--;
}
if (nLocation == 0) {
System.exit(1);
}
int displayLength = nLocation;
mDisplayBuffer = new byte[displayLength];
System.arraycopy(b, 0, mDisplayBuffer, 0, displayLength);
b = null;
System.gc();
} /**
* 获取上一个缓冲区
*/
private void readPreBuffer() {
int offsetOfLastScreen = mCurrentList.get(mCurrentLine).offset;
if (offsetOfLastScreen <= mDataLengthOfOneDoc) {
mBeforeOfDoc = true;
// if(offsetOfLastScreen>=mFileLength){
// mEndOfDoc=true;
// }
byte[] b = new byte[offsetOfLastScreen];
mRaf.openNewStream();
int actualLength = mRaf.readBytes(b);
if (actualLength < offsetOfLastScreen) {
mEndOfDoc = true;
} else {
mEndOfDoc = false;
}
if (actualLength == -1 && mScreenData.length == 0) {// 意外到了文件流的末尾或者
mTextView.setText("读取文件失或者文件缓冲区失败");
return;
} if (mEndOfDoc) {
mDisplayBuffer = new byte[actualLength];
System.arraycopy(b, 0, mDisplayBuffer, 0, actualLength);
b = null;
System.gc();
mCurrentOffset = 0;
return;
}
/** 最后一个换行符的索引 */
int readDataLength = actualLength;
int nLocation = 0;
while (readDataLength > 0) {
if ((b[readDataLength - 1] & 0xff) == 10) {
nLocation = readDataLength;
break;
}
readDataLength--;
}
if (nLocation == 0) {
System.exit(1);
}
int displayLength = nLocation;
mDisplayBuffer = new byte[displayLength];
System.arraycopy(b, 0, mDisplayBuffer, 0, displayLength);
b = null;
System.gc();
mCurrentOffset = 0;
return;
} int skipLength = offsetOfLastScreen - mDataLengthOfOneDoc;
mRaf.openNewStream();
mRaf.locate(skipLength);
mCurrentOffset = skipLength;
byte[] b = new byte[mDataLengthOfOneDoc];
int readLength = mRaf.readBytes(b);
mBeforeOfDoc = false;
if (readLength < mDataLengthOfOneDoc) {
mEndOfDoc = true;
}
if (readLength == -1 && mScreenData.length == 0) {// 意外到了文件流的末尾或者
mTextView.setText("读取文件失或者文件缓冲区失败");
return;
} int nlocation = 0;
while (nlocation < readLength) {
if ((b[readLength - 1] & 0xff) == 10) {
nlocation = readLength;
break;
}
readLength--;
}
if (nlocation == 0) {
System.exit(1);
} mDisplayBuffer = new byte[readLength];
System.arraycopy(b, 0, mDisplayBuffer, 0, readLength);
b = null;
System.gc();
}
* 对缓冲区进行字符解析
*/
private void analyzeDisplayBuffer() {
if (mDisplayBuffer == null) {
return;
}
mCurrentList.clear();
TxtLine line = new TxtLine(mCurrentOffset, 0, 0);
mCurrentList.add(line);
int length = 0;
int offset = 0;
int width = 0;
int beforeLength = 0;
for (offset = 0; offset < mDisplayBuffer.length;) {
int b = mDisplayBuffer[offset] & 0xff;
if (b == 13) {// '\r'
mDisplayBuffer[offset] = ' ';
} if (b == 10) {// '\n'
length++;
offset++;
beforeLength++;
mCurrentList.add(new TxtLine(mCurrentOffset + offset, length,
beforeLength));
length = 0;
width = 0;
continue;
} if (b > 0x7f) {// chinese
if (width + CT.ChineseFontWidth > mViewWidth) {
mCurrentList.add(new TxtLine(mCurrentOffset + offset,
length, beforeLength));
length = 0;
width = 0;
continue;
} else {
offset += 2;
length += 2;
beforeLength += 2;
width += CT.ChineseFontWidth;
}
} else {// Ascii
int aw = CT.upperAsciiWidth;
if (b >= 65 && b <= 90) {
aw = CT.lowerAsciiWidth;
}
if (width + aw > mViewWidth) {
mCurrentList.add(new TxtLine(mCurrentOffset + offset,
length, beforeLength));
length = 0;
width = 0;
continue;
} else {
offset += 1;
length += 1;
beforeLength += 1;
width += aw;
}
}
}
mCurrentList.add(new TxtLine(mCurrentOffset + offset, length,
beforeLength));
mCurrentLine = 0;
System.gc();
} /**
* 显示下一页
*
* @param n
* 显示的行数
*/
public void displayNextScreen(int n) {
int tempLine = mCurrentLine;
int lastLine = tempLine + n;
int lastIndex = mCurrentList.size() - 1;
if (lastLine + CT.mLinesOfOneScreen > lastIndex) {// 超过缓冲区
if (mEndOfDoc) {// 文件末尾
if (lastIndex <= CT.mLinesOfOneScreen) {// 如果文件大小不足以或者刚好显示整个页面
mStartOffset = mCurrentList.get(0).offset;
mDataStartLocation = mCurrentList.get(0).beforeLineLength;
mEndOffset = mCurrentList.get(lastIndex).offset;
mDataEndLocation = mCurrentList.get(lastIndex).beforeLineLength;
setData(mDataStartLocation, mDataEndLocation);
} else {
mStartOffset = mCurrentList.get(lastLine).offset;
mDataStartLocation = mCurrentList.get(lastLine).beforeLineLength;
mEndOffset = mCurrentList.get(lastIndex).offset;
mDataEndLocation = mCurrentList.get(lastIndex).beforeLineLength;
setData(mDataStartLocation, mDataEndLocation);
}
} else {
readNextBuffer();
analyzeDisplayBuffer();
mCurrentLine = n;//重新定位到末行
lastIndex = mCurrentList.size() - 1;
mStartOffset = mCurrentList.get(mCurrentLine ).offset;
mDataStartLocation = mCurrentList.get(mCurrentLine).beforeLineLength;
// lastLine = mCurrentLine + n;
// lastIndex = mCurrentList.size() - 1;
if (lastIndex <= CT.mLinesOfOneScreen) {
mStartOffset = mCurrentList.get(0).offset;
mDataStartLocation = mCurrentList.get(0).beforeLineLength;
mEndOffset = mCurrentList.get(lastIndex).offset;
mDataEndLocation = mCurrentList.get(lastIndex).beforeLineLength;
setData(mDataStartLocation, mDataEndLocation);
} else {
int i=mCurrentLine+CT.mLinesOfOneScreen;
if(i>=mCurrentList.size()){
i=mCurrentList.size()-1;
}
mEndOffset = mCurrentList.get(i).offset;
mDataEndLocation = mCurrentList.get(i).beforeLineLength;
setData(mDataStartLocation, mDataEndLocation);
}
}
return ;
} else {
mCurrentLine = lastLine;
mStartOffset = mCurrentList.get(mCurrentLine).offset;
mDataStartLocation = mCurrentList.get(mCurrentLine).beforeLineLength;
mEndOffset = mCurrentList.get(mCurrentLine + CT.mLinesOfOneScreen).offset;
mDataEndLocation = mCurrentList.get(mCurrentLine
+ CT.mLinesOfOneScreen).beforeLineLength;
setData(mDataStartLocation, mDataEndLocation);
return;
}
} /**
* 显示上一页
*
* @param n
* 显示的行数
*/
public void displayPreScreen(int n) {
int tempLine = mCurrentLine;
int lastLine = tempLine - n;
if (lastLine <= 0) {
lastLine = 0;
}
if (lastLine == 0 && !mBeforeOfDoc) {
readPreBuffer();
analyzeDisplayBuffer();
int lastIndex = mCurrentList.size() - 1;
if (lastIndex <= CT.mLinesOfOneScreen) {
mStartOffset = mCurrentList.get(0).offset;
mDataStartLocation = mCurrentList.get(0).beforeLineLength;
mEndOffset = mCurrentList.get(lastIndex).offset;
mDataEndLocation = mCurrentList.get(lastIndex).beforeLineLength;
setData(mDataStartLocation, mDataEndLocation);
} else {
mCurrentLine = lastIndex - CT.mLinesOfOneScreen;
if (mCurrentLine < 0) {
mCurrentLine = 0;
}
mStartOffset = mCurrentList.get(mCurrentLine).offset;
mDataStartLocation = mCurrentList.get(mCurrentLine).beforeLineLength;
mEndOffset = mCurrentList.get(lastIndex).offset;
mDataEndLocation = mCurrentList.get(lastIndex).beforeLineLength;
setData(mDataStartLocation, mDataEndLocation);
}
return;
}
if (lastLine == 0 && mBeforeOfDoc) {
mCurrentLine = 0;
mStartOffset = 0;
mDataStartLocation = 0;
int lastIndex = mCurrentList.size() - 1;
if (lastIndex <= CT.mLinesOfOneScreen) {
mEndOffset = mCurrentList.get(lastIndex).offset;
mDataEndLocation = mCurrentList.get(lastIndex).beforeLineLength;
} else {
mEndOffset = mCurrentList.get(CT.mLinesOfOneScreen).offset;
mDataEndLocation = mCurrentList.get(CT.mLinesOfOneScreen).beforeLineLength;
}
setData(mDataStartLocation, mDataEndLocation);
return;
} if (lastLine > 0) {
int futureLine = lastLine + CT.mLinesOfOneScreen;
if (lastLine > mCurrentList.size() - 1) {
lastLine = mCurrentList.size() - 1;
}
mCurrentLine = lastLine;
mStartOffset = mCurrentList.get(mCurrentLine).offset;
mDataStartLocation = mCurrentList.get(mCurrentLine).beforeLineLength;
mEndOffset = mCurrentList.get(futureLine).offset;
mDataEndLocation = mCurrentList.get(futureLine).beforeLineLength;
setData(mDataStartLocation, mDataEndLocation);
return;
}
} public void displayScreenbyLine(int lineNumber) {
if (lineNumber > 0) {
this.displayNextScreen(lineNumber);
} else {
this.displayPreScreen(Math.abs(lineNumber));
} } /**
* 设置数据
*
* @param start
* 起始索引
* @param end
* 终点索引
*/
public void setData(int start, int end) {
mScreenData = new byte[end - start];
mCurrentOffset = mStartOffset;
mPercent = (int) (((double) mCurrentOffset / (double) mFileLength) * 100);
System.arraycopy(mDisplayBuffer, start, mScreenData, 0,
mScreenData.length);
try {
mTextView.setText(new String(mScreenData, mEncoding));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} /**
* 从指定的索引读取缓冲区
*
* @param offset
* 起始索引
*/
public void readBufferByOffset(int offset) {
mStartOffset = offset;
mCurrentList.clear();
mCurrentLine = 0;
readNextBuffer();
analyzeDisplayBuffer();
displayNextScreen(0);
} /**
* 获取文件的当前索引
*
* @return
*/
public int getCurrentLineOffset() {
return mStartOffset;
} /**
* 获取当前行的指定字节组成的字符串
*
* @return
*/
public String getCurrentLineString() {//
int length = mScreenData.length;
String s = Constant.BOOKMARK;
if (length < 10) {
try {
s = new String(mScreenData, this.mEncoding);
} catch (UnsupportedEncodingException e) {
return s;
}
} else {
int lineFlag = 0;
for (int i = 0; i < 10; i++) {
int temp = mScreenData[i] & 0xff;
if (temp == 13 || temp == 10) {
lineFlag = i;
}
}
byte[] b = null;
if (lineFlag != 0) {//如果前10个字节包含换行符,那么从换行符之前取字段
b = new byte[lineFlag];
} else {
int temp = mScreenData[9] & 0xff;
if (temp > 0x7f) {// 如果是中文字节,那么可能是半个中文字,那么这里应该再往后取两个字节
b = new byte[12];
} else {//如果只是英文字母,那么直接在这个地方开始取字段
b = new byte[10];
}
}
System.arraycopy(mScreenData, 0, b, 0, b.length);
try {
s = new String(b, this.mEncoding);
} catch (UnsupportedEncodingException e) {
return s;
}
}
System.gc();
return s;
} public void close() {
mRaf.close();
} /** Percent */
public int getPercent() {
return mPercent;
}
}
下面就是调用类了://跳页,因为有乱码问题,取巧获取最近的一个换行符,避免乱码
private void jumpPage() {
// TODO Auto-generated method stub
mPercent = (int) (((double) current_startIndex / (double) CT.mFileLength) * 100);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.jump_page_title);
View view = LayoutInflater.from(this).inflate(
R.layout.reader_menu_jump_page, null);
final SeekBar bar = (SeekBar) view
.findViewById(R.id.jump_page_seek_bar);
bar.setProgress(mPercent);
final TextView text = (TextView) view
.findViewById(R.id.jump_page_show_percent);
text.setText(mPercent + "%");
bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub } @Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub } @Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
mPercent = progress;
text.setText(progress + "%");
RandomAccessRead ran = new RandomAccessRead(_mFilePath);
current_startIndex = (int) ((progress * 0.01) * CT.mFileLength);
ran.locate(current_startIndex);
int temp;
do {// 获取从current_startIndex开始的第一个换行符,这样就避免读取半个汉字字节
temp = ran.read();
current_startIndex += 1;
if ((temp & 0xff) == 10) {
break;
}
} while (true);
ran.close();
mTextReader.readBufferByOffset(current_startIndex);
}
});
builder.setView(view);
builder.setNegativeButton(R.string.widget_cancel,
new OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.dismiss();
}
});
Dialog dialog = builder.create();
dialog.show();
}/**
* 载入书籍的数据
*/
private void loadData() {
mReaderBytes = new RandomAccessRead(_mFilePath);
CT.mFileLength = mReaderBytes.length();
byte[] encodings = new byte[400];
mReaderBytes.readBytes(encodings);
mReaderBytes.close();
/** 以下是检测文件的编码 */
BytesEncodingDetect be = new BytesEncodingDetect();
this.mEncoding = BytesEncodingDetect.nicename[be
.detectEncoding(encodings)];
/** 检测文件的编码结束 */
/** load the attribute for font */
Paint tp = mTextView.getPaint();
/** Ascii char width */
CT.upperAsciiWidth = (int) tp.measureText(Constant.UPPERASCII);
CT.lowerAsciiWidth = (int) tp.measureText(Constant.LOWERASCII);
/** Chinese char width */
CT.ChineseFontWidth = (int) tp.measureText(
Constant.CHINESE.toCharArray(), 0, 1); mTextReader = new TextReader(mTextView, CT.mScreenWidth,
CT.mScreenHeight, _mFilePath, mEncoding);
if (current_startIndex == 0) {
mTextReader.readFile();
} else {
mTextReader.readBufferByOffset(current_startIndex);
}
showToast();
}
//初始化界面
private void init() {
// TODO Auto-generated method stub
mTextView.setBackgroundResource(BookConfig.backgroundResource);
CT.mScreenHeight = this.getWindowManager().getDefaultDisplay()
.getHeight();
CT.mScreenWidth = this.getWindowManager().getDefaultDisplay()
.getWidth();
mTextView.setTextSize(BookConfig.fontSize);
mTextView.setTextColor(BookConfig.fontColor);
mTextView.setLineSpacing(0, 1.2f);
}
//下一页
private void pageDown() {
// TODO Auto-generated method stub
if (mScroll.getScrollY() != 0) {// 如果滑块不是停在最前面,则自动滚到最前端
mScroll.smoothScrollTo(0, 0);
}
mTextReader.displayScreenbyLine(CT.mLinesOfOneScreen);
}
//上一页
private void pageUp() {
if (mScroll.getScrollY() != 0) {// 如果滑块不是停在最前面,则自动滚到最前端
mScroll.smoothScrollTo(0, 0);
}
mTextReader.displayScreenbyLine(-CT.mLinesOfOneScreen);
}@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE// 手势翻页上一页
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
pageDown();
return true;
} else if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE// 手势翻页下一页
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
pageUp();
return true;
} else {
return false;
}
}
android做了八个月了,mediaplayer的播放框架stagefright有了些了解。
如果想明白系统工作原理,不得不学习Linux了~~ 先看看 Android framework,再看linux kernel
1.曾经在android1.6上实现所有phone相关的功能,用的LC6311模块,包括自己扩展可视通话功能
2.StageFright,几乎全格式支持,利用自家芯片硬解码
3.GPU 2D/3D 加速移植
4.把V8等移植在amrV5 CPU上运行等armV5 兼容性改进
5.其它电源管理,wifi,bt,touch,vold,recovery升级包等乱七八糟的需求及bug修改
移植过android1.6/2.0/2.1/2.3/4.0
自学过surface机制,binder工作原理,之前一直搞wince移植比较多,window开发经验较多,
做android时,才开始学习linux,感觉linux还是很伟大的对android学习的最大感受:设计这款系统的人很牛X,但系统结构太臃肿,比较耗CPU及内存
1.扩展可视通话功能,是如何实现的,你说的LC6311模块又是怎么回事啊,见笑了,我对framework只停留在好奇层次
2.你说你移植过android1.6/2.0/2.1/2.3/4.0,是怎么回事啊 ,有相关的学习资料吗?
先谢过了啊
android1.6不支持可视通话,主要有camera数据压缩发送,vp数据解压显示等操作android1.6/2.0/2.1/2.3/4.0移植,因为我们是做芯片的,每出来一款android版本
我们都要让它先在我们平台上运行,2.0/2.1相差不大,是给别人平台做的,学习资料
现在网上已经很多了,一年前很少,主要学习方法是看代码了
2. 内存需要优化,尤其是图片较多的时候,容易内存溢出
3. 一个应用程序如果太臃肿,感觉需要使用多进程来处理,,把数据处理放到另外一个进程当中去Service。
请求各位android大侠给些建议。
请求各位android大侠给些建议。
System.out.printn("酱油....");
可,还是 停留在应用层 framework想研究 只能看懂 别人 剖析的 很小一部分(binder,
ams)至今还在做 app应用 ,顺便问一下 mediaplayer的 流怎么获取 如何 在缓冲完了后 取出 完整的 流 并
保存成 文件。
悲催
App开发门槛降低,吸引用户的不再是技术,而是服务和特色。