722 lines
36 KiB
Java
722 lines
36 KiB
Java
package com.xixun.xixunplayer;
|
|
|
|
import static android.view.View.VISIBLE;
|
|
|
|
import android.annotation.SuppressLint;
|
|
import android.app.ActivityManager;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.ComponentName;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.content.ServiceConnection;
|
|
import android.content.pm.PackageManager;
|
|
import android.graphics.BitmapFactory;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.Environment;
|
|
import android.os.IBinder;
|
|
import android.os.StatFs;
|
|
import android.os.StrictMode;
|
|
import android.view.Choreographer;
|
|
import android.view.View;
|
|
import android.webkit.WebView;
|
|
|
|
import androidx.activity.ComponentActivity;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.OptIn;
|
|
import androidx.annotation.RequiresApi;
|
|
import androidx.core.app.ActivityCompat;
|
|
import androidx.core.content.ContextCompat;
|
|
import androidx.media3.common.util.UnstableApi;
|
|
|
|
import com.xixun.joey.aidlset.CardService;
|
|
import com.xixun.xy.conn.aidl.ConnService;
|
|
|
|
import net.lingala.zip4j.ZipFile;
|
|
|
|
import java.io.BufferedInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
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.text.SimpleDateFormat;
|
|
import java.util.Arrays;
|
|
import java.util.HashSet;
|
|
import java.util.concurrent.CountDownLatch;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
import gnph.util.Chsets;
|
|
import gnph.util.IOs;
|
|
import gnph.util.JSList;
|
|
import gnph.util.JSMap;
|
|
import gnph.util.NumFmts;
|
|
import gnph.util.O;
|
|
|
|
public class MainActivity extends ComponentActivity implements Choreographer.FrameCallback, Runnable {
|
|
|
|
public static MainActivity ins;
|
|
public Intent environIntent = new Intent();
|
|
HashSet<IntentReceiver> environs = new HashSet<>();
|
|
BackView backView;
|
|
Prog progView;
|
|
long launchMilli = System.currentTimeMillis();
|
|
long syncMs;
|
|
int state;
|
|
|
|
@RequiresApi(api = Build.VERSION_CODES.R)
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
var msg = "==== MainActivity onCreate ==== UI Thread: "+Thread.currentThread().getId();
|
|
Util.println(msg);
|
|
ins = this;
|
|
startService(new Intent(this, RestartService.class));
|
|
|
|
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
|
|
|
|
if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) init();
|
|
else {
|
|
Util.println("---- No permission, Try again ...");
|
|
ActivityCompat.requestPermissions(this, new String[]{
|
|
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
|
android.Manifest.permission.READ_EXTERNAL_STORAGE,
|
|
android.Manifest.permission.MANAGE_EXTERNAL_STORAGE,
|
|
android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
|
|
android.Manifest.permission.INTERNET
|
|
}, 999);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
if(requestCode==999 && grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED && backView==null) init();
|
|
}
|
|
|
|
int receCnt;
|
|
ConnService connService;
|
|
|
|
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
|
public void init() {
|
|
var dir = Build.VERSION.SDK_INT < Build.VERSION_CODES.R ? Environment.getExternalStorageDirectory().getAbsolutePath() + "/XixunPlayer" : getExternalFilesDir(null).getAbsolutePath();
|
|
var msg = "---- dir "+dir;
|
|
Util.println(msg);
|
|
Util.programDir = dir + "/program";
|
|
Util.backImgFile = dir + "/background";
|
|
|
|
var program = new File(Util.programDir);
|
|
if(program.isFile()) program.delete();
|
|
msg = "---- mkdir: "+program.mkdirs();
|
|
Util.println(msg);
|
|
|
|
var cardConn = new ServiceConnection() {
|
|
public void onServiceDisconnected(ComponentName name) {
|
|
Util.println("Disconnected cardsystem aidl service");
|
|
}
|
|
|
|
public void onServiceConnected(ComponentName name, IBinder iBinder) {
|
|
unbindService(this);
|
|
Util.println("Bind cardsystem aidl service success");
|
|
var service = CardService.Stub.asInterface(iBinder);
|
|
try {
|
|
Util.isScreenOn = service.isScreenOpen();
|
|
Util.screenWidth = service.getScreenWidth();
|
|
Util.screenHeight = service.getScreenHeight();
|
|
Util.println(" IsScreenOn: "+Util.isScreenOn+" screen: "+Util.screenWidth+" x "+Util.screenHeight);
|
|
if(receCnt++>=1) {
|
|
backView = new BackView(MainActivity.this, Util.screenWidth, Util.screenHeight);
|
|
state = 5;
|
|
if(Util.isScreenOn) initProg();
|
|
else state = 8;
|
|
if(progView==null) setContentView(backView);
|
|
}
|
|
} catch (Exception e) {
|
|
Util.makeText(MainActivity.this, Util.toStr(e)).show();
|
|
Util.printStackTrace(e);
|
|
}
|
|
}
|
|
};
|
|
var intent = new Intent("com.xixun.joey.aidlset.SettingsService");
|
|
intent.setPackage("com.xixun.joey.cardsystem");
|
|
bindService(intent, cardConn, Context.BIND_AUTO_CREATE);
|
|
|
|
var connConn = new ServiceConnection() {
|
|
public void onServiceDisconnected(ComponentName name) {
|
|
Util.println("Disconnected xy.conn aidl service");
|
|
connService = null;
|
|
}
|
|
public void onServiceConnected(ComponentName name, IBinder iBinder) {
|
|
unbindService(this);
|
|
Util.println("Bind xy.conn aidl service success");
|
|
connService = ConnService.Stub.asInterface(iBinder);
|
|
try {
|
|
Util.serverURL = connService.getServerURL();
|
|
Util.println(" ServerURL: "+Util.serverURL);
|
|
if(Util.serverURL==null || Util.serverURL.isEmpty()) Util.serverURL = "https://m2mled.net/";
|
|
else {
|
|
if(! Util.serverURL.startsWith("http")) Util.serverURL = "http://"+Util.serverURL;
|
|
if(! Util.serverURL.endsWith("/")) Util.serverURL += "/";
|
|
}
|
|
if(receCnt++>=1) {
|
|
backView = new BackView(MainActivity.this, Util.screenWidth, Util.screenHeight);
|
|
state = 5;
|
|
if(Util.isScreenOn) initProg();
|
|
else state = 8;
|
|
if(progView==null) setContentView(backView);
|
|
}
|
|
} catch (Exception e) {
|
|
Util.makeText(MainActivity.this, Util.toStr(e)).show();
|
|
Util.printStackTrace(e);
|
|
}
|
|
}
|
|
};
|
|
intent = new Intent("xixun.intent.action.CONNECTION_INFO");
|
|
intent.setPackage("com.xixun.xy.conn");
|
|
bindService(intent, connConn, Context.BIND_AUTO_CREATE);
|
|
|
|
registerReceiver(new BroadcastReceiver(){
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
Util.println("Receive PAUSE_PLAYER");
|
|
Util.isScreenOn = ! intent.getBooleanExtra("pause", false);
|
|
Util.println(" IsScreenOn: "+Util.isScreenOn);
|
|
if(! Util.isScreenOn) {
|
|
state = 8;
|
|
if(progView!=null) {
|
|
progView.release();
|
|
progView = null;
|
|
setContentView(backView);
|
|
}
|
|
} else if(progView==null) initProg();
|
|
}
|
|
}, new IntentFilter("com.xixun.action.PAUSE_PLAYER"));
|
|
|
|
registerReceiver(new BroadcastReceiver(){
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
Util.println("Receive CHANGE_COMPANYID");
|
|
if(connService!=null) {
|
|
try {
|
|
Util.serverURL = connService.getServerURL();
|
|
Util.println(" ServerURL: "+Util.serverURL);
|
|
if(Util.serverURL==null || Util.serverURL.isEmpty()) Util.serverURL = "https://m2mled.net/";
|
|
else {
|
|
if(! Util.serverURL.startsWith("http")) Util.serverURL = "http://"+Util.serverURL;
|
|
if(! Util.serverURL.endsWith("/")) Util.serverURL += "/";
|
|
}
|
|
} catch (Exception e) {
|
|
Util.makeText(MainActivity.this, Util.toStr(e)).show();
|
|
Util.printStackTrace(e);
|
|
}
|
|
}
|
|
}
|
|
}, new IntentFilter("com.xixun.joey.CHANGE_COMPANYID"));
|
|
|
|
registerReceiver(new BroadcastReceiver(){
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
MainActivity.this.environIntent = intent;
|
|
for(var environ : environs) {
|
|
environ.onReceive(intent);
|
|
((View)environ).invalidate();
|
|
}
|
|
}
|
|
}, new IntentFilter("xixun.intent.action.TEMPERATURE_HUMIDITY"));
|
|
|
|
registerReceiver(new BroadcastReceiver(){
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
try {
|
|
var code = intent.getIntExtra("code", 0);
|
|
Util.println(" remote_control "+code);
|
|
if(progView == null || code > progView.pages.size()) return;
|
|
if(! progView.avas.isEmpty()) page(progView.curAva).hide();
|
|
var millis = (System.currentTimeMillis()+999)/1000*1000;
|
|
if(code > 0) {
|
|
progView.avas.clear();
|
|
progView.avas.add(code-1);
|
|
progView.curAva = 0;
|
|
progView.curTimes = 1;
|
|
progView.waitTo = 0; //点播
|
|
var page = page(0);
|
|
page.setMillis(millis);
|
|
if(state != 6) {
|
|
setContentView(progView);
|
|
state = 6;
|
|
}
|
|
} else {
|
|
progView.waitTo = Long.MAX_VALUE;
|
|
syncProg(millis);
|
|
}
|
|
} catch (Throwable e) {
|
|
Util.makeText(MainActivity.this, Util.toStr(e)).show();
|
|
Util.printStackTrace(e);
|
|
}
|
|
}
|
|
}, new IntentFilter("com.xixun.yzd.REMOTE_CONTROL"));
|
|
|
|
var intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
|
|
intentFilter.addDataScheme("file");
|
|
registerReceiver(new BroadcastReceiver(){
|
|
long lastMs;
|
|
final char[] pass = {'8','8','8'};
|
|
@Override
|
|
public void onReceive(Context context, Intent intent) {
|
|
var path = intent.getData().getPath();
|
|
Util.println("\nMEDIA_MOUNTED path: "+path);
|
|
var ms = System.currentTimeMillis();
|
|
if(ms-lastMs<1000) return;
|
|
lastMs = ms;
|
|
Util.makeText(MainActivity.this, "MEDIA_MOUNTED path: "+path).show();
|
|
new Thread(()->{
|
|
try {
|
|
var zip = new ZipFile(path+"/program.zip");
|
|
if(zip.isEncrypted()) zip.setPassword(pass);
|
|
long size = 0;
|
|
ByteArrayOutputStream progJson = null;
|
|
var headers = zip.getFileHeaders();
|
|
for(var header : headers) {
|
|
size += header.getUncompressedSize();
|
|
if("program".equals(header.getFileName())) {
|
|
progJson = new ByteArrayOutputStream();
|
|
IOs.writeClose(progJson, zip.getInputStream(header));
|
|
}
|
|
}
|
|
if(progJson==null) {
|
|
Util.println("No program File");
|
|
runOnUiThread(() -> Util.makeText(MainActivity.this, "No program File").show());
|
|
return;
|
|
}
|
|
if(size==0) {
|
|
Util.println("zip size is 0");
|
|
runOnUiThread(() -> Util.makeText(MainActivity.this, "zip size is 0").show());
|
|
return;
|
|
}
|
|
Util.deleteFiles(size, null);
|
|
for(var header : headers) if(! "program".equals(header.getFileName())) zip.extractFile(header, Util.programDir);
|
|
var json = progJson.toByteArray();
|
|
runOnUiThread(() -> {
|
|
Util.println("Import Succeed");
|
|
Util.makeText(MainActivity.this, "Import Succeed").show();
|
|
initProg(json);
|
|
});
|
|
} catch (Exception e) {
|
|
Util.printStackTrace(e);
|
|
runOnUiThread(() -> Util.makeText(MainActivity.this, Util.toStr(e)).show());
|
|
}
|
|
}).start();
|
|
}
|
|
}, intentFilter);
|
|
|
|
new Thread(this).start();
|
|
}
|
|
|
|
public void stopProg() {
|
|
if(progView==null) return;
|
|
progView.release();
|
|
progView = null;
|
|
setContentView(backView);
|
|
}
|
|
public boolean delProgFile() {
|
|
stopProg();
|
|
var files = new File(Util.programDir).listFiles();
|
|
var ok = true;
|
|
if(files != null) for(var file : files) if(! file.delete()) ok = false;
|
|
state = 4;
|
|
try {
|
|
var out = new FileOutputStream(Util.programDir+"/program");
|
|
out.write("{}".getBytes());
|
|
out.flush();
|
|
out.getFD().sync();
|
|
out.close();
|
|
} catch (Throwable ignored) {
|
|
}
|
|
return ok;
|
|
}
|
|
public void initProg() {
|
|
try {
|
|
var task = JSMap.fromClose(new BufferedInputStream(new FileInputStream(Util.programDir + "/program"))).jsmap("task");
|
|
if(task==null) {
|
|
state = 3;
|
|
return;
|
|
}
|
|
var view = new Prog(task, this);
|
|
if(view.getChildCount()==0) {
|
|
state = 3;
|
|
return;
|
|
}
|
|
if(progView!=null) progView.release();
|
|
progView = view;
|
|
setContentView(progView);
|
|
state = 5;
|
|
Util.println("Init Sync");
|
|
syncProg((System.currentTimeMillis()+999)/1000*1000);
|
|
if(canAdd) {
|
|
choreographer.postFrameCallback(this);
|
|
canAdd = false;
|
|
}
|
|
} catch (FileNotFoundException e) {
|
|
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) {
|
|
try {
|
|
Util.println("\nParse Prog Json");
|
|
var root = JSMap.from(json);
|
|
var task = root.jsmap("task");
|
|
if(task==null) {
|
|
if(! root.containsKey("layers")) {
|
|
state = 7;
|
|
Util.println(" Error: task==null\n");
|
|
Util.println(new String(json, Chsets.UTF8));
|
|
return;
|
|
}
|
|
task = new JSMap("items", new JSList<>(new JSMap("repeatTimes", 1, "_program", root)));
|
|
}
|
|
var view = new Prog(task, this);
|
|
if(view.getChildCount()==0) {
|
|
state = 7;
|
|
Util.println(" Error: ChildCount==0\n");
|
|
Util.println(new String(json, Chsets.UTF8));
|
|
return;
|
|
}
|
|
if(progView!=null) progView.release();
|
|
progView = view;
|
|
setContentView(progView);
|
|
var fOut = new FileOutputStream(Util.programDir + "/program");
|
|
fOut.write(json);
|
|
fOut.flush();
|
|
fOut.getFD().sync();
|
|
fOut.close();
|
|
state = 5;
|
|
Util.println("Init Sync");
|
|
syncProg((System.currentTimeMillis()+999)/1000*1000);
|
|
if(canAdd) {
|
|
choreographer.postFrameCallback(this);
|
|
canAdd = false;
|
|
}
|
|
} catch (Throwable e) {
|
|
state = 7;
|
|
Util.makeText(this, Util.toStr(e)).show();
|
|
Util.printStackTrace(e);
|
|
Util.println(new String(json, Chsets.UTF8));
|
|
}
|
|
}
|
|
|
|
Choreographer choreographer = Choreographer.getInstance();
|
|
boolean canAdd = true;
|
|
|
|
@Override
|
|
public void doFrame(long frameTimeNanos) {
|
|
if(progView == null) {
|
|
canAdd = true;
|
|
return;
|
|
}
|
|
var milli = System.currentTimeMillis();
|
|
if(progView.avas.isEmpty()) {
|
|
if(milli >= progView.waitTo) {
|
|
progView.waitTo = Long.MAX_VALUE;
|
|
Util.println("wait sync");
|
|
syncProg(milli);
|
|
}
|
|
} else {
|
|
var lastPage = page(progView.curAva);
|
|
if(milli >= lastPage.endMilli) {
|
|
lastPage.hide();
|
|
if(progView.waitTo > 0) { //waitTo==0 为点播,不换页
|
|
if(progView.curTimes < lastPage.repeatTimes) progView.curTimes++;
|
|
else {
|
|
progView.curTimes = 1;
|
|
progView.curAva++;
|
|
if(progView.curAva >= progView.avas.size()) {
|
|
var isDiff = milli-lastPage.endMilli>=1000;
|
|
if(Util.buf.length()>1000000) Util.buf.replace(0, 100000, "");
|
|
Util.println("isDiff: "+isDiff+" endMs: "+lastPage.endMilli+" millis:"+milli);
|
|
syncProg(isDiff ? milli : lastPage.endMilli);
|
|
if(progView.avas.isEmpty()) Util.println("after. No Avas");
|
|
else Util.println("after. curAva: "+progView.curAva+" endMs: "+page(progView.curAva).endMilli);
|
|
choreographer.postFrameCallback(this);
|
|
canAdd = false;
|
|
for(var call : progView.calls) call.doFrame(milli);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
page(progView.curAva).setMillis(lastPage.endMilli);
|
|
Util.println("curAva: "+progView.curAva+" endMs: "+page(progView.curAva).endMilli);
|
|
} else {
|
|
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);
|
|
canAdd = false;
|
|
for(var call : progView.calls) call.doFrame(milli);
|
|
}
|
|
|
|
void syncProg(long milli) {
|
|
progView.curTimes = 1;
|
|
progView.avas.clear();
|
|
var dur = 0;
|
|
for(int i=0; i<progView.pages.size(); i++) if(progView.pages.get(i).isScheOn(milli+dur)) {
|
|
progView.avas.add(i);
|
|
dur += progView.pages.get(i).tDur;
|
|
}
|
|
if(dur==0) {
|
|
for(int i=0; i<progView.pages.size(); i++) if(progView.pages.get(i).sches==null) {
|
|
progView.avas.add(i);
|
|
dur += progView.pages.get(i).tDur;
|
|
}
|
|
if(dur==0) {
|
|
progView.waitTo = milli + 1000;
|
|
if(state!=2) {
|
|
setContentView(backView);
|
|
state = 2;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
var start = milli / dur * dur;
|
|
progView.curAva = 0;
|
|
if(start < milli) {
|
|
do {
|
|
start += page(progView.curAva++).tDur;
|
|
} while(progView.curAva < progView.avas.size() && start<=milli);
|
|
start -= page(--progView.curAva).tDur;
|
|
syncMs = milli;
|
|
Util.println("Sync. dur: "+dur+" milli: "+milli+" start: "+start+" diff: "+(milli - start));
|
|
}
|
|
page(progView.curAva).setMillis(start);
|
|
if(state != 6) {
|
|
setContentView(progView);
|
|
state = 6;
|
|
}
|
|
}
|
|
|
|
Prog.Page page(int i) {
|
|
return progView.pages.get(progView.avas.get(i));
|
|
}
|
|
|
|
@OptIn(markerClass = UnstableApi.class) public void run() {
|
|
try {
|
|
var serverSocket = new ServerSocket(3333);
|
|
while(true) {
|
|
InputStream in = null;
|
|
OutputStream out = null;
|
|
try {
|
|
Util.println("\nAccepting ...");
|
|
final var socket = serverSocket.accept();
|
|
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");
|
|
writer.append("Page End: ").append(progView==null || progView.avas.isEmpty() ? "0" : Fmt.format(page(progView.curAva).endMilli)).append(" CurPage: ").append(String.valueOf(progView.curAva)).append(" / ").append(progView==null || progView.avas.isEmpty() ? "0" : 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) {
|
|
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());
|
|
Util.printStackTrace(e);
|
|
} finally {
|
|
O.close(in, out);
|
|
Util.println("conn end\n");
|
|
}
|
|
}
|
|
} catch (Throwable e) {
|
|
MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.this, Util.toStr(e)).show());
|
|
Util.printStackTrace(e);
|
|
}
|
|
}
|
|
} |