前提摘要:

 可以给电影加字幕,目前支持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端助力 外挂字幕(设置颜色,大小,位置,微调字幕)的更多相关文章

  1. Android为TV端助力转载:码农小阿飞(SpannableString)

    用SpannableString打造绚丽多彩的文本显示效果 引语 TeXtView大家应该都不陌生,文本展示控件嘛! 就用TextView显示普普通通的文本,OK,很简单,Android入门的都会,没 ...

  2. Android为TV端助力 Canvas 和 Paint用法

    自定义view里面的onDraw方法,在这里我们可以绘制各种图形,onDraw里面有两个API我们需要了解清楚他们的用法:Canvas 和 Paint. Canvas翻译成中文就是画布的意思,Canv ...

  3. Android为TV端助力之:maxWidth设置无效

    android:maxWidth用过几次,之前有效,今天再用就无效了.其实是有两个注意点的,记录下: 1. android:adjustViewBounds="true" 2.an ...

  4. Android为TV端助力(转载)

    作者地址http://www.jianshu.com/u/63915ef020e2 针对Android Tv的自定义RecyclerView 作者 wenju_song 关注 2016.12.09 1 ...

  5. Android为TV端助力 不需要Socket的跨进程推送消息AIDL!

    上篇介绍了跨进程实时通讯http://www.cnblogs.com/xiaoxiaing/p/5818161.html 但是他有个缺点就是服务端无法推送消息给客户端,今天这篇文章主要说的就是服务器推 ...

  6. Android为TV端助力:(转载)修改TextView字体样式

    一.开篇 因为 Android 字体相关的内容还比较多的.有时候其实我们只需要调整一下属性就可以满足设计师的需求,或者是一个退后的方案(毕竟有发版的时间卡住了),有一些效果可以大概满足需求. 那么本文 ...

  7. Android为TV端助力:自定义view之太阳

    先看效果图 package com.hhzt.iptv.lvb_w8.view; import android.content.Context;import android.graphics.Canv ...

  8. Android为TV端助力 listview与recyclerview上下联动

    首先是主布局fragment里面的xml文件 <?xml version="1.0" encoding="utf-8"?><RelativeL ...

  9. Android为TV端助力 转载:RecyclerView分页加载

    package com.android.ryane.pulltoloaddata_recyclerview; import android.os.Handler;import android.os.L ...

随机推荐

  1. Android项目中独立Git项目分库后的编译调试时Gradle的配置

    基于AS开发项目,对于特定的功能模块,往往抽取成独立的库进行管理,然后上传到Marven库中,通过Gradle依赖的方式进行引用. 其优势体现在: 1,独立的Git项目库,模块功能,及职责界定清晰: ...

  2. spring boot整合spring5-webflux从0开始的实战及源码解析

    上篇文章<你的响应阻塞了没有?--Spring-WebFlux源码分析>介绍了spring5.0 新出来的异步非阻塞服务,很多读者说太理论了,太单调了,这次我们就通过一个从0开始的实例实战 ...

  3. Unity制作即时战略游戏毕设

    创建项目 双击Unity,选择New Project:我们将它命名为rts,悬着其他本地磁盘例如C:,选择3D然后点击Create Project: 然后我们通过File->Save Scene ...

  4. 我学Java我傲娇

    今天,终于把学习了一年多的<Java核心技术36讲>第一遍完结了,历时一年多,花出去的钱终于感觉有了第一笔回报. 这是我在极客时间的第一门付费课程,刚出来的时候,正巧自己转到全职Java开 ...

  5. 结合JDK源码看设计模式——装饰者模式

    定义 在不改变原有对象的基础之上,将功能附加到对象上 适用场景 扩展一个类的功能 动态的给对象增加功能,当功能不需要的时候能够动态删除 详解 在看到定义的时候,可能很多人会想,这不就是继承吗?的确很像 ...

  6. SAP HUM 锁住一个HU?

    SAP HUM 锁住一个HU? 1)SAP HUM 不能锁一个已发货的HU! 如下的HU 180141205000已经发货过账, HUMO, 执行, 2)一个WHSE状态的HU就可以被锁定.比如HU ...

  7. arcgis画矢量图

    总图 首先建立目标文件夹和目标文件(shp文件) 现在H:\ex_gis\下新建test文件夹,起名为test,再此目录下建立一个线要素文件. 在这里选择要素类型.这里以线为例,点面类推即可. 设置坐 ...

  8. Oracle AWR报告详细分析--比较详细

    https://blog.csdn.net/demonson/article/details/79474133

  9. SQL server 表信息查询

    一.查看所有表的行数select a.name as '表名',b.rows as '表数据行数'from sysobjects a inner join sysindexes bon a.id = ...

  10. pyspider 文档介绍

    一 代码区结构 def on_start(self)是脚本的入口点.单击run仪表板上的按钮时将调用它. self.crawl(url, callback=self.index_page)*是这里最重 ...