Android为TV端助力 外挂字幕(设置颜色,大小,位置,微调字幕)
前提摘要:
可以给电影加字幕,目前支持srt和ass格式,
功能摘要:
支持微调字幕,设置大小,颜色,位置
1 .字幕解析类
package com.hhzt.iptv.lvb_x.utils; import android.os.Handler;
import android.util.Log; import com.hhzt.iptv.lvb_x.Constant;
import com.hhzt.iptv.lvb_x.log.LogUtil;
import com.hhzt.iptv.lvb_x.model.Srt; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern; public class SrtUtils {
/**上一次 字幕节点*/
private static int node = 0;
/**存放字幕*/
private static List<Srt> srtlist = new ArrayList<Srt>();
/**
* 正则表达式,判断是否是时间的格式
*/
private final static String equalStringExpress = "\\d\\d:\\d\\d:\\d\\d,\\d\\d\\d --> \\d\\d:\\d\\d:\\d\\d,\\d\\d\\d";
/**
* 正则表达式,判断是否是时间的格式
*/
private final static String equalExpressAss = "\\d:\\d\\d:\\d\\d.\\d\\d"; /**
* 单位转换
* 1秒=1000毫秒
*/
private final static int oneSecond = 1000; private final static int oneMinute = 60 * oneSecond; private final static int oneHour = 60 * oneMinute; public static String getFileEncode(InputStream in) {
String encode;
byte[] b = new byte[3];
try {
in.read(b);
} catch (IOException e) {
e.printStackTrace();
}
if (b[0] == -17 && b[1] == -69 && b[2] == -65){
encode="UTF-8";
} else {
encode="GBK";
}
return encode;
}
/**
*
* @param time 毫秒
* @return Srt
*/
public static Srt getSrt(double time) {
// System.out.println("上次节点"+node);
Log.i("TAG","getSrtgetSrt:;"+time);
int n=0;
//根据上一次节点 开始查找
for (int i = node; i < srtlist.size(); i++) {
n++;
Srt str=srtlist.get(i);
//当时间小于 当前字幕段 开始时间时往回倒序查找
if(time<str.getStar()){//小于开始时间
for (int f = node -1 ; f >= 0; f--) { // 倒序查找
n++;
Srt stre=srtlist.get(f);
if(stre.getStar()<=time && time<=stre.getEnd()){
node=f;//设置节点
//符合时间段返回
// System.out.println("总查询次数 : "+n);
return stre;
}
}
}else{
//当时间大于或等于 当前字幕段 开始时间时 顺序往下查找
if(str.getStar()<=time && time<=str.getEnd()){
node=i;//设置节点
//符合时间段返回
// System.out.println("总循环次数 : "+n);
return str;
}
}
}
return null;
}
/***
* 初始化字幕库
*
* @param path 本地文件路径
* @return boolean
*/
public static boolean srtInit(String path) {
boolean b=false;
File file = new File(path);
InputStream inputStream=null;
try {
inputStream = new FileInputStream(file);
String prefix=path.substring(path.lastIndexOf(".")+1);
List<Srt> list =null;
if("srt".equalsIgnoreCase(prefix)){
list = parseSrt(inputStream);
}else if("ass".equalsIgnoreCase(prefix)){
list = parseAss(inputStream);
}else{
return b;
}
srtlist=list;
node=0;
if(srtlist!=null && srtlist.size()>0){
b=true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
try {
if(inputStream!=null ){
inputStream.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
return b;
}
/***
* 初始化字幕库
* @param srturl 网络文件地址
* @return boolean
*/
public static boolean srtInitHttp(String srturl, Handler handler) {
boolean b=false;
URL url = null;
HttpURLConnection connection = null;
InputStream in = null;
try {
url = new URL(URLEncoder(srturl));
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setReadTimeout(30000);
in = connection.getInputStream();
List<Srt> list =null;
String prefix=srturl.substring(srturl.lastIndexOf(".")+1);
if("srt".equalsIgnoreCase(prefix)){
list = parseSrt(in);
}else if("ass".equalsIgnoreCase(prefix)){
list = parseAss(in);
}else{
return b;
}
srtlist=list;
node=0;
if(srtlist!=null && srtlist.size()>0){
handler.sendEmptyMessage(Constant.IPTV_MSG_ANALYSIS_SUCCESS);
b=true;
}
} catch (Exception e) {
LogUtil.e("TAG","EEEEEEEE:"+e.getMessage());
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return b;
}
/***
* 清除字幕库
* @return
*/
public static boolean srtClear() {
try {
if(srtlist!=null && srtlist.size()>0){
srtlist.clear();
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/***
* 修改字幕 当前加载的
* @param timeError 需要调整的时间秒数,正数为延迟,负数为提早
*/
public static boolean update(double timeError) {
int time=(int)(timeError*1000);
for (Srt srt : srtlist) {
srt.setStar(srt.getStar()+time);
srt.setEnd(srt.getEnd()+time);
}
return false; }
/***
* 修改字幕
* @param file 源字幕文件位置
* @param timeError 需要调整的时间秒数,正数为延迟,负数为提早
* @param file 新的字幕文件保存位置
*/
public static boolean update(File file,double timeError) {
boolean b=false;
long time=(long)(timeError*1000);
String path=file.getPath();
String prefix=path.substring(path.lastIndexOf(".")+1);
if("srt".equalsIgnoreCase(prefix)){
b= updateSrt(file,time);
}else if("ass".equalsIgnoreCase(prefix)){
b=updateAss(file, time);
}
return b;
}
private static boolean updateSrt(File file,long timeError){
boolean b=false;
InputStream inputStream=null;
OutputStream outputStream=null;
BufferedReader in=null;
BufferedWriter outWriter=null; File newfile=new File(file.getParentFile().getAbsolutePath()+"/new_"+file.getName());
String line=null;
StringBuffer newLine=new StringBuffer(); try {
newfile.createNewFile(); //创建新文件
inputStream = new FileInputStream(file);
outputStream=new FileOutputStream(newfile); in = new BufferedReader(new InputStreamReader(inputStream,getFileEncode(inputStream))); //创建文件输入流
outWriter = new BufferedWriter(new OutputStreamWriter(outputStream,getFileEncode(inputStream)));//缓冲 //创建文件输出流 //以下while循环逐行读取字幕源文件
while((line=in.readLine()) != null) {
if (! Pattern.matches(equalStringExpress,line)){ //进行正则式的匹配。
outWriter.write(line+"\r\n");//println(newLine.toString()); //如果读到的不是时间描述字符行,则原样写入新文件
outWriter.flush();
continue; //提早结束本次循环继续读取下一行
}
//以下对时间描述字符行进行格式转换和数学运算
String times=line.substring(0,12);
Date date= stringToDate(times, "HH:mm:ss,SSS");
Date date2= getTimeValueSSS(date,timeError);
times=dateToString(date2, "HH:mm:ss,SSS");
/*
int times; int second=Integer.parseInt(line.substring(6,8));
int minute=Integer.parseInt(line.substring(3,5));
int hour=Integer.parseInt(line.substring(0,2)); times=timeError + second + minute*60 + hour*3600;
String shour= "0" + (times/3600);
String sminute="0" + ((times % 3600)/60);
String ssecond="0" + (times % 60); int second2=Integer.parseInt(line.substring(23,25));
int minute2=Integer.parseInt(line.substring(20,22));
int hour2=Integer.parseInt(line.substring(17,19));
times=timeError + second2 + minute2*60 + hour2*3600; String shour2= "0" + (times/3600);
String sminute2="0" + ((times % 3600)/60);
String ssecond2="0" + (times % 60);
*/
String times2=line.substring(17,29);
date= stringToDate(times2, "HH:mm:ss,SSS");
date2= getTimeValueSSS(date,timeError);
times2=dateToString(date2, "HH:mm:ss,SSS"); newLine.setLength(0);
newLine.append(times + " --> ");
newLine.append(times2);
//最后把得到的时间描述字符行写入新文件
outWriter.write(newLine+"\r\n");//println(newLine.toString());
outWriter.flush();
}
in.close();
outWriter.close();
String filename=file.getName();
deleteFile(file.getPath());
renameFile(newfile.getParentFile().getAbsolutePath(), newfile.getName(),filename);
b=true;
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}catch (IOException ex) {
ex.printStackTrace();
}finally{
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outWriter!=null){
try {
outWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return b;
}
private static boolean updateAss(File file,long timeError){
boolean b=false;
InputStream inputStream=null;
OutputStream outputStream=null;
BufferedReader in=null;
BufferedWriter outWriter=null; File newfile=new File(file.getParentFile().getAbsolutePath()+"/new_"+file.getName());
String line=null;
StringBuffer newLine=new StringBuffer(); try {
newfile.createNewFile(); //创建新文件
inputStream = new FileInputStream(file);
outputStream=new FileOutputStream(newfile); in = new BufferedReader(new InputStreamReader(inputStream,getFileEncode(inputStream))); //创建文件输入流
outWriter = new BufferedWriter(new OutputStreamWriter(outputStream,getFileEncode(inputStream)));//缓冲 //创建文件输出流 int startIndex=-1;//事件开始的时间
int endIndex=-1;// 事件结束的时间
int textIndex=-1;//为对白字幕区域
int marginLIndex=-1;//与左边缘的距离, 为4位数字代表的像素值. 0000代表使用当前Style定义的值
int marginRIndex=-1;//与右边缘的距离, 为4位数字代表的像素值. 0000代表使用当前Style定义的值
int marginVIndex=-1;//垂直距离, 为4位数字代表的像素值. 0000代表使用当前Style定义的值
boolean events=false;
//以下while循环逐行读取字幕源文件
while((line=in.readLine()) != null) {
if ("[Events]".equals(line)){
events=true;
}
if(line!=null && line.length()>0 && line.indexOf(",")>-1){
if(startIndex>-1 && endIndex>-1){
// 填充开始时间数据
String[] contexts= line.split(",", 10);
String startime =contexts[startIndex];
// 填充开始时间数据
if(Pattern.matches("\\d:\\d\\d:\\d\\d.\\d\\d", startime)){
Date date= stringToDate(startime+"0", "H:mm:ss.SSS");
Date date2= getTimeValueSSS(date,timeError);
String strtime=dateToString(date2, "H:mm:ss.SSS");
contexts[startIndex]=strtime.substring(0, strtime.length()-1);
}
// 填充结束时间数据
String endtime =contexts[endIndex];;
if(Pattern.matches("\\d:\\d\\d:\\d\\d.\\d\\d", endtime)){
Date date= stringToDate(endtime+"0", "H:mm:ss.SSS");
Date date2= getTimeValueSSS(date,timeError);
String strtime=dateToString(date2, "H:mm:ss.SSS");
contexts[endIndex]=strtime.substring(0, strtime.length()-1);
}
newLine.setLength(0);
for (int i = 0; i < contexts.length; i++) {
if(i>0){
newLine.append(",");
}
newLine.append(contexts[i]);
}
//最后把得到的时间描述字符行写入新文件
outWriter.write(newLine.toString()+"\r\n");//println(newLine.toString());
outWriter.flush();
continue;
}else{
if(events){
if(line.startsWith("Format")){
String[] formats= line.split(",");
for (int i = 0; i < formats.length; i++) {
if("Start".equals(formats[i].trim())){
startIndex=i;
}else
if("End".equals(formats[i].trim())){
endIndex=i;
}else
if("Text".equals(formats[i].trim())){
textIndex=i;
}else
if("MarginL".equals(formats[i].trim())){
marginLIndex=i;
}else
if("MarginR".equals(formats[i].trim())){
marginRIndex=i;
}else
if("MarginV".equals(formats[i].trim())){
marginVIndex=i;
}
}
}
}
}
}
//不修改直接写入
outWriter.write(line+"\r\n");
outWriter.flush();
}
in.close();
outWriter.close();
String filename=file.getName();
deleteFile(file.getPath());
renameFile(newfile.getParentFile().getAbsolutePath(), newfile.getName(),filename);
b=true;
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}catch (IOException ex) {
ex.printStackTrace();
}catch (Exception ex) {
// System.out.println(newLine);
ex.printStackTrace();
}finally{
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outWriter!=null){
try {
outWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return b;
}
public static boolean renameFile(String path,String oldname,String newname){
File oldfile=new File(path+"/"+oldname);
File newfile=new File(path+"/"+newname);
if(!oldfile.exists()){
return false;//重命名文件不存在
}
if(!oldname.equals(newname)){//新的文件名和以前文件名不同时,才有必要进行重命名
if(newfile.exists())//若在该目录下已经有一个文件和新文件名相同,则不允许重命名
return false ;
else{
oldfile.renameTo(newfile);
return true;
}
}else{
return true;
}
}
public static boolean deleteFile(String fileName) {
File file = new File(fileName);
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) {
if (file.delete()) {
// System.out.println("删除单个文件" + fileName + "成功!");
return true;
} else {
// System.out.println("删除单个文件" + fileName + "失败!");
return false;
}
} else {
// System.out.println("删除单个文件失败:" + fileName + "不存在!");
return false;
}
}
/**
* 解析字幕
*
* @param inputStream
* 字幕路径
*/
private static List<Srt> parseSrt(InputStream inputStream) {
ArrayList<Srt> list = new ArrayList<Srt>();
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,getFileEncode(inputStream)));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
String line = null;
try { while ((line = bufferedReader.readLine()) != null) {
Srt sm = new Srt();
// 匹配正则表达式,不符合提前结束当前行;
if (Pattern.matches(equalStringExpress, line)){
// 填充开始时间数据
sm.star = getTime(line.substring(0, 12));
// 填充结束时间数据
sm.end = getTime(line.substring(17, 29));
// 填充中文数据
sm.contextC = bufferedReader.readLine();
// 填充英文数据
sm.contextE = bufferedReader.readLine();
// 当前字幕的节点位置
sm.node = list.size() + 1;
list.add(sm);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* 解析字幕
*
* @param inputStream
* 字幕路径
*/
private static List<Srt> parseAss(InputStream inputStream) {
ArrayList<Srt> list = new ArrayList<Srt>();
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,getFileEncode(inputStream)));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
String line = null;
try {
int startIndex=-1;//事件开始的时间
int endIndex=-1;// 事件结束的时间
int textIndex=-1;//为对白字幕区域
int marginLIndex=-1;//与左边缘的距离, 为4位数字代表的像素值. 0000代表使用当前Style定义的值
int marginRIndex=-1;//与右边缘的距离, 为4位数字代表的像素值. 0000代表使用当前Style定义的值
int marginVIndex=-1;//垂直距离, 为4位数字代表的像素值. 0000代表使用当前Style定义的值
boolean events=false; while ((line = bufferedReader.readLine()) != null) {
if ("[Events]".equals(line)){
events=true;
}
if(events){
if(line!=null && line.length()>0 && line.indexOf(",")>-1){
if(line.startsWith("Format")){
String[] formats= line.split(",");
for (int i = 0; i < formats.length; i++) {
if("Start".equals(formats[i].trim())){
startIndex=i;
}else
if("End".equals(formats[i].trim())){
endIndex=i;
}else
if("Text".equals(formats[i].trim())){
textIndex=i;
}else
if("MarginL".equals(formats[i].trim())){
marginLIndex=i;
}else
if("MarginR".equals(formats[i].trim())){
marginRIndex=i;
}else
if("MarginV".equals(formats[i].trim())){
marginVIndex=i;
}
}
}else{
Srt sm = new Srt();
String[] contexts= line.split(",", 10);
if(startIndex>-1){
// 填充开始时间数据
String startime =contexts[startIndex].replace(".",",")+"0";
if(Pattern.matches("\\d:\\d\\d:\\d\\d,\\d\\d\\d", startime)){
startime="0"+startime;
}
sm.star = getTime(startime);
}
if(endIndex>-1){
// 填充结束时间数据
String endtime =contexts[endIndex].replace(".",",")+"0";
if(Pattern.matches("\\d:\\d\\d:\\d\\d,\\d\\d\\d", endtime)){
endtime="0"+endtime;
}
sm.end = getTime(endtime);
}
if(textIndex>-1){
String text=contexts[textIndex];
if(text.indexOf("\\n")>-1){ String[] strs=text.replace("\\n", "@_@").split("@_@",2);
sm.contextC =strs[0];
// 填充英文数据
sm.contextE =strs[1];
}else if (text.indexOf("\\N")>-1){ String[] strs=text.replace("\\N", "@_@").split("@_@",2);
sm.contextC =strs[0];
// 填充英文数据
sm.contextE =strs[1];
}else{
// 填充中文数据
sm.contextC =text;
}
}
// 当前字幕的节点位置
sm.node = list.size() + 1;
list.add(sm);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
/**
* @param line
* @return 字幕所在的时间节点
* @descraption 将String类型的时间转换成int的时间类型
*/
private static int getTime(String line){
try
{
// 0:00:05.00+0
// 00:00:21,715
// System.out.println(line);
return Integer.parseInt(line.substring(0, 2)) * oneHour// 时
+ Integer.parseInt(line.substring(3, 5)) * oneMinute// 分
+ Integer.parseInt(line.substring(6, 8)) * oneSecond// 秒
+ Integer.parseInt(line.substring(9, line.length()));// 毫秒
}
catch (NumberFormatException e)
{
e.printStackTrace();
}
return -1;
}
//指定日期毫秒后的日期
private static Date getTimeValueSSS(Date d,long l){
Calendar cal=Calendar.getInstance();
cal.setTime(d);
cal.setTimeInMillis(cal.getTimeInMillis()+l);
return cal.getTime();
}
/**
* 字符串转换日期
* @param str
* @param formatprn 格式
* @return
*/
private static Date stringToDate(String str,String formatprn){
//str = " 2008-07-10 19:20:00 " 格式
SimpleDateFormat format = new SimpleDateFormat(formatprn);
if(!str.equals("")&&str!=null){
try {
return format.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 日期转换成字符串
* @param date
* @param formatprn 格式
* @return
*/
private static String dateToString(Date date,String formatprn){
SimpleDateFormat format = new SimpleDateFormat(formatprn);
return format.format(date);
} // 完整的判断中文汉字和符号
public static String URLEncoder(String urls) {
String[] urls2=urls.split("/");
StringBuffer srt=new StringBuffer();
for (int i = 0; i < urls2.length; i++) {
if(urls2[i]!=null && urls2[i].length()>0){ try {
if(isChinese(urls2[i])){
srt.append(URLEncoder.encode(urls2[i], "utf-8"));
}else{
srt.append(urls2[i]);
}
if("http:".equals(urls2[i])|| "https:".equals(urls2[i])){
srt.append("//");
}else if(i < urls2.length-1){
srt.append("/");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
return srt.toString();
}
// 完整的判断中文汉字和符号
public static boolean isChinese(String strName) {
char[] ch = strName.toCharArray();
for (int i = 0; i < ch.length; i++) {
char c = ch[i];
if (isChinese(c)) {
return true;
}
}
return false;
} // 根据Unicode编码完美的判断中文汉字和符号
private static boolean isChinese(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
return true;
}
return false;
}
}
2.字幕实体类
package com.hhzt.iptv.lvb_x.model;
/**
*
* @author Administrator
* 字幕的实体类
*/
public class Srt {
/**
* 当前节点
*/
public int node; /**
* 开始显示的时间
*/
public int star; /**
* 结束显示的时间
*/
public int end; /**
* 显示的内容《英文》
*/
public String contextE; /**
* 显示的内容《中文》
*/
public String contextC; public int getNode() {
return node;
} public void setNode(int node) {
this.node = node;
} public int getStar() {
return star;
} public void setStar(int star) {
this.star = star;
} public int getEnd() {
return end;
} public void setEnd(int end) {
this.end = end;
}
/**原生英文字幕*/
public String getContextE() {
return contextE;
}
/**英文字幕去除 前缀*/
public String getContextEn() {
if(contextE!=null && contextE.length()>0){
String regex="\\{.+?\\}";
return contextE.replaceAll(regex,"").replace("{\\fs12}", "");
}
return contextE;
}
public void setContextE(String contextE) {
this.contextE = contextE;
}
/**中文文字幕去除 样式格式*/
public String getContextCn() {
if(contextC!=null && contextC.length()>0){
String regex="\\{.+?\\}";
return contextC.replaceAll(regex, "");
}
return contextC;
}
public String getContextC() {
return contextC;
} public void setContextC(String contextC) {
this.contextC = contextC;
} @Override
public String toString() {
return "Srt{" +
"node=" + node +
", star=" + star +
", end=" + end +
", contextE='" + contextE + '\'' +
", contextC='" + contextC + '\'' +
'}';
}
} 3.activity调用
public static class NetUtil2 extends Thread {
private boolean isClose = false;
private boolean isPause = false;
/**
* 暂停线程
*/
public synchronized void onThreadPause() {
isPause = true;
} /**
* 线程等待,不提供给外部调用
*/
private void onThreadWait() {
try {
synchronized (this) {
this.wait();
}
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 线程继续运行
*/
public synchronized void onThreadResume() {
isPause = false;
this.notify();
} /**
* 关闭线程
*/
public synchronized void closeThread() {
try {
notify();
setClose(true);
interrupt();
} catch (Exception e) {
e.printStackTrace();
}
} public boolean isClose() {
return isClose;
} public void setClose(boolean isClose) {
this.isClose = isClose;
} @Override
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
while (!isClose && !isInterrupted()) {
if (!isPause) {
if(!isGetReady && null ==mMediaPlayer){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
} final Srt str = SrtUtils.getSrt(mMediaPlayer.getCurrentPosition()+value);
LogUtil.i("TAG","SrtSrt::"+mMediaPlayer.getCurrentPosition());
if(null == str){
try {
Thread.sleep(10);
continue;
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
LogUtil.i("TAG","getContextC11::"+str.getContextC());
LogUtil.i("TAG","tinme::"+str.getStar());
LogUtil.i("TAG","tinmeend::"+str.getEnd()); if(!str.getContextC().equalsIgnoreCase(text)){
LogUtil.i("TAG","getContextC11::"+str.getContextC());
LogUtil.i("TAG","getContextC22::"+str.getStar());
text = str.getContextCn();
text_en = str.getContextEn();
isTime = str.getEnd()-(int)value;
mMediaPlayerHandler.removeMessages(Constant.IPTV_MSG_SHOW_ANALYSIS);
mMediaPlayerHandler.sendEmptyMessage(Constant.IPTV_MSG_SHOW_ANALYSIS);
}}
} else {
onThreadWait();
}
}
}
}
Android为TV端助力 外挂字幕(设置颜色,大小,位置,微调字幕)的更多相关文章
- Android为TV端助力转载:码农小阿飞(SpannableString)
用SpannableString打造绚丽多彩的文本显示效果 引语 TeXtView大家应该都不陌生,文本展示控件嘛! 就用TextView显示普普通通的文本,OK,很简单,Android入门的都会,没 ...
- Android为TV端助力 Canvas 和 Paint用法
自定义view里面的onDraw方法,在这里我们可以绘制各种图形,onDraw里面有两个API我们需要了解清楚他们的用法:Canvas 和 Paint. Canvas翻译成中文就是画布的意思,Canv ...
- Android为TV端助力之:maxWidth设置无效
android:maxWidth用过几次,之前有效,今天再用就无效了.其实是有两个注意点的,记录下: 1. android:adjustViewBounds="true" 2.an ...
- Android为TV端助力(转载)
作者地址http://www.jianshu.com/u/63915ef020e2 针对Android Tv的自定义RecyclerView 作者 wenju_song 关注 2016.12.09 1 ...
- Android为TV端助力 不需要Socket的跨进程推送消息AIDL!
上篇介绍了跨进程实时通讯http://www.cnblogs.com/xiaoxiaing/p/5818161.html 但是他有个缺点就是服务端无法推送消息给客户端,今天这篇文章主要说的就是服务器推 ...
- Android为TV端助力:(转载)修改TextView字体样式
一.开篇 因为 Android 字体相关的内容还比较多的.有时候其实我们只需要调整一下属性就可以满足设计师的需求,或者是一个退后的方案(毕竟有发版的时间卡住了),有一些效果可以大概满足需求. 那么本文 ...
- Android为TV端助力:自定义view之太阳
先看效果图 package com.hhzt.iptv.lvb_w8.view; import android.content.Context;import android.graphics.Canv ...
- Android为TV端助力 listview与recyclerview上下联动
首先是主布局fragment里面的xml文件 <?xml version="1.0" encoding="utf-8"?><RelativeL ...
- Android为TV端助力 转载:RecyclerView分页加载
package com.android.ryane.pulltoloaddata_recyclerview; import android.os.Handler;import android.os.L ...
随机推荐
- C#动态调用泛型类、泛型方法
在制作一个批量序列化工具时遇到了如下问题,在此记录一下,仅供参考. 主程序加载另一个程序集,将其中的所有类取出,然后对这些类分别调用泛型类或泛型方法.控制台程序解决方案如下: Main工程:提供Wor ...
- Java 在PPT中绘制图形
Microsoft PowerPoint可支持在幻灯片中插入各种类型的图形并且可设置图形填充.线条颜色.图形大小.位置等.下面将通过Java编程来演示在PPT中绘制图形的方法. 工具:Free Spi ...
- PHP 单例模式优点意义及如何实现
一.什么是单例模式? 1.含义 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例.它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用. 2. ...
- 简单地做一下“回到顶部”按钮,用jQuery实现其隐藏和显示
1.首先,我们要准备HTML代码: <div id="return-top"> <a href="#top">返回顶部</a> ...
- Percona XtraBackup 8.0, 安装与测试
Percona XtraBackup 8.0 是Percona XtraBackup新推出了一个针对MySQL8.0的版本,主要是MySQL8.0在Redo 和 数据库字典方面有了新的改进. Xtra ...
- Abnormal build process termination--解决IDEA启动web项目报错
iDEA启动后报Error:Abnormal build process terminatio 报错的原因如下: Error:Abnormal build process termination: & ...
- Kafka 消费者相关配置
消费者相关配置类为 org.apache.kafka.clients.consumer.ConsumerConfig 具有以下配置参数 1. GROUP_ID_CONFIG = "grou ...
- CAS、原子操作类的应用与浅析及Java8对其的优化
前几天刷朋友圈的时候,看到一段话:如果现在我是傻逼,那么我现在不管怎么努力,也还是傻逼,因为我现在的傻逼是由以前决定的,现在努力,是为了让以后的自己不再傻逼.话糙理不糙,如果妄想现在努力一下,马上就不 ...
- pandas的apply操作
pandas的apply操作类似于Scala的udf一样方便,假设存在如下dataframe: id_part pred pred_class v_id 0 d [0.722817, 0.650064 ...
- 详解IPTABLES
详解IPTABLES Iptables 是Linux 内核集成的 IP 信息包过滤系统.如果Linux 系统连接到因特网或 LAN.服务器或连接 LAN 和因特网的代理服务器, 则该系统有利于在 Li ...