player
This commit is contained in:
parent
6465b57b0a
commit
bd5851a5a3
|
@ -11,8 +11,7 @@ android {
|
||||||
minSdk 21
|
minSdk 21
|
||||||
targetSdk 34
|
targetSdk 34
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "2.0.4"
|
versionName "2.1"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@ dependencies {
|
||||||
implementation files('libs/ijkplayer-java-0.8.8.aar')
|
implementation files('libs/ijkplayer-java-0.8.8.aar')
|
||||||
implementation files('libs/ijkplayer-armv7a-0.8.8.aar')
|
implementation files('libs/ijkplayer-armv7a-0.8.8.aar')
|
||||||
implementation files('libs/ijkplayer-arm64-0.8.8.aar')
|
implementation files('libs/ijkplayer-arm64-0.8.8.aar')
|
||||||
implementation files('libs\\connService2.jar')
|
implementation files('libs/connService2.jar')
|
||||||
}
|
}
|
||||||
|
|
||||||
def getAppName() {
|
def getAppName() {
|
||||||
|
@ -55,8 +54,8 @@ def getAppName() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改 Apk 名
|
// 修改 Apk 名
|
||||||
android.applicationVariants.all { variant ->
|
android.applicationVariants.configureEach { variant ->
|
||||||
variant.outputs.all {
|
variant.outputs.configureEach {
|
||||||
def fileName = "${getAppName()}-${versionName}.apk"
|
def fileName = "${getAppName()}-${versionName}.apk"
|
||||||
outputFileName = fileName
|
outputFileName = fileName
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.XixunPlayer" >
|
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" >
|
||||||
<service
|
<service
|
||||||
android:name=".RestartService"
|
android:name=".RestartService"
|
||||||
android:exported="false" >
|
android:exported="false" >
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package com.xixun.xixunplayer;
|
package com.xixun.xixunplayer;
|
||||||
|
|
||||||
import static android.view.View.VISIBLE;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.ActivityManager;
|
import android.app.Activity;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -11,24 +9,18 @@ import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.StatFs;
|
|
||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.webkit.WebView;
|
|
||||||
|
|
||||||
import androidx.activity.ComponentActivity;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.OptIn;
|
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
|
||||||
|
|
||||||
import com.xixun.joey.aidlset.CardService;
|
import com.xixun.joey.aidlset.CardService;
|
||||||
import com.xixun.xy.conn.aidl.ConnService;
|
import com.xixun.xy.conn.aidl.ConnService;
|
||||||
|
@ -41,31 +33,21 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import gnph.util.Chsets;
|
import gnph.util.Chsets;
|
||||||
import gnph.util.IOs;
|
import gnph.util.IOs;
|
||||||
import gnph.util.JSList;
|
import gnph.util.JSList;
|
||||||
import gnph.util.JSMap;
|
import gnph.util.JSMap;
|
||||||
import gnph.util.NumFmts;
|
|
||||||
import gnph.util.O;
|
|
||||||
|
|
||||||
public class MainActivity extends ComponentActivity implements Choreographer.FrameCallback, Runnable {
|
public class MainActivity extends Activity implements Choreographer.FrameCallback, Runnable {
|
||||||
|
|
||||||
public static MainActivity ins;
|
public static MainActivity ins;
|
||||||
public Intent environIntent = new Intent();
|
public Intent environIntent = new Intent();
|
||||||
HashSet<IntentReceiver> environs = new HashSet<>();
|
HashSet<IntentReceiver> environs = new HashSet<>();
|
||||||
BackView backView;
|
BackView backView;
|
||||||
Prog progView;
|
Prog progView, insView;
|
||||||
long launchMilli = System.currentTimeMillis();
|
long launchMilli = System.currentTimeMillis();
|
||||||
long syncMs;
|
long syncMs;
|
||||||
int state;
|
int state;
|
||||||
|
@ -129,11 +111,10 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
Util.screenWidth = service.getScreenWidth();
|
Util.screenWidth = service.getScreenWidth();
|
||||||
Util.screenHeight = service.getScreenHeight();
|
Util.screenHeight = service.getScreenHeight();
|
||||||
Util.println(" IsScreenOn: "+Util.isScreenOn+" screen: "+Util.screenWidth+" x "+Util.screenHeight);
|
Util.println(" IsScreenOn: "+Util.isScreenOn+" screen: "+Util.screenWidth+" x "+Util.screenHeight);
|
||||||
backView = new BackView(MainActivity.this, Util.screenWidth, Util.screenHeight);
|
setContentView(backView = new BackView(MainActivity.this, Util.screenWidth, Util.screenHeight));
|
||||||
state = 5;
|
state = 5;
|
||||||
if(Util.isScreenOn) initProg();
|
if(Util.isScreenOn) initProg();
|
||||||
else state = 8;
|
else state = 8;
|
||||||
if(progView==null) setContentView(backView);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Util.makeText(MainActivity.this, Util.toStr(e)).show();
|
Util.makeText(MainActivity.this, Util.toStr(e)).show();
|
||||||
Util.printStackTrace(e);
|
Util.printStackTrace(e);
|
||||||
|
@ -179,12 +160,16 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
Util.println(" IsScreenOn: "+Util.isScreenOn);
|
Util.println(" IsScreenOn: "+Util.isScreenOn);
|
||||||
if(! Util.isScreenOn) {
|
if(! Util.isScreenOn) {
|
||||||
state = 8;
|
state = 8;
|
||||||
|
if(insView!=null) {
|
||||||
|
insView.release();
|
||||||
|
insView = null;
|
||||||
|
}
|
||||||
if(progView!=null) {
|
if(progView!=null) {
|
||||||
progView.release();
|
progView.release();
|
||||||
progView = null;
|
progView = null;
|
||||||
setContentView(backView);
|
|
||||||
}
|
}
|
||||||
} else if(progView==null) initProg();
|
setContentView(backView);
|
||||||
|
} else if(progView==null && insView==null) initProg();
|
||||||
}
|
}
|
||||||
}, new IntentFilter("com.xixun.action.PAUSE_PLAYER"));
|
}, new IntentFilter("com.xixun.action.PAUSE_PLAYER"));
|
||||||
|
|
||||||
|
@ -226,8 +211,8 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
try {
|
try {
|
||||||
var code = intent.getIntExtra("code", 0);
|
var code = intent.getIntExtra("code", 0);
|
||||||
Util.println(" remote_control "+code);
|
Util.println(" remote_control "+code);
|
||||||
if(progView == null || code > progView.pages.size()) return;
|
if(progView == null || ! progView.isShown() || code > progView.pages.size()) return;
|
||||||
if(! progView.avas.isEmpty()) page(progView.curAva).hide();
|
if(! progView.avas.isEmpty()) progView.curAva().hide();
|
||||||
var millis = (System.currentTimeMillis()+999)/1000*1000;
|
var millis = (System.currentTimeMillis()+999)/1000*1000;
|
||||||
if(code > 0) {
|
if(code > 0) {
|
||||||
progView.avas.clear();
|
progView.avas.clear();
|
||||||
|
@ -235,7 +220,7 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
progView.curAva = 0;
|
progView.curAva = 0;
|
||||||
progView.curTimes = 1;
|
progView.curTimes = 1;
|
||||||
progView.waitTo = 0; //点播
|
progView.waitTo = 0; //点播
|
||||||
var page = page(0);
|
var page = progView.curAva();
|
||||||
page.setMillis(millis);
|
page.setMillis(millis);
|
||||||
if(state != 6) {
|
if(state != 6) {
|
||||||
setContentView(progView);
|
setContentView(progView);
|
||||||
|
@ -316,9 +301,14 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopProg() {
|
public void stopProg() {
|
||||||
if(progView==null) return;
|
if(insView!=null) {
|
||||||
|
insView.release();
|
||||||
|
insView = null;
|
||||||
|
}
|
||||||
|
if(progView!=null) {
|
||||||
progView.release();
|
progView.release();
|
||||||
progView = null;
|
progView = null;
|
||||||
|
}
|
||||||
setContentView(backView);
|
setContentView(backView);
|
||||||
}
|
}
|
||||||
public boolean delProgFile() {
|
public boolean delProgFile() {
|
||||||
|
@ -338,27 +328,40 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
public void initProg() {
|
public void initProg() {
|
||||||
|
state = 1;
|
||||||
|
try {
|
||||||
|
Util.println("\nParse Insert Prog Json");
|
||||||
|
var root = JSMap.fromClose(new BufferedInputStream(new FileInputStream(Util.programDir + "/insert")));
|
||||||
|
var task = root.jsmap("task");
|
||||||
|
if(task==null && root.containsKey("layers")) task = new JSMap("items", new JSList<>(new JSMap("_program", root)));
|
||||||
|
if(task!=null) {
|
||||||
|
var view = new Prog(task, this);
|
||||||
|
if(view.getChildCount()!=0) setContentView(insView = view);
|
||||||
|
}
|
||||||
|
} catch(FileNotFoundException ignored) {
|
||||||
|
} catch(Throwable e) {
|
||||||
|
state = 7;
|
||||||
|
Util.printStackTrace(e);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
Util.println("\nParse Prog Json");
|
Util.println("\nParse Prog Json");
|
||||||
var root = JSMap.fromClose(new BufferedInputStream(new FileInputStream(Util.programDir + "/program")));
|
var root = JSMap.fromClose(new BufferedInputStream(new FileInputStream(Util.programDir + "/program")));
|
||||||
var task = root.jsmap("task");
|
var task = root.jsmap("task");
|
||||||
if(task==null) {
|
if(task==null && root.containsKey("layers")) task = new JSMap("items", new JSList<>(new JSMap("_program", root)));
|
||||||
if(! root.containsKey("layers")) {
|
if(task==null) Util.println(root.isEmpty() ? " Empty program JSON\n" : " Error: task==null\n");
|
||||||
state = 3;
|
else {
|
||||||
Util.println(root.isEmpty() ? " Empty program JSON\n" : " Error: task==null\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
task = new JSMap("items", new JSList<>(new JSMap("repeatTimes", 1, "_program", root)));
|
|
||||||
}
|
|
||||||
var view = new Prog(task, this);
|
var view = new Prog(task, this);
|
||||||
if(view.getChildCount()==0) {
|
if(view.getChildCount()==0) Util.println(" Error: ChildCount==0\n");
|
||||||
state = 3;
|
else setContentView(progView = view);
|
||||||
Util.println(" Error: ChildCount==0\n");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if(progView!=null) progView.release();
|
} catch(FileNotFoundException e) {
|
||||||
progView = view;
|
Util.println(""+e);
|
||||||
setContentView(progView);
|
} catch(Throwable e) {
|
||||||
|
state = 7;
|
||||||
|
Util.makeText(this, Util.toStr(e)).show();
|
||||||
|
Util.printStackTrace(e);
|
||||||
|
}
|
||||||
|
if(insView!=null || progView!=null) {
|
||||||
state = 5;
|
state = 5;
|
||||||
Util.println("Init Sync");
|
Util.println("Init Sync");
|
||||||
syncProg((System.currentTimeMillis()+999)/1000*1000);
|
syncProg((System.currentTimeMillis()+999)/1000*1000);
|
||||||
|
@ -366,14 +369,7 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
choreographer.postFrameCallback(this);
|
choreographer.postFrameCallback(this);
|
||||||
canAdd = false;
|
canAdd = false;
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException e) {
|
} else if(state != 7) state = 3;
|
||||||
state = 3;
|
|
||||||
Util.println(""+e);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
state = 7;
|
|
||||||
Util.makeText(this, Util.toStr(e)).show();
|
|
||||||
Util.printStackTrace(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public void initProg(byte[] json) {
|
public void initProg(byte[] json) {
|
||||||
try {
|
try {
|
||||||
|
@ -387,19 +383,25 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
Util.println(new String(json, Chsets.UTF8));
|
Util.println(new String(json, Chsets.UTF8));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
task = new JSMap("items", new JSList<>(new JSMap("repeatTimes", 1, "_program", root)));
|
task = new JSMap("items", new JSList<>(new JSMap("_program", root)));
|
||||||
}
|
}
|
||||||
var view = new Prog(task, this);
|
var view = new Prog(task, this);
|
||||||
if(view.getChildCount()==0) {
|
if(view.getChildCount()==0) {
|
||||||
state = 7;
|
if(! view.isInsert) state = 7;
|
||||||
Util.println(" Error: ChildCount==0\n");
|
Util.println(" Error: ChildCount==0\n");
|
||||||
Util.println(new String(json, Chsets.UTF8));
|
Util.println(new String(json, Chsets.UTF8));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(view.isInsert) {
|
||||||
|
if(insView!=null) insView.release();
|
||||||
|
insView = view;
|
||||||
|
setContentView(insView);
|
||||||
|
} else {
|
||||||
if(progView!=null) progView.release();
|
if(progView!=null) progView.release();
|
||||||
progView = view;
|
progView = view;
|
||||||
setContentView(progView);
|
setContentView(progView);
|
||||||
var fOut = new FileOutputStream(Util.programDir + "/program");
|
}
|
||||||
|
var fOut = new FileOutputStream(Util.programDir + (view.isInsert?"/insert":"/program"));
|
||||||
fOut.write(json);
|
fOut.write(json);
|
||||||
fOut.flush();
|
fOut.flush();
|
||||||
fOut.getFD().sync();
|
fOut.getFD().sync();
|
||||||
|
@ -424,11 +426,32 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doFrame(long frameTimeNanos) {
|
public void doFrame(long frameTimeNanos) {
|
||||||
if(progView == null) {
|
if(progView == null && insView==null) {
|
||||||
canAdd = true;
|
canAdd = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var milli = System.currentTimeMillis();
|
var milli = System.currentTimeMillis();
|
||||||
|
if(insView!=null && ! insView.avas.isEmpty()) {
|
||||||
|
var lastPage = insView.curAva();
|
||||||
|
if(milli >= lastPage.endMilli) {
|
||||||
|
lastPage.hide();
|
||||||
|
if(--lastPage.repeatTimes<=0 && ++insView.curAva >= insView.avas.size()) {
|
||||||
|
var isDiff = milli-lastPage.endMilli>=1000;
|
||||||
|
Util.println("isDiff: "+isDiff+" endMs: "+lastPage.endMilli+" millis:"+milli);
|
||||||
|
syncProg(isDiff ? milli : lastPage.endMilli);
|
||||||
|
choreographer.postFrameCallback(this);
|
||||||
|
canAdd = false;
|
||||||
|
if(insView!=null) for(var call : insView.calls) call.doFrame(milli);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
insView.curAva().setMillis(lastPage.endMilli);
|
||||||
|
Util.println("curAva: "+insView.curAva+" endMs: "+insView.curAva().endMilli);
|
||||||
|
} else lastPage.showHideSrcs(milli);
|
||||||
|
choreographer.postFrameCallback(this);
|
||||||
|
canAdd = false;
|
||||||
|
for(var call : insView.calls) call.doFrame(milli);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(progView.avas.isEmpty()) {
|
if(progView.avas.isEmpty()) {
|
||||||
if(milli >= progView.waitTo) {
|
if(milli >= progView.waitTo) {
|
||||||
progView.waitTo = Long.MAX_VALUE;
|
progView.waitTo = Long.MAX_VALUE;
|
||||||
|
@ -436,21 +459,20 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
syncProg(milli);
|
syncProg(milli);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var lastPage = page(progView.curAva);
|
var lastPage = progView.curAva();
|
||||||
if(milli >= lastPage.endMilli) {
|
if(milli >= lastPage.endMilli) {
|
||||||
lastPage.hide();
|
lastPage.hide();
|
||||||
if(progView.waitTo > 0) { //waitTo==0 为点播,不换页
|
if(progView.waitTo > 0) { //waitTo==0 为点播,不换页
|
||||||
if(progView.curTimes < lastPage.repeatTimes) progView.curTimes++;
|
if(progView.curTimes < lastPage.repeatTimes) progView.curTimes++;
|
||||||
else {
|
else {
|
||||||
progView.curTimes = 1;
|
progView.curTimes = 1;
|
||||||
progView.curAva++;
|
if(++progView.curAva >= progView.avas.size()) {
|
||||||
if(progView.curAva >= progView.avas.size()) {
|
|
||||||
var isDiff = milli-lastPage.endMilli>=1000;
|
var isDiff = milli-lastPage.endMilli>=1000;
|
||||||
if(Util.buf.length()>1000000) Util.buf.replace(0, 100000, "");
|
if(Util.buf.length()>1000000) Util.buf.replace(0, 100000, "");
|
||||||
Util.println("isDiff: "+isDiff+" endMs: "+lastPage.endMilli+" millis:"+milli);
|
Util.println("isDiff: "+isDiff+" endMs: "+lastPage.endMilli+" millis:"+milli);
|
||||||
syncProg(isDiff ? milli : lastPage.endMilli);
|
syncProg(isDiff ? milli : lastPage.endMilli);
|
||||||
if(progView.avas.isEmpty()) Util.println("after. No Avas");
|
if(! progView.isShown() || progView.avas.isEmpty()) Util.println("after. No Avas");
|
||||||
else Util.println("after. curAva: "+progView.curAva+" endMs: "+page(progView.curAva).endMilli);
|
else Util.println("after. curAva: "+progView.curAva+" endMs: "+progView.curAva().endMilli);
|
||||||
choreographer.postFrameCallback(this);
|
choreographer.postFrameCallback(this);
|
||||||
canAdd = false;
|
canAdd = false;
|
||||||
for(var call : progView.calls) call.doFrame(milli);
|
for(var call : progView.calls) call.doFrame(milli);
|
||||||
|
@ -458,27 +480,9 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
page(progView.curAva).setMillis(lastPage.endMilli);
|
progView.curAva().setMillis(lastPage.endMilli);
|
||||||
Util.println("curAva: "+progView.curAva+" endMs: "+page(progView.curAva).endMilli);
|
Util.println("curAva: "+progView.curAva+" endMs: "+progView.curAva().endMilli);
|
||||||
} else {
|
} else lastPage.showHideSrcs(milli);
|
||||||
for(var layer : lastPage.layers) {
|
|
||||||
for(var src : layer.srcs) {
|
|
||||||
if(src.view.getVisibility()==VISIBLE) {
|
|
||||||
if(milli >= src.endMilli) src.hide();
|
|
||||||
else src.doEff();
|
|
||||||
} else if(milli < src.endMilli && milli >= src.startMilli) src.show();
|
|
||||||
}
|
|
||||||
if(milli >= layer.endMilli) {
|
|
||||||
layer.endMilli += layer.dur;
|
|
||||||
for(var src : layer.srcs) {
|
|
||||||
src.endMilli += layer.dur;
|
|
||||||
src.startMilli += layer.dur;
|
|
||||||
if(src.startTime > 0) src.hide();
|
|
||||||
else src.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
choreographer.postFrameCallback(this);
|
choreographer.postFrameCallback(this);
|
||||||
canAdd = false;
|
canAdd = false;
|
||||||
|
@ -486,6 +490,47 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncProg(long milli) {
|
void syncProg(long milli) {
|
||||||
|
if(insView!=null) {
|
||||||
|
insView.avas.clear();
|
||||||
|
for(int i=0; i<insView.pages.size(); i++) if(insView.pages.get(i).repeatTimes <= 0) {
|
||||||
|
for(var layer : insView.pages.get(i).layers) for(var src : layer.srcs) {
|
||||||
|
insView.removeView(src.view);
|
||||||
|
insView.calls.remove(src);
|
||||||
|
}
|
||||||
|
insView.pages.remove(i--);
|
||||||
|
}
|
||||||
|
if(insView.pages.isEmpty()) {
|
||||||
|
insView.release();
|
||||||
|
insView = null;
|
||||||
|
try {
|
||||||
|
var fOut = new FileOutputStream(Util.programDir + "/insert");
|
||||||
|
fOut.write("{}".getBytes());
|
||||||
|
fOut.flush();
|
||||||
|
fOut.getFD().sync();
|
||||||
|
fOut.close();
|
||||||
|
} catch(Exception e) {
|
||||||
|
Util.printStackTrace(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var dur = 0;
|
||||||
|
for(int i=0; i<insView.pages.size(); i++) if(insView.pages.get(i).isScheOn(milli+dur)) {
|
||||||
|
insView.avas.add(i);
|
||||||
|
dur += insView.pages.get(i).tDur;
|
||||||
|
}
|
||||||
|
if(dur==0) for(int i=0; i<insView.pages.size(); i++) if(insView.pages.get(i).sches==null) {
|
||||||
|
insView.avas.add(i);
|
||||||
|
dur += insView.pages.get(i).tDur;
|
||||||
|
}
|
||||||
|
if(dur!=0) {
|
||||||
|
insView.curAva = 0;
|
||||||
|
insView.curAva().setMillis(milli);
|
||||||
|
if(! insView.isShown()) setContentView(insView);
|
||||||
|
state = 6;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(progView!=null) {
|
||||||
progView.curTimes = 1;
|
progView.curTimes = 1;
|
||||||
progView.avas.clear();
|
progView.avas.clear();
|
||||||
var dur = 0;
|
var dur = 0;
|
||||||
|
@ -511,213 +556,32 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
||||||
progView.curAva = 0;
|
progView.curAva = 0;
|
||||||
if(start < milli) {
|
if(start < milli) {
|
||||||
do {
|
do {
|
||||||
start += page(progView.curAva++).tDur;
|
start += progView.curAva().tDur;
|
||||||
|
progView.curAva++;
|
||||||
} while(progView.curAva < progView.avas.size() && start<=milli);
|
} while(progView.curAva < progView.avas.size() && start<=milli);
|
||||||
start -= page(--progView.curAva).tDur;
|
progView.curAva--;
|
||||||
|
start -= progView.curAva().tDur;
|
||||||
syncMs = milli;
|
syncMs = milli;
|
||||||
Util.println("Sync. dur: "+dur+" milli: "+milli+" start: "+start+" diff: "+(milli - start));
|
Util.println("Sync. dur: "+dur+" milli: "+milli+" start: "+start+" diff: "+(milli - start));
|
||||||
}
|
}
|
||||||
page(progView.curAva).setMillis(start);
|
progView.curAva().setMillis(start);
|
||||||
if(state != 6) {
|
if(! progView.isShown()) setContentView(progView);
|
||||||
setContentView(progView);
|
|
||||||
state = 6;
|
state = 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Prog.Page page(int i) {
|
public void run() {
|
||||||
return progView.pages.get(progView.avas.get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(markerClass = UnstableApi.class) public void run() {
|
|
||||||
try {
|
try {
|
||||||
var serverSocket = new ServerSocket(3333);
|
var serverSocket = new ServerSocket(3333);
|
||||||
while(true) {
|
while(true) {
|
||||||
InputStream in = null;
|
|
||||||
OutputStream out = null;
|
|
||||||
try {
|
try {
|
||||||
Util.println("\nAccepting ...");
|
Util.println("\nAccepting ...");
|
||||||
final var socket = serverSocket.accept();
|
var socket = serverSocket.accept();
|
||||||
|
new SocketThread(this, socket).start();
|
||||||
Util.println("\nAccepted");
|
Util.println("\nAccepted");
|
||||||
in = socket.getInputStream();
|
|
||||||
out = socket.getOutputStream();
|
|
||||||
HashSet<String> hases = null;
|
|
||||||
ByteArrayOutputStream progJson = null;
|
|
||||||
while(true) {
|
|
||||||
var obj = JSMap.from(in);
|
|
||||||
var _type = obj.stnn("_type");
|
|
||||||
Util.println("_type: "+_type);
|
|
||||||
if("consult".equals(_type)) {
|
|
||||||
JSList<String> ids = obj.jslist("idList");
|
|
||||||
hases = new HashSet<>();
|
|
||||||
if(ids!=null) for(int i=0; i<ids.size(); i++) {
|
|
||||||
if(new File(Util.programDir + "/" + ids.get(i)).exists()) ids.remove(i--);
|
|
||||||
else hases.add(ids.get(i));
|
|
||||||
}
|
|
||||||
new JSMap("_type", _type, "idList", ids).write(out);
|
|
||||||
} else if("proStart".equals(_type)) {
|
|
||||||
Util.deleteFiles(obj.intg("proSize"), hases);
|
|
||||||
} else if("fileStart".equals(_type)) {
|
|
||||||
var size = obj.intg("size");
|
|
||||||
var name = obj.stnn("id");
|
|
||||||
Util.println(" size: " + size + " name: " + name);
|
|
||||||
if(name.equals("program")) {
|
|
||||||
progJson = new ByteArrayOutputStream();
|
|
||||||
IOs.writeCloseOut(progJson, in, size);
|
|
||||||
} else {
|
|
||||||
var fOut = new FileOutputStream(Util.programDir + "/" + name);
|
|
||||||
IOs.write(fOut, in, size);
|
|
||||||
fOut.flush();
|
|
||||||
fOut.getFD().sync();
|
|
||||||
fOut.close();
|
|
||||||
}
|
|
||||||
} else if("imgFileStart".equals(_type)) {
|
|
||||||
var size = obj.intg("size");
|
|
||||||
var fout = new FileOutputStream(Util.backImgFile);
|
|
||||||
IOs.write(fout, in, size);
|
|
||||||
fout.flush();
|
|
||||||
fout.getFD().sync();
|
|
||||||
fout.close();
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
backView.cosImg = BitmapFactory.decodeFile(Util.backImgFile);
|
|
||||||
backView.invalidate();
|
|
||||||
});
|
|
||||||
} else if("imgFileEnd".equals(_type)) {
|
|
||||||
new JSMap("success", true).write(out);
|
|
||||||
} else if("proEnd".equals(_type)) {
|
|
||||||
new JSMap("success", progJson!=null).write(out);
|
|
||||||
if(progJson!=null) {
|
|
||||||
var json = progJson.toByteArray();
|
|
||||||
progJson = null;
|
|
||||||
runOnUiThread(() -> initProg(json));
|
|
||||||
}
|
|
||||||
} else if("DelPrograms".equals(_type)) {
|
|
||||||
var latch = new CountDownLatch(1);
|
|
||||||
var ok = new AtomicBoolean(false);
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
ok.set(delProgFile());
|
|
||||||
latch.countDown();
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
latch.await();
|
|
||||||
} catch (InterruptedException ignored) {}
|
|
||||||
new JSMap("success", ok.get()).write(out);
|
|
||||||
} else if("DelBackImg".equals(_type)) {
|
|
||||||
MainActivity.ins.runOnUiThread(() -> {
|
|
||||||
MainActivity.ins.backView.cosImg = null;
|
|
||||||
MainActivity.ins.backView.invalidate();
|
|
||||||
});
|
|
||||||
new JSMap("success", new File(Util.backImgFile).delete()).write(out);
|
|
||||||
} else if("getPlayerState".equals(_type)) {
|
|
||||||
var descs = Util.getState(state);
|
|
||||||
new JSMap(
|
|
||||||
"code", state,
|
|
||||||
"des_en", descs[0],
|
|
||||||
"des", descs[1]
|
|
||||||
).write(out);
|
|
||||||
} else if("GetInfo".equals(_type)) {
|
|
||||||
var writer = new OutputStreamWriter(out);
|
|
||||||
var Fmt = new SimpleDateFormat("yy-MM-dd HH:mm:ss.SSS");
|
|
||||||
var dur = 0;
|
|
||||||
if(progView!=null) for(var page : progView.pages) dur += page.tDur;
|
|
||||||
writer.append("ProgSend: ").append(Fmt.format(new File(Util.programDir + "/program").lastModified())).append(" ProgDur: ").append(String.valueOf(dur));
|
|
||||||
if(progView!=null) writer.append(" Pages: ").append(String.valueOf(progView.avas.size())).append(" / ").append(String.valueOf(progView.pages.size()));
|
|
||||||
writer.append("\n");
|
|
||||||
writer.append(" Launch: ").append(Fmt.format(launchMilli)).append("\n");
|
|
||||||
writer.append(" Sync: ").append(Fmt.format(syncMs)).append("\n");
|
|
||||||
if(progView==null) writer.append(" ProgView is Null\n");
|
|
||||||
else if(progView.avas.isEmpty()) writer.append(" No Avas\n");
|
|
||||||
else writer.append("Page End: ").append(Fmt.format(page(progView.curAva).endMilli)).append(" CurPage: ").append(String.valueOf(progView.curAva)).append(" / ").append(String.valueOf(progView.avas.get(progView.curAva))).append("\n");
|
|
||||||
writer.append(" Current: ").append(Fmt.format(System.currentTimeMillis())).append("\n");
|
|
||||||
var statFs = new StatFs(Environment.getExternalStorageDirectory().getPath());
|
|
||||||
writer.append(" Disk: ").append(String.valueOf(statFs.getTotalBytes()/1000000)).append(" ").append(String.valueOf(statFs.getAvailableBytes()/1000000)).append(" ").append(String.valueOf(statFs.getFreeBytes()/1000000)).append(" (total avail free)\n");
|
|
||||||
var actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
|
|
||||||
var memoryInfo = new ActivityManager.MemoryInfo();
|
|
||||||
actManager.getMemoryInfo(memoryInfo);
|
|
||||||
writer.append(" Memory: ").append(String.valueOf(memoryInfo.totalMem/1000000)).append(" ").append(String.valueOf(memoryInfo.availMem/1000000)).append(" ").append(String.valueOf(memoryInfo.threshold/1000000)).append(" ").append(String.valueOf(memoryInfo.lowMemory)).append(" (total avail threshold low)\n");
|
|
||||||
var runtime = Runtime.getRuntime();
|
|
||||||
writer.append("Runtime: ").append(String.valueOf(runtime.maxMemory()/1000000)).append(" ").append(String.valueOf(runtime.totalMemory()/1000000)).append(" ").append(NumFmts.cfix2().format(runtime.freeMemory()*0.000001)).append(" (max total free)\n");
|
|
||||||
writer.append("/proc/stat\n");
|
|
||||||
IOs.writeCloseIn(writer, new FileReader("/proc/stat"));
|
|
||||||
writer.append("\n");
|
|
||||||
var latch = new CountDownLatch(1);
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
if(progView!=null && ! progView.avas.isEmpty()) {
|
|
||||||
var page = page(progView.curAva);
|
|
||||||
for(var layer : page.layers) for(var src : layer.srcs) if(src.view.getVisibility()==VISIBLE) {
|
|
||||||
try {
|
|
||||||
if(src.view instanceof SrcVideo) {
|
|
||||||
var view = (SrcVideo) src.view;
|
|
||||||
if(view.ijkPlayer!=null) {
|
|
||||||
writer.append("VideoPlaying: ").append(String.valueOf(view.ijkPlayer.isPlaying())).append("\tCur/Dur: ").append(String.valueOf(view.ijkPlayer.getCurrentPosition())).append("/").append(String.valueOf(view.ijkPlayer.getDuration())).append("\n");
|
|
||||||
var mediaInfo = view.ijkPlayer.getMediaInfo();
|
|
||||||
var vStream = mediaInfo.mMeta.mVideoStream;
|
|
||||||
writer.append(" BitRate: ").append(String.valueOf(view.ijkPlayer.getBitRate()/1000)).append("k\tFPS: ").append(String.valueOf(vStream.mFpsNum/(float)vStream.mFpsDen)).append(" (").append(String.valueOf(vStream.mFpsNum)).append("/").append(String.valueOf(vStream.mFpsDen)).append(")\n");
|
|
||||||
var tracks = view.ijkPlayer.getTrackInfo();
|
|
||||||
for(var track : tracks) writer.append(" ").append(track.getInfoInline()).append("\n");
|
|
||||||
writer.append(" Format: ").append(mediaInfo.mMeta.mFormat).append("\n");
|
|
||||||
writer.append("VideoDecoder: ").append(mediaInfo.mVideoDecoder).append(" ").append(mediaInfo.mVideoDecoderImpl).append(" (").append(String.valueOf(view.ijkPlayer.getVideoDecoder())).append(")\n");
|
|
||||||
writer.append("AudioDecoder: ").append(mediaInfo.mAudioDecoder).append(" ").append(mediaInfo.mAudioDecoderImpl).append("\n");
|
|
||||||
//writer.append("PROFILE: ").append(mediaInfo.mMeta.getString(IjkMediaMeta.IJKM_KEY_CODEC_PROFILE)).append("\n");
|
|
||||||
} else if(view.exoPlayer!=null) {
|
|
||||||
writer.append("VideoPlaying: ").append(String.valueOf(view.exoPlayer.isPlaying())).append(" ").append(String.valueOf(view.exoPlayer.getCurrentPosition())).append("/").append(String.valueOf(view.exoPlayer.getDuration())).append("\n");
|
|
||||||
writer.append(" BitRate: ").append(String.valueOf(view.bitRate/1000)).append("k\n");
|
|
||||||
writer.append("PlaybackStat: ").append(view.getState()).append("\n");
|
|
||||||
writer.append(" PlayerError: ").append(String.valueOf(view.exoPlayer.getPlayerError())).append("\n");
|
|
||||||
writer.append(" VideoFormat: ").append(String.valueOf(view.exoPlayer.getVideoFormat())).append("\n");
|
|
||||||
var cnt = view.exoPlayer.getRendererCount();
|
|
||||||
for(int rr=0; rr<cnt; rr++) writer.append(" Renderer: ").append(String.valueOf(view.exoPlayer.getRendererType(rr))).append(" ").append(String.valueOf(view.exoPlayer.getRenderer(rr))).append("\n");
|
|
||||||
writer.append("getPlaybackParameters: ").append(String.valueOf(view.exoPlayer.getPlaybackParameters())).append("\n");
|
|
||||||
}
|
|
||||||
writer.append("\n");
|
|
||||||
} else if(src.view instanceof SrcWeather) {
|
|
||||||
var view = (SrcWeather) src.view;
|
|
||||||
writer.append("SrcWeather html: ").append(view.html).append("\n");
|
|
||||||
} else if(src.view instanceof WebView) {
|
|
||||||
var view = (WebView) src.view;
|
|
||||||
writer.append("Title: ").append(view.getTitle()).append("\n");
|
|
||||||
writer.append(" Url: ").append(view.getUrl()).append("\n");
|
|
||||||
writer.append("OrUrl: ").append(view.getOriginalUrl()).append("\n");
|
|
||||||
writer.append("Progress: ").append(String.valueOf(view.getProgress())).append("\n");
|
|
||||||
}
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
latch.countDown();
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
latch.await();
|
|
||||||
} catch (InterruptedException ignored) {}
|
|
||||||
writer.flush();
|
|
||||||
} else if("GetLog".equals(_type)) {
|
|
||||||
out.write(Util.buf.toString().getBytes());
|
|
||||||
} else if("ListProgFiles".equals(_type)) {
|
|
||||||
var files = new File(Util.programDir).listFiles();
|
|
||||||
if(files == null) return;
|
|
||||||
Arrays.sort(files, (f1, f2) -> (int) (f2.lastModified() - f1.lastModified()));
|
|
||||||
var writer = new OutputStreamWriter(out);
|
|
||||||
for(var file : files) writer.append(file.getName()).append(' ').append(String.valueOf(file.length())).append('\n');
|
|
||||||
writer.append('\n');
|
|
||||||
writer.flush();
|
|
||||||
} else if("GetFile".equals(_type)) {
|
|
||||||
var name = obj.str("name");
|
|
||||||
if(name!=null) IOs.writeCloseIn(out, new FileInputStream(Util.programDir+"/"+name));
|
|
||||||
else new JSMap("code", 1, "msg", "name is null").write(out);
|
|
||||||
}
|
|
||||||
out.flush();
|
|
||||||
Util.println("cmd end");
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
var emsg = e.getMessage();
|
|
||||||
if(emsg!=null && ("Socket closed".equals(emsg) || emsg.endsWith("end-of-input"))) {
|
|
||||||
Util.println(emsg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.this, Util.toStr(e)).show());
|
MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.this, Util.toStr(e)).show());
|
||||||
Util.printStackTrace(e);
|
Util.printStackTrace(e);
|
||||||
} finally {
|
|
||||||
O.close(in, out);
|
|
||||||
Util.println("conn end\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
|
@ -2,11 +2,13 @@ package com.xixun.xixunplayer;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.speech.tts.TextToSpeech;
|
import android.speech.tts.TextToSpeech;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.webkit.JavascriptInterface;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
@ -31,10 +33,12 @@ public class Prog extends AbsLayout {
|
||||||
ArrayList<Choreographer.FrameCallback> calls = new ArrayList<>();
|
ArrayList<Choreographer.FrameCallback> calls = new ArrayList<>();
|
||||||
int curAva, curTimes = 1;
|
int curAva, curTimes = 1;
|
||||||
long waitTo = Long.MAX_VALUE;
|
long waitTo = Long.MAX_VALUE;
|
||||||
|
boolean isInsert;
|
||||||
|
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
public Prog(JSMap task, Context context) {
|
public Prog(JSMap task, Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
isInsert = task.bool("insert");
|
||||||
JSList<JSMap> jpages = task.jslist("items");
|
JSList<JSMap> jpages = task.jslist("items");
|
||||||
JSList<Long> partLengths = task.jslist("partLengths");
|
JSList<Long> partLengths = task.jslist("partLengths");
|
||||||
var isVertical = task.bool("isVertical");
|
var isVertical = task.bool("isVertical");
|
||||||
|
@ -49,8 +53,9 @@ public class Prog extends AbsLayout {
|
||||||
}
|
}
|
||||||
var width = partObj.intg("width");
|
var width = partObj.intg("width");
|
||||||
var height = partObj.intg("height");
|
var height = partObj.intg("height");
|
||||||
AbsLayout box = this;
|
AbsLayout box;
|
||||||
if(partLengths!=null && partLengths.size() > 1) {
|
if(partLengths==null || partLengths.size() <= 1) box = this;
|
||||||
|
else {
|
||||||
box = new AbsLayout(context);
|
box = new AbsLayout(context);
|
||||||
addView(box, new AbsLayout.LayoutParams(0, 0, width, height));
|
addView(box, new AbsLayout.LayoutParams(0, 0, width, height));
|
||||||
var mask = new View(context);
|
var mask = new View(context);
|
||||||
|
@ -76,11 +81,15 @@ public class Prog extends AbsLayout {
|
||||||
JSList<JSMap> layers = _program.jslist("layers");
|
JSList<JSMap> layers = _program.jslist("layers");
|
||||||
var isSimple = _program.intg("version")==2;
|
var isSimple = _program.intg("version")==2;
|
||||||
if(layers==null || layers.isEmpty()) continue;
|
if(layers==null || layers.isEmpty()) continue;
|
||||||
|
if(isSimple) {
|
||||||
|
width = _program.intg("width", Util.screenWidth);
|
||||||
|
height = _program.intg("height", Util.screenHeight);
|
||||||
|
}
|
||||||
var page = new Page();
|
var page = new Page();
|
||||||
page.name = _program.str("name");
|
page.name = _program.str("name");
|
||||||
page.repeatTimes = pageMap.intg("repeatTimes", 1);
|
page.repeatTimes = pageMap.intg("repeatTimes", 1);
|
||||||
page.parse(pageMap.jslist("schedules"));
|
page.parse(pageMap.jslist("schedules"));
|
||||||
HashMap<String, SrcVideo> videoMap = new HashMap<>();
|
HashMap<String, View> videoMap = new HashMap<>();
|
||||||
for(int ll=layers.size()-1; ll>=0; ll--) {
|
for(int ll=layers.size()-1; ll>=0; ll--) {
|
||||||
var layer = new Layer();
|
var layer = new Layer();
|
||||||
layer.isLoop = layers.get(ll).bool("repeat");
|
layer.isLoop = layers.get(ll).bool("repeat");
|
||||||
|
@ -97,10 +106,22 @@ public class Prog extends AbsLayout {
|
||||||
src.type = source.stnn("_type");
|
src.type = source.stnn("_type");
|
||||||
if(src.type.isEmpty()) continue;
|
if(src.type.isEmpty()) continue;
|
||||||
var timeSpan = source.intg("timeSpan")*1000;
|
var timeSpan = source.intg("timeSpan")*1000;
|
||||||
if(timeSpan==0) continue;
|
if(timeSpan==0) {
|
||||||
|
Util.println("\nError: timeSpan is 0. _type: "+src.type);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var geo = isSimple ? new AbsLayout.LayoutParams(0, 0, width, height) : new AbsLayout.LayoutParams(source.intg("left")+bdWidth, source.intg("top")+bdWidth, source.intg("width")-bdWidth-bdWidth, source.intg("height")-bdWidth-bdWidth);
|
var geo = isSimple ? new AbsLayout.LayoutParams(0, 0, width, height) : new AbsLayout.LayoutParams(source.intg("left")+bdWidth, source.intg("top")+bdWidth, source.intg("width")-bdWidth-bdWidth, source.intg("height")-bdWidth-bdWidth);
|
||||||
var notAudio = ! src.type.equals("Audio");
|
var notAudio = ! src.type.equals("Audio");
|
||||||
if((geo.width<=0 || geo.height<=0 || (geo.y>=height && height>0) || (geo.x>=width && width>0)) && notAudio) continue;
|
if(notAudio) {
|
||||||
|
if(geo.width<=0 || geo.height<=0) {
|
||||||
|
Util.println("\nError: width or height is 0. _type: "+src.type+" width: "+geo.width+" height: "+geo.height);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(box != this && ((geo.y>=height && height>0) || (geo.x>=width && width>0))) {
|
||||||
|
Util.println("\nError: y>=height or x>=width. _type: "+src.type+" width: "+width+" height: "+height+" x: "+geo.x+" y: "+geo.y);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
src.startTime = isSimple ? (layer.srcs.isEmpty() ? 0 : layer.srcs.get(layer.srcs.size()-1).endTime) : source.intg("playTime")*1000;
|
src.startTime = isSimple ? (layer.srcs.isEmpty() ? 0 : layer.srcs.get(layer.srcs.size()-1).endTime) : source.intg("playTime")*1000;
|
||||||
if(bdStart > src.startTime) bdStart = src.startTime;
|
if(bdStart > src.startTime) bdStart = src.startTime;
|
||||||
src.endTime = src.startTime + timeSpan;
|
src.endTime = src.startTime + timeSpan;
|
||||||
|
@ -183,18 +204,18 @@ public class Prog extends AbsLayout {
|
||||||
if(url==null) continue;
|
if(url==null) continue;
|
||||||
} else if(id==null) continue;
|
} else if(id==null) continue;
|
||||||
var key = isLive ? url : id + src.startTime + src.endTime;
|
var key = isLive ? url : id + src.startTime + src.endTime;
|
||||||
var videoView = videoMap.get(key);
|
var exist = videoMap.get(key);
|
||||||
if(videoView!=null) {
|
if(exist!=null) {
|
||||||
var geoOld = (AbsLayout.LayoutParams) videoView.getLayoutParams();
|
var geoOld = (AbsLayout.LayoutParams) exist.getLayoutParams();
|
||||||
if(geo.width*geo.height > geoOld.width*geoOld.height) {
|
if(geo.width*geo.height > geoOld.width*geoOld.height) {
|
||||||
videoView.setLayoutParams(geo);
|
exist.setLayoutParams(geo);
|
||||||
geo = geoOld;
|
geo = geoOld;
|
||||||
}
|
}
|
||||||
src.view = new SrcCopy(context, videoView);
|
src.view = new SrcCopy(context, exist);
|
||||||
((SrcCopy) src.view).scaleX = 0;
|
((SrcCopy) src.view).scaleX = 0;
|
||||||
} else {
|
} else {
|
||||||
src.view = new SrcVideo(context, isLive ? url : Util.programDir+"/"+id, source.intg("vol", 100) / 100.0f, isLive);
|
src.view = new SrcVideo(context, isLive ? url : Util.programDir+"/"+id, source.intg("vol", 100) / 100.0f, isLive);
|
||||||
videoMap.put(key, (SrcVideo) src.view);
|
videoMap.put(key, src.view);
|
||||||
}
|
}
|
||||||
} else if(src.type.equals("Audio")) {
|
} else if(src.type.equals("Audio")) {
|
||||||
if(id==null) continue;
|
if(id==null) continue;
|
||||||
|
@ -207,7 +228,7 @@ public class Prog extends AbsLayout {
|
||||||
var speechRate = (float) source.dbl("voiceRate");
|
var speechRate = (float) source.dbl("voiceRate");
|
||||||
if(mode!=null ? mode.endsWith("roll") : (imgs.size()==1 && imgs.get(0).intg("picDuration")==0)) {
|
if(mode!=null ? mode.endsWith("roll") : (imgs.size()==1 && imgs.get(0).intg("picDuration")==0)) {
|
||||||
var img = imgs.get(0);
|
var img = imgs.get(0);
|
||||||
src.view = new SrcScroll(this, img);
|
src.view = new SrcScroll(this, img, null);
|
||||||
if(hasTTS) {
|
if(hasTTS) {
|
||||||
src.text = img.str("text");
|
src.text = img.str("text");
|
||||||
if(src.text!=null) {
|
if(src.text!=null) {
|
||||||
|
@ -262,13 +283,17 @@ public class Prog extends AbsLayout {
|
||||||
webView.setBackgroundColor(Color.TRANSPARENT);
|
webView.setBackgroundColor(Color.TRANSPARENT);
|
||||||
webView.setVerticalScrollBarEnabled(false);
|
webView.setVerticalScrollBarEnabled(false);
|
||||||
webView.setHorizontalScrollBarEnabled(false);
|
webView.setHorizontalScrollBarEnabled(false);
|
||||||
webView.setInitialScale(100);
|
webView.setInitialScale(source.intg("zoom", 100));
|
||||||
webView.getSettings().setJavaScriptEnabled(true);
|
webView.getSettings().setJavaScriptEnabled(true);
|
||||||
webView.setWebViewClient(new WebViewClient() {
|
webView.setWebViewClient(new WebViewClient() {
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public void onPageFinished(WebView view, String url) {
|
||||||
|
view.loadUrl("javascript:window.scrollTo("+source.str("offX", "0")+", "+source.str("offY", "0")+")");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
webView.loadUrl(source.stnn("url"));
|
webView.loadUrl(source.stnn("url"));
|
||||||
src.view = webView;
|
src.view = webView;
|
||||||
|
@ -279,6 +304,41 @@ public class Prog extends AbsLayout {
|
||||||
else if(src.type.startsWith("Weather")) src.view = new SrcWeather(context, source);
|
else if(src.type.startsWith("Weather")) src.view = new SrcWeather(context, source);
|
||||||
else if(src.type.startsWith("VistorSource")) src.view = new SrcVisitor(this, source);
|
else if(src.type.startsWith("VistorSource")) src.view = new SrcVisitor(this, source);
|
||||||
else if(src.type.startsWith("MultiLineText")) src.view = new SrcSensor(this, source, geo.width, geo.height);
|
else if(src.type.startsWith("MultiLineText")) src.view = new SrcSensor(this, source, geo.width, geo.height);
|
||||||
|
else if(src.type.startsWith("SingleLineText")) {
|
||||||
|
var webView = new WebView(context);
|
||||||
|
webView.setBackgroundColor(Color.TRANSPARENT);
|
||||||
|
webView.setVerticalScrollBarEnabled(false);
|
||||||
|
webView.setHorizontalScrollBarEnabled(false);
|
||||||
|
webView.setInitialScale(100);
|
||||||
|
webView.getSettings().setJavaScriptEnabled(true);
|
||||||
|
webView.setLayoutParams(new AbsLayout.LayoutParams(0, -geo.height, geo.width, geo.height));
|
||||||
|
var html = source.stnn("html");
|
||||||
|
var prefix = "<body style=\"color:#fff; margin:0; padding:0; white-space:nowrap; ";
|
||||||
|
var lineHeight = source.get("lineHeight");
|
||||||
|
if(lineHeight!=null) prefix += "line-height:"+lineHeight+";";
|
||||||
|
var fontSize = lineHeight instanceof Number ? geo.height / ((Number)lineHeight).doubleValue() : geo.height;
|
||||||
|
prefix += "height:"+geo.height+"; font-size:"+fontSize+"px;\">";
|
||||||
|
var suffix = "</body><script>window.onload = function() {\n" +
|
||||||
|
"window.java.setWidth(document.body.scrollWidth);};</script>";
|
||||||
|
source.put("effect", "to left");
|
||||||
|
source.put("effectSpeed", source.intg("speed"));
|
||||||
|
var view = new SrcScroll(this, source, Bitmap.createBitmap(geo.width, geo.height, Bitmap.Config.ARGB_8888));
|
||||||
|
src.view = view;
|
||||||
|
webView.addJavascriptInterface(new Object() {
|
||||||
|
@JavascriptInterface
|
||||||
|
public void setWidth(int width) {
|
||||||
|
MainActivity.ins.runOnUiThread(() -> {
|
||||||
|
var hhh = view.imgs.get(0).getHeight();
|
||||||
|
var www = width + hhh;
|
||||||
|
webView.getLayoutParams().width = www;
|
||||||
|
view.imgs.set(0, Bitmap.createBitmap(www, hhh, Bitmap.Config.ARGB_8888));
|
||||||
|
box.addView(webView);
|
||||||
|
view.webView = webView;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, "java");
|
||||||
|
webView.loadDataWithBaseURL(null, prefix+html+suffix, "text/html", "UTF-8", null);
|
||||||
|
}
|
||||||
else continue;
|
else continue;
|
||||||
if(src.view==null) continue;
|
if(src.view==null) continue;
|
||||||
src.view.setVisibility(GONE);
|
src.view.setVisibility(GONE);
|
||||||
|
@ -322,6 +382,9 @@ public class Prog extends AbsLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Page curAva() {
|
||||||
|
return pages.get(avas.get(curAva));
|
||||||
|
}
|
||||||
void release() {
|
void release() {
|
||||||
try {
|
try {
|
||||||
setVisibility(GONE);
|
setVisibility(GONE);
|
||||||
|
@ -528,7 +591,7 @@ public class Prog extends AbsLayout {
|
||||||
for(var layer : layers) for(var src : layer.srcs) src.hide();
|
for(var layer : layers) for(var src : layer.srcs) src.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMillis(long milli) {
|
void setMillis(long milli) {
|
||||||
endMilli = milli + sDur;
|
endMilli = milli + sDur;
|
||||||
for(var layer : layers) {
|
for(var layer : layers) {
|
||||||
if(layer.isLoop) layer.endMilli = milli + layer.dur;
|
if(layer.isLoop) layer.endMilli = milli + layer.dur;
|
||||||
|
@ -539,7 +602,26 @@ public class Prog extends AbsLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public boolean isScheOn(long milli) {
|
void showHideSrcs(long milli) {
|
||||||
|
for(var layer : layers) {
|
||||||
|
for(var src : layer.srcs) {
|
||||||
|
if(src.view.getVisibility()==VISIBLE) {
|
||||||
|
if(milli >= src.endMilli) src.hide();
|
||||||
|
else src.doEff();
|
||||||
|
} else if(milli < src.endMilli && milli >= src.startMilli) src.show();
|
||||||
|
}
|
||||||
|
if(milli >= layer.endMilli) {
|
||||||
|
layer.endMilli += layer.dur;
|
||||||
|
for(var src : layer.srcs) {
|
||||||
|
src.endMilli += layer.dur;
|
||||||
|
src.startMilli += layer.dur;
|
||||||
|
if(src.startTime > 0) src.hide();
|
||||||
|
else src.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean isScheOn(long milli) {
|
||||||
if(sches==null) return false;
|
if(sches==null) return false;
|
||||||
var local = milli + Dates.zoneOff;
|
var local = milli + Dates.zoneOff;
|
||||||
var time = local % 86400000L;
|
var time = local % 86400000L;
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class Server extends Service {
|
||||||
@Override
|
@Override
|
||||||
public String getProgramName() throws RemoteException {
|
public String getProgramName() throws RemoteException {
|
||||||
try {
|
try {
|
||||||
var name = MainActivity.ins!=null && MainActivity.ins.progView!=null && ! MainActivity.ins.progView.avas.isEmpty() ? MainActivity.ins.page(MainActivity.ins.progView.curAva).name : null;
|
var name = MainActivity.ins!=null && MainActivity.ins.progView!=null && ! MainActivity.ins.progView.avas.isEmpty() ? MainActivity.ins.progView.curAva().name : null;
|
||||||
Util.println("Server getProgramName. <-"+name);
|
Util.println("Server getProgramName. <-"+name);
|
||||||
return name;
|
return name;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -257,10 +257,18 @@ public class Server extends Service {
|
||||||
"commandId", commandId,
|
"commandId", commandId,
|
||||||
"img", img
|
"img", img
|
||||||
).toString();
|
).toString();
|
||||||
|
} else if(_type.equalsIgnoreCase("getProgramTask")) {
|
||||||
|
var task = JSMap.fromClose(new FileInputStream(Util.programDir+"/program")).jsmap("task");
|
||||||
|
return new JSMap(
|
||||||
|
"_type", "ProgramTaskCallback",
|
||||||
|
"cardId", Util.getCardId(),
|
||||||
|
"commandId", commandId,
|
||||||
|
"task", task
|
||||||
|
).toString();
|
||||||
}
|
}
|
||||||
return new JSMap(
|
return new JSMap(
|
||||||
"_type", "Error",
|
"_type", "Error",
|
||||||
"errorMessage", "Unknow Type",
|
"errorMessage", "Unknown Type: "+_type,
|
||||||
"cardId", Util.getCardId(),
|
"cardId", Util.getCardId(),
|
||||||
"commandId", commandId
|
"commandId", commandId
|
||||||
).toString();
|
).toString();
|
||||||
|
@ -268,7 +276,7 @@ public class Server extends Service {
|
||||||
Util.printStackTrace(e);
|
Util.printStackTrace(e);
|
||||||
return new JSMap(
|
return new JSMap(
|
||||||
"_type", "Error",
|
"_type", "Error",
|
||||||
"errorMessage", e.toString(),
|
"errorMessage", Util.toStr(e),
|
||||||
"cardId", Util.getCardId(),
|
"cardId", Util.getCardId(),
|
||||||
"commandId", commandId
|
"commandId", commandId
|
||||||
).toString();
|
).toString();
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
package com.xixun.xixunplayer;
|
||||||
|
|
||||||
|
import static android.view.View.VISIBLE;
|
||||||
|
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.StatFs;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
|
||||||
|
import androidx.annotation.OptIn;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import gnph.util.IOs;
|
||||||
|
import gnph.util.JSList;
|
||||||
|
import gnph.util.JSMap;
|
||||||
|
import gnph.util.NumFmts;
|
||||||
|
import gnph.util.O;
|
||||||
|
|
||||||
|
public class SocketThread extends Thread {
|
||||||
|
MainActivity main;
|
||||||
|
Socket socket;
|
||||||
|
InputStream in;
|
||||||
|
OutputStream out;
|
||||||
|
public SocketThread(MainActivity main, Socket socket) {
|
||||||
|
this.main = main;
|
||||||
|
this.socket = socket;
|
||||||
|
}
|
||||||
|
@OptIn(markerClass = UnstableApi.class) @Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
socket.setSoTimeout(600000);
|
||||||
|
Util.socketThreads.add(this);
|
||||||
|
in = socket.getInputStream();
|
||||||
|
out = socket.getOutputStream();
|
||||||
|
HashSet<String> hases = null;
|
||||||
|
ByteArrayOutputStream progJson = null;
|
||||||
|
while(true) {
|
||||||
|
var obj = JSMap.from(in);
|
||||||
|
var _type = obj.stnn("_type");
|
||||||
|
Util.println("_type: "+_type);
|
||||||
|
if("consult".equals(_type)) {
|
||||||
|
JSList<String> ids = obj.jslist("idList");
|
||||||
|
hases = new HashSet<>();
|
||||||
|
if(ids!=null) for(int i=0; i<ids.size(); i++) {
|
||||||
|
if(new File(Util.programDir + "/" + ids.get(i)).exists()) ids.remove(i--);
|
||||||
|
else hases.add(ids.get(i));
|
||||||
|
}
|
||||||
|
new JSMap("_type", _type, "idList", ids).write(out);
|
||||||
|
} else if("proStart".equals(_type)) {
|
||||||
|
Util.deleteFiles(obj.intg("proSize"), hases);
|
||||||
|
} else if("fileStart".equals(_type)) {
|
||||||
|
var size = obj.intg("size");
|
||||||
|
var name = obj.stnn("id");
|
||||||
|
Util.println(" size: " + size + " name: " + name);
|
||||||
|
if(name.equals("program")) {
|
||||||
|
progJson = new ByteArrayOutputStream();
|
||||||
|
IOs.writeCloseOut(progJson, in, size);
|
||||||
|
} else {
|
||||||
|
var fOut = new FileOutputStream(Util.programDir + "/" + name);
|
||||||
|
IOs.write(fOut, in, size);
|
||||||
|
fOut.flush();
|
||||||
|
fOut.getFD().sync();
|
||||||
|
fOut.close();
|
||||||
|
}
|
||||||
|
} else if("imgFileStart".equals(_type)) {
|
||||||
|
var size = obj.intg("size");
|
||||||
|
var fout = new FileOutputStream(Util.backImgFile);
|
||||||
|
IOs.write(fout, in, size);
|
||||||
|
fout.flush();
|
||||||
|
fout.getFD().sync();
|
||||||
|
fout.close();
|
||||||
|
main.runOnUiThread(() -> {
|
||||||
|
main.backView.cosImg = BitmapFactory.decodeFile(Util.backImgFile);
|
||||||
|
main.backView.invalidate();
|
||||||
|
});
|
||||||
|
} else if("imgFileEnd".equals(_type)) {
|
||||||
|
new JSMap("success", true).write(out);
|
||||||
|
} else if("proEnd".equals(_type)) {
|
||||||
|
new JSMap("success", progJson!=null).write(out);
|
||||||
|
if(progJson!=null) {
|
||||||
|
var json = progJson.toByteArray();
|
||||||
|
progJson = null;
|
||||||
|
main.runOnUiThread(() -> main.initProg(json));
|
||||||
|
}
|
||||||
|
} else if("DelPrograms".equals(_type)) {
|
||||||
|
var latch = new CountDownLatch(1);
|
||||||
|
var ok = new AtomicBoolean(false);
|
||||||
|
main.runOnUiThread(() -> {
|
||||||
|
ok.set(main.delProgFile());
|
||||||
|
latch.countDown();
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (InterruptedException ignored) {}
|
||||||
|
new JSMap("success", ok.get()).write(out);
|
||||||
|
} else if("DelBackImg".equals(_type)) {
|
||||||
|
MainActivity.ins.runOnUiThread(() -> {
|
||||||
|
MainActivity.ins.backView.cosImg = null;
|
||||||
|
MainActivity.ins.backView.invalidate();
|
||||||
|
});
|
||||||
|
new JSMap("success", new File(Util.backImgFile).delete()).write(out);
|
||||||
|
} else if("getPlayerState".equals(_type)) {
|
||||||
|
var descs = Util.getState(main.state);
|
||||||
|
new JSMap(
|
||||||
|
"code", main.state,
|
||||||
|
"des_en", descs[0],
|
||||||
|
"des", descs[1]
|
||||||
|
).write(out);
|
||||||
|
} else if("GetInfo".equals(_type)) {
|
||||||
|
var writer = new OutputStreamWriter(out);
|
||||||
|
var Fmt = new SimpleDateFormat("yy-MM-dd HH:mm:ss.SSS");
|
||||||
|
var dur = 0;
|
||||||
|
if(main.progView!=null) for(var page : main.progView.pages) dur += page.tDur;
|
||||||
|
writer.append("ProgSend: ").append(Fmt.format(new File(Util.programDir + "/program").lastModified())).append(" ProgDur: ").append(String.valueOf(dur));
|
||||||
|
if(main.progView!=null) writer.append(" Pages: ").append(String.valueOf(main.progView.avas.size())).append(" / ").append(String.valueOf(main.progView.pages.size()));
|
||||||
|
writer.append("\n");
|
||||||
|
writer.append(" Launch: ").append(Fmt.format(main.launchMilli)).append("\n");
|
||||||
|
writer.append(" Sync: ").append(Fmt.format(main.syncMs)).append("\n");
|
||||||
|
if(main.progView==null) writer.append(" ProgView is Null\n");
|
||||||
|
else if(main.progView.avas.isEmpty()) writer.append(" No Avas\n");
|
||||||
|
else writer.append("Page End: ").append(Fmt.format(main.progView.curAva().endMilli)).append(" CurPage: ").append(String.valueOf(main.progView.curAva)).append(" / ").append(String.valueOf(main.progView.avas.get(main.progView.curAva))).append("\n");
|
||||||
|
writer.append(" Current: ").append(Fmt.format(System.currentTimeMillis())).append("\n");
|
||||||
|
var statFs = new StatFs(Environment.getExternalStorageDirectory().getPath());
|
||||||
|
writer.append(" Disk: ").append(String.valueOf(statFs.getTotalBytes()/1000000)).append(" ").append(String.valueOf(statFs.getAvailableBytes()/1000000)).append(" ").append(String.valueOf(statFs.getFreeBytes()/1000000)).append(" (total avail free)\n");
|
||||||
|
var actManager = (ActivityManager) main.getSystemService(main.ACTIVITY_SERVICE);
|
||||||
|
var memoryInfo = new ActivityManager.MemoryInfo();
|
||||||
|
actManager.getMemoryInfo(memoryInfo);
|
||||||
|
writer.append(" Memory: ").append(String.valueOf(memoryInfo.totalMem/1000000)).append(" ").append(String.valueOf(memoryInfo.availMem/1000000)).append(" ").append(String.valueOf(memoryInfo.threshold/1000000)).append(" ").append(String.valueOf(memoryInfo.lowMemory)).append(" (total avail threshold low)\n");
|
||||||
|
var runtime = Runtime.getRuntime();
|
||||||
|
writer.append("Runtime: ").append(String.valueOf(runtime.maxMemory()/1000000)).append(" ").append(String.valueOf(runtime.totalMemory()/1000000)).append(" ").append(NumFmts.cfix2().format(runtime.freeMemory()*0.000001)).append(" (max total free)\n");
|
||||||
|
// writer.append("/proc/stat\n");
|
||||||
|
// IOs.writeCloseIn(writer, new FileReader("/proc/stat"));
|
||||||
|
writer.append("\nSockets ").append(String.valueOf(Util.socketThreads.size())).append("\n");
|
||||||
|
for(var socket : Util.socketThreads) writer.append(" ").append(String.valueOf(socket.socket.getInetAddress())).append(":").append(String.valueOf(socket.socket.getPort())).append(" Buf:").append(String.valueOf(socket.socket.getReceiveBufferSize()/1000)).append("k SoLinger:").append(String.valueOf(socket.socket.getSoLinger())).append("\n");
|
||||||
|
|
||||||
|
writer.append("\n");
|
||||||
|
var latch = new CountDownLatch(1);
|
||||||
|
main.runOnUiThread(() -> {
|
||||||
|
if(main.progView!=null && ! main.progView.avas.isEmpty()) {
|
||||||
|
var page = main.progView.curAva();
|
||||||
|
for(var layer : page.layers) for(var src : layer.srcs) if(src.view.getVisibility()==VISIBLE) {
|
||||||
|
try {
|
||||||
|
if(src.view instanceof SrcVideo) {
|
||||||
|
var view = (SrcVideo) src.view;
|
||||||
|
if(view.ijkPlayer!=null) {
|
||||||
|
writer.append("VideoPlaying: ").append(String.valueOf(view.ijkPlayer.isPlaying())).append("\tCur/Dur: ").append(String.valueOf(view.ijkPlayer.getCurrentPosition())).append("/").append(String.valueOf(view.ijkPlayer.getDuration())).append("\n");
|
||||||
|
var mediaInfo = view.ijkPlayer.getMediaInfo();
|
||||||
|
var vStream = mediaInfo.mMeta.mVideoStream;
|
||||||
|
writer.append(" BitRate: ").append(String.valueOf(view.ijkPlayer.getBitRate()/1000)).append("k\tFPS: ").append(String.valueOf(vStream.mFpsNum/(float)vStream.mFpsDen)).append(" (").append(String.valueOf(vStream.mFpsNum)).append("/").append(String.valueOf(vStream.mFpsDen)).append(")\n");
|
||||||
|
var tracks = view.ijkPlayer.getTrackInfo();
|
||||||
|
for(var track : tracks) writer.append(" ").append(track.getInfoInline()).append("\n");
|
||||||
|
writer.append(" Format: ").append(mediaInfo.mMeta.mFormat).append("\n");
|
||||||
|
writer.append("VideoDecoder: ").append(mediaInfo.mVideoDecoder).append(" ").append(mediaInfo.mVideoDecoderImpl).append(" (").append(String.valueOf(view.ijkPlayer.getVideoDecoder())).append(")\n");
|
||||||
|
writer.append("AudioDecoder: ").append(mediaInfo.mAudioDecoder).append(" ").append(mediaInfo.mAudioDecoderImpl).append("\n");
|
||||||
|
//writer.append("PROFILE: ").append(mediaInfo.mMeta.getString(IjkMediaMeta.IJKM_KEY_CODEC_PROFILE)).append("\n");
|
||||||
|
} else if(view.exoPlayer!=null) {
|
||||||
|
writer.append("VideoPlaying: ").append(String.valueOf(view.exoPlayer.isPlaying())).append(" ").append(String.valueOf(view.exoPlayer.getCurrentPosition())).append("/").append(String.valueOf(view.exoPlayer.getDuration())).append("\n");
|
||||||
|
writer.append(" BitRate: ").append(String.valueOf(view.bitRate/1000)).append("k\n");
|
||||||
|
writer.append("PlaybackStat: ").append(view.getState()).append("\n");
|
||||||
|
writer.append(" PlayerError: ").append(String.valueOf(view.exoPlayer.getPlayerError())).append("\n");
|
||||||
|
writer.append(" VideoFormat: ").append(String.valueOf(view.exoPlayer.getVideoFormat())).append("\n");
|
||||||
|
var cnt = view.exoPlayer.getRendererCount();
|
||||||
|
for(int rr=0; rr<cnt; rr++) writer.append(" Renderer: ").append(String.valueOf(view.exoPlayer.getRendererType(rr))).append(" ").append(String.valueOf(view.exoPlayer.getRenderer(rr))).append("\n");
|
||||||
|
writer.append("getPlaybackParameters: ").append(String.valueOf(view.exoPlayer.getPlaybackParameters())).append("\n");
|
||||||
|
}
|
||||||
|
writer.append("\n");
|
||||||
|
} else if(src.view instanceof SrcWeather) {
|
||||||
|
var view = (SrcWeather) src.view;
|
||||||
|
writer.append("SrcWeather html: ").append(view.html).append("\n");
|
||||||
|
} else if(src.view instanceof WebView) {
|
||||||
|
var view = (WebView) src.view;
|
||||||
|
writer.append("Title: ").append(view.getTitle()).append("\n");
|
||||||
|
writer.append(" Url: ").append(view.getUrl()).append("\n");
|
||||||
|
writer.append("OrUrl: ").append(view.getOriginalUrl()).append("\n");
|
||||||
|
writer.append("Progress: ").append(String.valueOf(view.getProgress())).append("\n");
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
latch.countDown();
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (InterruptedException ignored) {}
|
||||||
|
writer.flush();
|
||||||
|
} else if("GetLog".equals(_type)) {
|
||||||
|
out.write(Util.buf.toString().getBytes());
|
||||||
|
} else if("ListProgFiles".equals(_type)) {
|
||||||
|
var files = new File(Util.programDir).listFiles();
|
||||||
|
if(files == null) return;
|
||||||
|
Arrays.sort(files, (f1, f2) -> (int) (f2.lastModified() - f1.lastModified()));
|
||||||
|
var writer = new OutputStreamWriter(out);
|
||||||
|
for(var file : files) writer.append(file.getName()).append(' ').append(String.valueOf(file.length())).append('\n');
|
||||||
|
writer.append('\n');
|
||||||
|
writer.flush();
|
||||||
|
} else if("GetFile".equals(_type)) {
|
||||||
|
var name = obj.str("name");
|
||||||
|
if(name!=null) IOs.writeCloseIn(out, new FileInputStream(Util.programDir+"/"+name));
|
||||||
|
else new JSMap("code", 1, "msg", "name is null").write(out);
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
Util.println("cmd end");
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
var emsg = e.getMessage();
|
||||||
|
if(emsg!=null && ("Socket closed".equals(emsg) || emsg.endsWith("end-of-input"))) {
|
||||||
|
Util.println(emsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
main.runOnUiThread(() -> Util.makeText(main, Util.toStr(e)).show());
|
||||||
|
Util.printStackTrace(e);
|
||||||
|
} finally {
|
||||||
|
Util.socketThreads.remove(this);
|
||||||
|
O.close(in, out, socket);
|
||||||
|
Util.println("conn end\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import android.graphics.Canvas;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
@ -19,14 +20,14 @@ public class SrcScroll extends View implements Choreographer.FrameCallback {
|
||||||
|
|
||||||
ArrayList<Bitmap> imgs = new ArrayList<>();
|
ArrayList<Bitmap> imgs = new ArrayList<>();
|
||||||
Rect rect = new Rect();
|
Rect rect = new Rect();
|
||||||
int imgsWidth;
|
|
||||||
int interval, cur, end, step;
|
int interval, cur, end, step;
|
||||||
|
WebView webView;
|
||||||
char effect;
|
char effect;
|
||||||
|
|
||||||
public SrcScroll(Prog prog, JSMap json) {
|
public SrcScroll(Prog prog, JSMap json, Bitmap img) {
|
||||||
super(prog.getContext());
|
super(prog.getContext());
|
||||||
var img = BitmapFactory.decodeFile(Util.programDir+"/"+json.stnn("id"));
|
if(img==null) img = BitmapFactory.decodeFile(Util.programDir+"/"+json.stnn("id"));
|
||||||
imgsWidth = img.getWidth();
|
var imgsWidth = img.getWidth();
|
||||||
if(imgsWidth <= 8192) imgs.add(img);
|
if(imgsWidth <= 8192) imgs.add(img);
|
||||||
else {
|
else {
|
||||||
var rem = img.getWidth();
|
var rem = img.getWidth();
|
||||||
|
@ -57,11 +58,21 @@ public class SrcScroll extends View implements Choreographer.FrameCallback {
|
||||||
}
|
}
|
||||||
if(effect!=0) prog.calls.add(this);
|
if(effect!=0) prog.calls.add(this);
|
||||||
}
|
}
|
||||||
|
int aaaaaa;
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(@NonNull Canvas canvas) {
|
protected void onDraw(@NonNull Canvas canvas) {
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
if(imgs.isEmpty()) return;
|
if(imgs.isEmpty()) return;
|
||||||
try {
|
try {
|
||||||
|
if(webView!=null && aaaaaa++>30) {
|
||||||
|
var canva = new Canvas(imgs.get(0));
|
||||||
|
webView.draw(canva);
|
||||||
|
webView.setVisibility(GONE);
|
||||||
|
webView = null;
|
||||||
|
freshCnt = cur = 0;
|
||||||
|
if(effect=='l') end = -(imgs.get(0).getWidth()-step);
|
||||||
|
else if(effect=='r') end = imgs.get(0).getWidth()-step;
|
||||||
|
}
|
||||||
drawOther(canvas);
|
drawOther(canvas);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
setVisibility(GONE);
|
setVisibility(GONE);
|
||||||
|
|
|
@ -127,8 +127,10 @@ public class SrcSensor extends WebView implements IntentReceiver, Choreographer.
|
||||||
@Override
|
@Override
|
||||||
public void doFrame(long ms) {
|
public void doFrame(long ms) {
|
||||||
if(! isShown()) {
|
if(! isShown()) {
|
||||||
|
if(! isFirst) {
|
||||||
act.environs.remove(this);
|
act.environs.remove(this);
|
||||||
isFirst = true;
|
isFirst = true;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean needRefresh = false;
|
boolean needRefresh = false;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.xixun.xixunplayer;
|
package com.xixun.xixunplayer;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
|
@ -15,6 +16,7 @@ import androidx.media3.exoplayer.SeekParameters;
|
||||||
import tv.danmaku.ijk.media.player.IMediaPlayer;
|
import tv.danmaku.ijk.media.player.IMediaPlayer;
|
||||||
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
|
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
|
||||||
|
|
||||||
|
@SuppressLint("ViewConstructor")
|
||||||
public class SrcVideo extends TextureView implements TextureView.SurfaceTextureListener {
|
public class SrcVideo extends TextureView implements TextureView.SurfaceTextureListener {
|
||||||
|
|
||||||
String path;
|
String path;
|
||||||
|
@ -44,7 +46,7 @@ public class SrcVideo extends TextureView implements TextureView.SurfaceTextureL
|
||||||
}
|
}
|
||||||
void initIjk() {
|
void initIjk() {
|
||||||
ijkPlayer = new IjkMediaPlayer();
|
ijkPlayer = new IjkMediaPlayer();
|
||||||
//ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
|
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-avc", 1);
|
||||||
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
|
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
|
||||||
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", 1);
|
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", 1);
|
||||||
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
|
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
|
||||||
|
@ -54,6 +56,7 @@ public class SrcVideo extends TextureView implements TextureView.SurfaceTextureL
|
||||||
ijkPlayer.setLooping(true);
|
ijkPlayer.setLooping(true);
|
||||||
ijkPlayer.setVolume(vol, vol);
|
ijkPlayer.setVolume(vol, vol);
|
||||||
ijkPlayer.setOnPreparedListener((IMediaPlayer var1)->{
|
ijkPlayer.setOnPreparedListener((IMediaPlayer var1)->{
|
||||||
|
ijkPlayer.setOnPreparedListener(null);
|
||||||
bitRate = ijkPlayer.getBitRate();
|
bitRate = ijkPlayer.getBitRate();
|
||||||
if(bitRate > 12000000) {
|
if(bitRate > 12000000) {
|
||||||
setSurfaceTextureListener(null);
|
setSurfaceTextureListener(null);
|
||||||
|
@ -62,6 +65,10 @@ public class SrcVideo extends TextureView implements TextureView.SurfaceTextureL
|
||||||
}
|
}
|
||||||
if(isShown()) start();
|
if(isShown()) start();
|
||||||
});
|
});
|
||||||
|
ijkPlayer.setOnErrorListener((IMediaPlayer var1, int var2, int var3)->{
|
||||||
|
Util.println(" Video Error: "+var1+" "+var2+" "+var3);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
ijkPlayer.prepareAsync();
|
ijkPlayer.prepareAsync();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Util.makeText(getContext(), Util.toStr(e)).show();
|
Util.makeText(getContext(), Util.toStr(e)).show();
|
||||||
|
@ -71,7 +78,7 @@ public class SrcVideo extends TextureView implements TextureView.SurfaceTextureL
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
|
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
|
||||||
setSurfaceTextureListener(null);
|
Util.println(" onSurfaceTextureAvailable "+(ijkPlayer==null?"ijkPlayer==null":""));
|
||||||
if(ijkPlayer!=null) ijkPlayer.setSurface(new Surface(surface));
|
if(ijkPlayer!=null) ijkPlayer.setSurface(new Surface(surface));
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.xixun.xixunplayer;
|
package com.xixun.xixunplayer;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
package com.xixun.xixunplayer;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.SurfaceHolder;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.OptIn;
|
||||||
|
import androidx.media3.common.MediaItem;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
import androidx.media3.exoplayer.ExoPlayer;
|
||||||
|
import androidx.media3.exoplayer.SeekParameters;
|
||||||
|
|
||||||
|
import tv.danmaku.ijk.media.player.IMediaPlayer;
|
||||||
|
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
|
||||||
|
|
||||||
|
@SuppressLint("ViewConstructor")
|
||||||
|
public class SrcVideoSurface extends SurfaceView implements SurfaceHolder.Callback {
|
||||||
|
|
||||||
|
String path;
|
||||||
|
float vol;
|
||||||
|
IjkMediaPlayer ijkPlayer;
|
||||||
|
ExoPlayer exoPlayer;
|
||||||
|
long bitRate;
|
||||||
|
boolean isLive;
|
||||||
|
|
||||||
|
public SrcVideoSurface(Context context, String path, float vol, boolean isLive) {
|
||||||
|
super(context);
|
||||||
|
this.path = path;
|
||||||
|
this.vol = vol;
|
||||||
|
this.isLive = isLive;
|
||||||
|
initIjk();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
|
void initExo() {
|
||||||
|
exoPlayer = new ExoPlayer.Builder(getContext()).build();
|
||||||
|
exoPlayer.setMediaItem(MediaItem.fromUri(path));
|
||||||
|
exoPlayer.setRepeatMode(ExoPlayer.REPEAT_MODE_ONE);
|
||||||
|
exoPlayer.setSeekParameters(SeekParameters.CLOSEST_SYNC);
|
||||||
|
exoPlayer.setVolume(vol);
|
||||||
|
exoPlayer.setVideoSurfaceView(this);
|
||||||
|
exoPlayer.prepare();
|
||||||
|
}
|
||||||
|
void initIjk() {
|
||||||
|
ijkPlayer = new IjkMediaPlayer();
|
||||||
|
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-avc", 1);
|
||||||
|
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
|
||||||
|
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", 1);
|
||||||
|
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
|
||||||
|
try {
|
||||||
|
getHolder().addCallback(this);
|
||||||
|
ijkPlayer.setDataSource(path);
|
||||||
|
ijkPlayer.setLooping(true);
|
||||||
|
ijkPlayer.setVolume(vol, vol);
|
||||||
|
ijkPlayer.setOnPreparedListener((IMediaPlayer var1)->{
|
||||||
|
ijkPlayer.setOnPreparedListener(null);
|
||||||
|
bitRate = ijkPlayer.getBitRate();
|
||||||
|
if(bitRate > 12000000) {
|
||||||
|
getHolder().removeCallback(this);
|
||||||
|
release();
|
||||||
|
initExo();
|
||||||
|
}
|
||||||
|
if(isShown()) start();
|
||||||
|
});
|
||||||
|
ijkPlayer.setOnErrorListener((IMediaPlayer var1, int var2, int var3)->{
|
||||||
|
Util.println(" Video Error: "+var1+" "+var2+" "+var3);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
ijkPlayer.prepareAsync();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Util.makeText(getContext(), Util.toStr(e)).show();
|
||||||
|
Util.printStackTrace(e);
|
||||||
|
ijkPlayer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
||||||
|
Util.println(" surfaceCreated "+(ijkPlayer==null?"ijkPlayer==null":""));
|
||||||
|
if(ijkPlayer!=null) ijkPlayer.setDisplay(holder);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {}
|
||||||
|
@Override
|
||||||
|
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
if(ijkPlayer!=null) {
|
||||||
|
ijkPlayer.seekTo(0);
|
||||||
|
ijkPlayer.start();
|
||||||
|
} else if(exoPlayer!=null) {
|
||||||
|
if(exoPlayer.getPlaybackState()==ExoPlayer.STATE_IDLE) exoPlayer.prepare();
|
||||||
|
exoPlayer.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void pause() {
|
||||||
|
if(ijkPlayer!=null) {
|
||||||
|
ijkPlayer.pause();
|
||||||
|
ijkPlayer.seekTo(0);
|
||||||
|
}
|
||||||
|
if(exoPlayer!=null && exoPlayer.isPlaying()) {
|
||||||
|
exoPlayer.pause();
|
||||||
|
exoPlayer.seekToDefaultPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void release() {
|
||||||
|
if(ijkPlayer!=null) {
|
||||||
|
ijkPlayer.release();
|
||||||
|
ijkPlayer = null;
|
||||||
|
}
|
||||||
|
if(exoPlayer!=null) {
|
||||||
|
exoPlayer.release();
|
||||||
|
exoPlayer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getState() {
|
||||||
|
if(exoPlayer!=null) {
|
||||||
|
var state = exoPlayer.getPlaybackState();
|
||||||
|
if(state==ExoPlayer.STATE_IDLE) return "STATE_IDLE";
|
||||||
|
if(state==ExoPlayer.STATE_BUFFERING) return "STATE_BUFFERING";
|
||||||
|
if(state==ExoPlayer.STATE_READY) return "STATE_READY";
|
||||||
|
if(state==ExoPlayer.STATE_ENDED) return "STATE_ENDED";
|
||||||
|
}
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onVisibilityAggregated(boolean isVisible) {
|
||||||
|
super.onVisibilityAggregated(isVisible);
|
||||||
|
if(isVisible) {
|
||||||
|
start();
|
||||||
|
if(isLive) ijkPlayer.setVolume(vol, vol);
|
||||||
|
} else if(isLive) ijkPlayer.setVolume(0, 0);
|
||||||
|
else pause();
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.Vector;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
import gnph.util.IOs;
|
import gnph.util.IOs;
|
||||||
|
@ -24,6 +25,7 @@ public class Util {
|
||||||
public static int screenWidth, screenHeight;
|
public static int screenWidth, screenHeight;
|
||||||
public static boolean isScreenOn;
|
public static boolean isScreenOn;
|
||||||
|
|
||||||
|
public static final Vector<SocketThread> socketThreads = new Vector<>();
|
||||||
public static final HashMap<Integer, String[]> stateDescs = new HashMap<>();
|
public static final HashMap<Integer, String[]> stateDescs = new HashMap<>();
|
||||||
static {
|
static {
|
||||||
stateDescs.put(1, new String[]{"Initialize", "初始化"});
|
stateDescs.put(1, new String[]{"Initialize", "初始化"});
|
||||||
|
@ -43,6 +45,7 @@ public class Util {
|
||||||
|
|
||||||
public static void println(String msg) {
|
public static void println(String msg) {
|
||||||
System.out.println(msg);
|
System.out.println(msg);
|
||||||
|
if(buf.length()>1000000) buf.replace(0, 100000, "");
|
||||||
buf.append(msg).append("\n");
|
buf.append(msg).append("\n");
|
||||||
}
|
}
|
||||||
public static void printStackTrace(Throwable e) {
|
public static void printStackTrace(Throwable e) {
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
<style name="Theme.XixunPlayer" parent="android:Theme.Black.NoTitleBar">
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
Loading…
Reference in New Issue
Block a user