lollipop版本分开,有些新特性android5.0和6.0不支持

This commit is contained in:
kunfei committed 2023-03-30 08:40:58 +08:00
1 parent 0959e50f53
commit 3cf3231da5
258 files changed
+12817 -13529

No files matched your search

@@ -0,0 +1,88 @@
package me.ag2s.umdlib.domain;
import java.io.IOException;
import java.io.OutputStream;
import me.ag2s.umdlib.tool.WrapOutputStream;
public class UmdBook {
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
private int num;
/**
* Header Part of UMD book
*/
private UmdHeader header = new UmdHeader();
/**
* Detail chapters Part of UMD book
* (include Titles & Contents of each chapter)
*/
private UmdChapters chapters = new UmdChapters();
/**
* Cover Part of UMD book (for example, and JPEG file)
*/
private UmdCover cover = new UmdCover();
/**
* End Part of UMD book
*/
private UmdEnd end = new UmdEnd();
/**
* Build the UMD file.
*
* @param os OutputStream
* @throws IOException
*/
public void buildUmd(OutputStream os) throws IOException {
WrapOutputStream wos = new WrapOutputStream(os);
header.buildHeader(wos);
chapters.buildChapters(wos);
cover.buildCover(wos);
end.buildEnd(wos);
}
public UmdHeader getHeader() {
return header;
}
public void setHeader(UmdHeader header) {
this.header = header;
}
public UmdChapters getChapters() {
return chapters;
}
public void setChapters(UmdChapters chapters) {
this.chapters = chapters;
}
public UmdCover getCover() {
return cover;
}
public void setCover(UmdCover cover) {
this.cover = cover;
}
public UmdEnd getEnd() {
return end;
}
public void setEnd(UmdEnd end) {
this.end = end;
}
}
@@ -0,0 +1,212 @@
package me.ag2s.umdlib.domain;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.DeflaterOutputStream;
import me.ag2s.umdlib.tool.UmdUtils;
import me.ag2s.umdlib.tool.WrapOutputStream;
/**
* It includes all titles and contents of each chapter in the UMD file.
* And the content has been compressed by zlib.
*
* @author Ray Liang (liangguanhui@qq.com)
* 2009-12-20
*/
public class UmdChapters {
private static final int DEFAULT_CHUNK_INIT_SIZE = 32768;
private int TotalContentLen;
public List<byte[]> getTitles() {
return titles;
}
private final List<byte[]> titles = new ArrayList<>();
public List<Integer> contentLengths = new ArrayList<>();
public ByteArrayOutputStream contents = new ByteArrayOutputStream();
public void addTitle(String s) {
titles.add(UmdUtils.stringToUnicodeBytes(s));
}
public void addTitle(byte[] s) {
titles.add(s);
}
public void addContentLength(Integer integer) {
contentLengths.add(integer);
}
public int getContentLength(int index) {
return contentLengths.get(index);
}
public byte[] getContent(int index) {
int st = contentLengths.get(index);
byte[] b = contents.toByteArray();
int end = index + 1 < contentLengths.size() ? contentLengths.get(index + 1) : getTotalContentLen();
System.out.println("总长度:" + contents.size());
System.out.println("起始值:" + st);
System.out.println("结束值:" + end);
byte[] bAr = new byte[end - st];
System.arraycopy(b, st, bAr, 0, bAr.length);
return bAr;
}
public String getContentString(int index) {
return UmdUtils.unicodeBytesToString(getContent(index)).replace((char) 0x2029, '\n');
}
public String getTitle(int index) {
return UmdUtils.unicodeBytesToString(titles.get(index));
}
public void buildChapters(WrapOutputStream wos) throws IOException {
writeChaptersHead(wos);
writeChaptersContentOffset(wos);
writeChaptersTitles(wos);
writeChaptersChunks(wos);
}
private void writeChaptersHead(WrapOutputStream wos) throws IOException {
wos.writeBytes('#', 0x0b, 0, 0, 0x09);
wos.writeInt(contents.size());
}
private void writeChaptersContentOffset(WrapOutputStream wos) throws IOException {
wos.writeBytes('#', 0x83, 0, 0, 0x09);
byte[] rb = UmdUtils.genRandomBytes(4);
wos.writeBytes(rb); //random numbers
wos.write('$');
wos.writeBytes(rb); //random numbers
wos.writeInt(contentLengths.size() * 4 + 9); // about the count of chapters
int offset = 0;
for (Integer n : contentLengths) {
wos.writeInt(offset);
offset += n;
}
}
private void writeChaptersTitles(WrapOutputStream wos) throws IOException {
wos.writeBytes('#', 0x84, 0, 0x01, 0x09);
byte[] rb = UmdUtils.genRandomBytes(4);
wos.writeBytes(rb); //random numbers
wos.write('$');
wos.writeBytes(rb); //random numbers
int totalTitlesLen = 0;
for (byte[] t : titles) {
totalTitlesLen += t.length;
}
// about the length of the titles
wos.writeInt(totalTitlesLen + titles.size() + 9);
for (byte[] t : titles) {
wos.writeByte(t.length);
wos.write(t);
}
}
private void writeChaptersChunks(WrapOutputStream wos) throws IOException {
byte[] allContents = contents.toByteArray();
byte[] zero16 = new byte[16];
Arrays.fill(zero16, 0, zero16.length, (byte) 0);
// write each package of content
int startPos = 0;
int len = 0;
int left = 0;
int chunkCnt = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream(DEFAULT_CHUNK_INIT_SIZE + 256);
List<byte[]> chunkRbList = new ArrayList<>();
while (startPos < allContents.length) {
left = allContents.length - startPos;
len = Math.min(DEFAULT_CHUNK_INIT_SIZE, left);
bos.reset();
DeflaterOutputStream zos = new DeflaterOutputStream(bos);
zos.write(allContents, startPos, len);
zos.close();
byte[] chunk = bos.toByteArray();
byte[] rb = UmdUtils.genRandomBytes(4);
wos.writeByte('$');
wos.writeBytes(rb); // 4 random
chunkRbList.add(rb);
wos.writeInt(chunk.length + 9);
wos.write(chunk);
// end of each chunk
wos.writeBytes('#', 0xF1, 0, 0, 0x15);
wos.write(zero16);
startPos += len;
chunkCnt++;
}
// end of all chunks
wos.writeBytes('#', 0x81, 0, 0x01, 0x09);
wos.writeBytes(0, 0, 0, 0); //random numbers
wos.write('$');
wos.writeBytes(0, 0, 0, 0); //random numbers
wos.writeInt(chunkCnt * 4 + 9);
for (int i = chunkCnt - 1; i >= 0; i--) {
// random. They are as the same as random numbers in the begin of each chunk
// use desc order to output these random
wos.writeBytes(chunkRbList.get(i));
}
}
public void addChapter(String title, String content) {
titles.add(UmdUtils.stringToUnicodeBytes(title));
byte[] b = UmdUtils.stringToUnicodeBytes(content);
contentLengths.add(b.length);
try {
contents.write(b);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void addFile(File f, String title) throws IOException {
byte[] temp = UmdUtils.readFile(f);
String s = new String(temp);
addChapter(title, s);
}
public void addFile(File f) throws IOException {
String s = f.getName();
int idx = s.lastIndexOf('.');
if (idx >= 0) {
s = s.substring(0, idx);
}
addFile(f, s);
}
public void clearChapters() {
titles.clear();
contentLengths.clear();
contents.reset();
}
public int getTotalContentLen() {
return TotalContentLen;
}
public void setTotalContentLen(int totalContentLen) {
TotalContentLen = totalContentLen;
}
}
@@ -0,0 +1,97 @@
package me.ag2s.umdlib.domain;
import java.io.File;
import java.io.IOException;
import me.ag2s.umdlib.tool.UmdUtils;
import me.ag2s.umdlib.tool.WrapOutputStream;
/**
* This is the cover part of the UMD file.
* <p>
* NOTICE: if the "coverData" is empty, it will be skipped when building UMD file.
* </P>
* There are 3 ways to load the image data:
* <ol>
* <li>new constructor function of UmdCover.</li>
* <li>use UmdCover.load function.</li>
* <li>use UmdCover.initDefaultCover, it will generate a simple image with text.</li>
* </ol>
*
* @author Ray Liang (liangguanhui@qq.com)
* 2009-12-20
*/
public class UmdCover {
private static final int DEFAULT_COVER_WIDTH = 120;
private static final int DEFAULT_COVER_HEIGHT = 160;
private byte[] coverData;
public UmdCover() {
}
public UmdCover(byte[] coverData) {
this.coverData = coverData;
}
public void load(File f) throws IOException {
this.coverData = UmdUtils.readFile(f);
}
public void load(String fileName) throws IOException {
load(new File(fileName));
}
public void initDefaultCover(String title) throws IOException {
// BufferedImage img = new BufferedImage(DEFAULT_COVER_WIDTH, DEFAULT_COVER_HEIGHT, BufferedImage.TYPE_INT_RGB);
// Graphics g = img.getGraphics();
// g.setColor(Color.BLACK);
// g.fillRect(0, 0, img.getWidth(), img.getHeight());
// g.setColor(Color.WHITE);
// g.setFont(new Font("����", Font.PLAIN, 12));
//
// FontMetrics fm = g.getFontMetrics();
// int ascent = fm.getAscent();
// int descent = fm.getDescent();
// int strWidth = fm.stringWidth(title);
// int x = (img.getWidth() - strWidth) / 2;
// int y = (img.getHeight() - ascent - descent) / 2;
// g.drawString(title, x, y);
// g.dispose();
//
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
//
// JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baos);
// JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(img);
// param.setQuality(0.5f, false);
// encoder.setJPEGEncodeParam(param);
// encoder.encode(img);
//
// coverData = baos.toByteArray();
}
public void buildCover(WrapOutputStream wos) throws IOException {
if (coverData == null || coverData.length == 0) {
return;
}
wos.writeBytes('#', 0x82, 0, 0x01, 0x0A, 0x01);
byte[] rb = UmdUtils.genRandomBytes(4);
wos.writeBytes(rb); //random numbers
wos.write('$');
wos.writeBytes(rb); //random numbers
wos.writeInt(coverData.length + 9);
wos.write(coverData);
}
public byte[] getCoverData() {
return coverData;
}
public void setCoverData(byte[] coverData) {
this.coverData = coverData;
}
}
@@ -0,0 +1,20 @@
package me.ag2s.umdlib.domain;
import java.io.IOException;
import me.ag2s.umdlib.tool.WrapOutputStream;
/**
* End part of UMD book, nothing to be special
*
* @author Ray Liang (liangguanhui@qq.com)
* 2009-12-20
*/
public class UmdEnd {
public void buildEnd(WrapOutputStream wos) throws IOException {
wos.writeBytes('#', 0x0C, 0, 0x01, 0x09);
wos.writeInt(wos.getWritten() + 4);
}
}
@@ -0,0 +1,164 @@
package me.ag2s.umdlib.domain;
import androidx.annotation.NonNull;
import java.io.IOException;
import me.ag2s.umdlib.tool.UmdUtils;
import me.ag2s.umdlib.tool.WrapOutputStream;
/**
* Header of UMD file.
* It includes a lot of properties of header.
* All the properties are String type.
*
* @author Ray Liang (liangguanhui@qq.com)
* 2009-12-20
*/
public class UmdHeader {
public byte getUmdType() {
return umdType;
}
public void setUmdType(byte umdType) {
this.umdType = umdType;
}
private byte umdType;
private String title;
private String author;
private String year;
private String month;
private String day;
private String bookType;
private String bookMan;
private String shopKeeper;
private final static byte B_type_umd = (byte) 0x01;
private final static byte B_type_title = (byte) 0x02;
private final static byte B_type_author = (byte) 0x03;
private final static byte B_type_year = (byte) 0x04;
private final static byte B_type_month = (byte) 0x05;
private final static byte B_type_day = (byte) 0x06;
private final static byte B_type_bookType = (byte) 0x07;
private final static byte B_type_bookMan = (byte) 0x08;
private final static byte B_type_shopKeeper = (byte) 0x09;
public void buildHeader(WrapOutputStream wos) throws IOException {
wos.writeBytes(0x89, 0x9b, 0x9a, 0xde); // UMD file type flags
wos.writeByte('#');
wos.writeBytes(0x01, 0x00, 0x00, 0x08); // Unknown
wos.writeByte(0x01); //0x01 is text type; while 0x02 is Image type.
wos.writeBytes(UmdUtils.genRandomBytes(2)); //random number
// start properties output
buildType(wos, B_type_title, getTitle());
buildType(wos, B_type_author, getAuthor());
buildType(wos, B_type_year, getYear());
buildType(wos, B_type_month, getMonth());
buildType(wos, B_type_day, getDay());
buildType(wos, B_type_bookType, getBookType());
buildType(wos, B_type_bookMan, getBookMan());
buildType(wos, B_type_shopKeeper, getShopKeeper());
}
public void buildType(WrapOutputStream wos, byte type, String content) throws IOException {
if (content == null || content.length() == 0) {
return;
}
wos.writeBytes('#', type, 0, 0);
byte[] temp = UmdUtils.stringToUnicodeBytes(content);
wos.writeByte(temp.length + 5);
wos.write(temp);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getBookMan() {
return bookMan;
}
public void setBookMan(String bookMan) {
this.bookMan = bookMan;
}
public String getShopKeeper() {
return shopKeeper;
}
public void setShopKeeper(String shopKeeper) {
this.shopKeeper = shopKeeper;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
public String getBookType() {
return bookType;
}
public void setBookType(String bookType) {
this.bookType = bookType;
}
@Override
@NonNull
public String toString() {
return "UmdHeader{" +
"umdType=" + umdType +
", title='" + title + '\'' +
", author='" + author + '\'' +
", year='" + year + '\'' +
", month='" + month + '\'' +
", day='" + day + '\'' +
", bookType='" + bookType + '\'' +
", bookMan='" + bookMan + '\'' +
", shopKeeper='" + shopKeeper + '\'' +
'}';
}
}