diff --git a/XixunPlayer/app/build.gradle b/XixunPlayer/app/build.gradle
index b24bed3..617e6f5 100644
--- a/XixunPlayer/app/build.gradle
+++ b/XixunPlayer/app/build.gradle
@@ -11,7 +11,7 @@ android {
minSdk 21
targetSdk 34
versionCode 1
- versionName "2.1.9"
+ versionName "2.1.15"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/XixunPlayer/app/src/main/AndroidManifest.xml b/XixunPlayer/app/src/main/AndroidManifest.xml
index f9075c3..b10fe5c 100644
--- a/XixunPlayer/app/src/main/AndroidManifest.xml
+++ b/XixunPlayer/app/src/main/AndroidManifest.xml
@@ -11,6 +11,7 @@
reces = new ArrayList<>();
public Intent environIntent = new Intent();
HashSet environs = new HashSet<>();
BackView backView;
@@ -56,10 +58,13 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
@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));
+ Util.println("==>> MainActivity onCreate >>>> this "+hashCode()+" UI Thread: "+Thread.currentThread().getId());
+ try{
+ if(RestartService.ins==null) startService(new Intent(this, RestartService.class));
+ } catch(Throwable e) {
+ Util.printStackTrace(e);
+ }
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
@@ -76,6 +81,58 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
}
}
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ Util.println("==<< MainActivity onDestroy <<<< this "+hashCode());
+ state = 8;
+ if(insView!=null) {
+ insView.release();
+ insView = null;
+ }
+ if(progView!=null) {
+ progView.release();
+ progView = null;
+ }
+ ins = null;
+ for(var rece : reces) {
+ try {
+ unregisterReceiver(rece);
+ } catch (Throwable ignored){
+ }
+ }
+ System.gc();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ Util.println(" ==>> MainActivity onStart >> "+hashCode());
+ }
+ @Override
+ protected void onStop() {
+ super.onStop();
+ Util.println(" ==<< MainActivity onStop << "+hashCode());
+ }
+ @Override
+ protected void onRestart() {
+ super.onRestart();
+ Util.println(" ==>> MainActivity onRestart >> "+hashCode());
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ Util.println(" ==>> MainActivity onResume >> "+hashCode());
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ Util.println(" ==<< MainActivity onPause << "+hashCode());
+ }
+
+
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
@@ -152,7 +209,9 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
intent.setPackage("com.xixun.xy.conn");
bindService(intent, connConn, Context.BIND_AUTO_CREATE);
- registerReceiver(new BroadcastReceiver(){
+ reces.clear();
+ BroadcastReceiver rece;
+ registerReceiver(rece = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
Util.println("Receive PAUSE_PLAYER");
@@ -169,11 +228,13 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
progView = null;
}
setContentView(backView);
- } else if(progView==null && insView==null) initProg();
+ } else if(progView==null && insView==null) MainActivity.ins.runOnUiThread(() -> initProg());
+ System.gc();
}
}, new IntentFilter("com.xixun.action.PAUSE_PLAYER"));
+ reces.add(rece);
- registerReceiver(new BroadcastReceiver(){
+ registerReceiver(rece = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
Util.println("Receive CHANGE_COMPANYID");
@@ -193,8 +254,9 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
}
}
}, new IntentFilter("com.xixun.joey.CHANGE_COMPANYID"));
+ reces.add(rece);
- registerReceiver(new BroadcastReceiver(){
+ registerReceiver(rece = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
MainActivity.this.environIntent = intent;
@@ -204,34 +266,36 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
}
}
}, new IntentFilter("xixun.intent.action.TEMPERATURE_HUMIDITY"));
+ reces.add(rece);
- registerReceiver(new BroadcastReceiver(){
+ registerReceiver(rece = 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 || ! progView.isShown() || code > progView.pages.size()) return;
- if(! progView.avas.isEmpty()) {
- progView.curAva().hide();
- if(progView.avas.size()==1 && progView.avas.get(0)==code-1) for(var call : progView.calls) call.doFrame(System.currentTimeMillis());
+ var page = progView.pages.get(code-1);
+ var ms = System.currentTimeMillis();
+ if(! avas.isEmpty()) {
+ avas.get(curAva).hide();
+ if(avas.size()==1 && avas.get(0)==page) for(var call : progView.calls) call.doFrame(ms);
}
- var millis = (System.currentTimeMillis()+999)/1000*1000;
+ ms = (ms+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 = progView.curAva();
- page.setMillis(millis);
+ avas.clear();
+ avas.add(page);
+ curAva = 0;
+ curTimes = 1;
+ waitTo = 0; //点播
+ page.setMillis(ms);
if(state != 6) {
setContentView(progView);
state = 6;
}
} else {
- progView.waitTo = Long.MAX_VALUE;
- syncProg(millis);
+ waitTo = Long.MAX_VALUE;
+ syncProg(ms);
}
} catch (Throwable e) {
Util.makeText(MainActivity.this, Util.toStr(e)).show();
@@ -239,10 +303,11 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
}
}
}, new IntentFilter("com.xixun.yzd.REMOTE_CONTROL"));
+ reces.add(rece);
var intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
intentFilter.addDataScheme("file");
- registerReceiver(new BroadcastReceiver(){
+ registerReceiver(rece = new BroadcastReceiver(){
long lastMs;
final char[] pass = {'8','8','8'};
@Override
@@ -296,6 +361,7 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
}).start();
}
}, intentFilter);
+ reces.add(rece);
new Thread(this).start();
}
@@ -310,6 +376,7 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
progView = null;
}
setContentView(backView);
+ System.gc();
}
public boolean delProgFile() {
stopProg();
@@ -407,6 +474,7 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
fOut.getFD().sync();
fOut.close();
state = 5;
+ System.gc();
Util.println("Init Sync");
syncProg((System.currentTimeMillis()+999)/1000*1000);
if(canAdd) {
@@ -421,6 +489,11 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
}
}
+ ArrayList avas = new ArrayList<>();
+ int curAva, curTimes = 1;
+ long waitTo = Long.MAX_VALUE;
+ boolean isInsert;
+
Choreographer choreographer = Choreographer.getInstance();
boolean canAdd = true;
@@ -430,72 +503,64 @@ public class MainActivity extends Activity implements Choreographer.FrameCallbac
canAdd = true;
return;
}
+ choreographer.postFrameCallback(this);
+ canAdd = false;
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(milli >= progView.waitTo) {
- progView.waitTo = Long.MAX_VALUE;
+ if(avas.isEmpty()) {
+ if(milli >= waitTo) {
+ waitTo = Long.MAX_VALUE;
Util.println("wait sync");
syncProg(milli);
+ if(insView!=null) for(var call : insView.calls) call.doFrame(milli);
+ if(progView!=null) for(var call : progView.calls) call.doFrame(milli);
}
- } else {
- var lastPage = progView.curAva();
- if(milli >= lastPage.endMilli) {
- lastPage.hide();
- if(progView.waitTo > 0) { //waitTo==0 为点播,不换页
- if(progView.curTimes < lastPage.repeatTimes) progView.curTimes++;
+ return;
+ }
+ var lastPage = avas.get(curAva);
+ if(milli < lastPage.endMilli) lastPage.showHideSrcs(milli);
+ else {
+ lastPage.hide();
+ if(isInsert) {
+ if(--lastPage.repeatTimes<=0 && ++curAva >= avas.size()) {
+ var isDiff = milli-lastPage.endMilli>=1000;
+ syncProg(isDiff ? milli : lastPage.endMilli);
+ if(insView!=null) for(var call : insView.calls) call.doFrame(milli);
+ if(progView!=null) for(var call : progView.calls) call.doFrame(milli);
+ return;
+ }
+ } else {
+ if(waitTo > 0) { //waitTo==0 为点播,不换页
+ if(curTimes < lastPage.repeatTimes) curTimes++;
else {
- progView.curTimes = 1;
- if(++progView.curAva >= progView.avas.size()) {
+ curTimes = 1;
+ if(++curAva >= 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.isShown() || progView.avas.isEmpty()) Util.println("after. No Avas");
- else Util.println("after. curAva: "+progView.curAva+" endMs: "+progView.curAva().endMilli);
- choreographer.postFrameCallback(this);
- canAdd = false;
- for(var call : progView.calls) call.doFrame(milli);
+ if(insView!=null) for(var call : insView.calls) call.doFrame(milli);
+ if(progView!=null) for(var call : progView.calls) call.doFrame(milli);
return;
}
}
}
- progView.curAva().setMillis(lastPage.endMilli);
- Util.println("curAva: "+progView.curAva+" endMs: "+progView.curAva().endMilli);
- } else lastPage.showHideSrcs(milli);
+ }
+ avas.get(curAva).setMillis(lastPage.endMilli);
+ Util.println("curAva: "+curAva+" endMs: "+avas.get(curAva).endMilli);
}
- choreographer.postFrameCallback(this);
- canAdd = false;
- for(var call : progView.calls) call.doFrame(milli);
+ if(isInsert) for(var call : insView.calls) call.doFrame(milli);
+ else for(var call : progView.calls) call.doFrame(milli);
}
void syncProg(long milli) {
+ Util.println("\nSyncProg");
+ avas.clear();
+ curAva = 0;
+ curTimes = 1;
+ isInsert = false;
if(insView!=null) {
- insView.avas.clear();
for(int i=0; i Util.makeText(MainActivity.this, Util.toStr(e)).show());
+ if(MainActivity.ins!=null) MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.ins, Util.toStr(e)).show());
Util.printStackTrace(e);
}
}
} catch (Throwable e) {
- MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.this, Util.toStr(e)).show());
+ var msg = e.getMessage();
+ if(msg==null || ! msg.contains("EADDRINUSE")) MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.ins, Util.toStr(e)).show());
Util.printStackTrace(e);
}
}
diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/RestartService.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/RestartService.java
index 33b5f21..57ec86a 100644
--- a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/RestartService.java
+++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/RestartService.java
@@ -6,16 +6,27 @@ import android.os.IBinder;
public class RestartService extends Service {
+ static RestartService ins;
+
@Override
public void onCreate() {
super.onCreate();
- Util.println("---- RestartService onCreate");
+ ins = this;
+ Util.println("==>> RestartService onCreate >>>> "+hashCode());
if(MainActivity.ins!=null) return;
var intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Util.println("==<< RestartService onDestroy <<<< this "+hashCode());
+ ins = null;
+ System.gc();
+ }
+
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/Server.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/Server.java
index f6766d3..4f8e9e1 100644
--- a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/Server.java
+++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/Server.java
@@ -35,10 +35,8 @@ public class Server extends Service {
public String getProgramName() throws RemoteException {
try {
String name = null;
- if(MainActivity.ins!=null) {
- if(MainActivity.ins.insView!=null && ! MainActivity.ins.insView.avas.isEmpty()) name = MainActivity.ins.insView.curAva().name;
- else if(MainActivity.ins.progView!=null && ! MainActivity.ins.progView.avas.isEmpty()) name = MainActivity.ins.progView.curAva().name;
- }
+ var ins = MainActivity.ins;
+ if(ins!=null && ! ins.avas.isEmpty()) name = ins.avas.get(ins.curAva).name;
Util.println("Server getProgramName. <-"+name);
return name;
} catch (Exception e) {
diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SocketThread.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SocketThread.java
index a698b20..692d66a 100644
--- a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SocketThread.java
+++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SocketThread.java
@@ -100,7 +100,7 @@ public class SocketThread extends Thread {
fout.flush();
fout.getFD().sync();
fout.close();
- main.runOnUiThread(() -> {
+ if(main!=null) main.runOnUiThread(() -> {
main.backView.cosImg = BitmapFactory.decodeFile(Util.backImgFile, Util.noScaled);
main.backView.invalidate();
});
@@ -110,7 +110,14 @@ public class SocketThread extends Thread {
if(progJson!=null) {
var json = progJson.toByteArray();
progJson = null;
- main.runOnUiThread(() -> main.initProg(json));
+ if(main!=null) main.runOnUiThread(() -> main.initProg(json));
+ else {
+ var fOut = new FileOutputStream(Util.programDir + "/program");
+ fOut.write(json);
+ fOut.flush();
+ fOut.getFD().sync();
+ fOut.close();
+ }
}
} else if("playZipTask".equals(_type)) {
var zip = new ZipFile(Util.programDir+"/"+obj.stnn("proName"));
@@ -126,11 +133,11 @@ public class SocketThread extends Thread {
if(jsonOut==null) {
Util.println("No 'program' File");
new JSMap("success", false, "msg", "No 'program' File").write(out);
- main.runOnUiThread(() -> Util.makeText(main, "No program File").show());
+ if(main!=null) main.runOnUiThread(() -> Util.makeText(main, "No program File").show());
} else if(size==0) {
Util.println("Zip Size is 0");
new JSMap("success", false, "msg", "Zip Size is 0").write(out);
- main.runOnUiThread(() -> Util.makeText(main, "zip size is 0").show());
+ if(main!=null) main.runOnUiThread(() -> Util.makeText(main, "zip size is 0").show());
} else {
Util.deleteFiles(size, null);
for(var header : headers) if(! "program".equals(header.getFileName())) {
@@ -142,19 +149,19 @@ public class SocketThread extends Thread {
fOut.close();
}
var json = jsonOut.toByteArray();
- main.runOnUiThread(()->main.initProg(json));
+ if(main!=null) main.runOnUiThread(()->main.initProg(json));
Util.println(" Succeed");
new JSMap("success", true).write(out);
}
} catch (Exception e) {
Util.printStackTrace(e);
new JSMap("success", false).write(out);
- main.runOnUiThread(() -> Util.makeText(main, Util.toStr(e)).show());
+ if(main!=null) main.runOnUiThread(() -> Util.makeText(main, Util.toStr(e)).show());
}
} else if("DelPrograms".equals(_type)) {
var latch = new CountDownLatch(1);
var ok = new AtomicBoolean(false);
- main.runOnUiThread(() -> {
+ if(main!=null) main.runOnUiThread(() -> {
ok.set(main.delProgFile());
latch.countDown();
});
@@ -169,9 +176,10 @@ public class SocketThread extends Thread {
});
new JSMap("success", new File(Util.backImgFile).delete()).write(out);
} else if("getPlayerState".equals(_type)) {
- var descs = Util.getState(main.state);
+ var state = main==null ? 8 : main.state;
+ var descs = Util.getState(state);
new JSMap(
- "code", main.state,
+ "code", state,
"des_en", descs[0],
"des", descs[1]
).write(out);
@@ -179,22 +187,28 @@ public class SocketThread extends Thread {
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)).append("ms");
- if(main.progView!=null) writer.append(" Size Avas: ").append(String.valueOf(main.progView.avas.size())).append(" Pages: ").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");
+ if(main==null) writer.append("\nAPP is Closed\n");
+ else {
+ 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)).append("ms");
+ writer.append(" Size Avas: ").append(String.valueOf(main.avas.size())).append(" Pages: ").append(main.progView==null ? "null" : 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.insView==null) writer.append(" InseView is Null\n");
+ if(main.progView==null) writer.append(" ProgView is Null\n");
+ if(main.avas.isEmpty()) writer.append(" No Avas\n");
+ else writer.append("Page End: ").append(fmt.format(main.avas.get(main.curAva).endMilli)).append(" CurPage: ").append(String.valueOf(main.curAva)).append(" ").append(String.valueOf(main.avas.get(main.curAva).name)).append("\n");
+ }
writer.append(" Current: ").append(fmt.format(System.currentTimeMillis())).append(" ").append(String.valueOf(TimeZone.getDefault().getRawOffset()/3600000f)).append(" ").append(TimeZone.getDefault().getDisplayName()).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");
+ if(main!=null) {
+ var actManager = (ActivityManager) main.getSystemService(MainActivity.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");
@@ -204,9 +218,9 @@ public class SocketThread extends Thread {
writer.append("\n");
var latch = new CountDownLatch(1);
- main.runOnUiThread(() -> {
- if(main.progView!=null && ! main.progView.avas.isEmpty()) {
- var page = main.progView.curAva();
+ if(main!=null) main.runOnUiThread(() -> {
+ if(! main.avas.isEmpty()) {
+ var page = main.avas.get(main.curAva);
for(var layer : page.layers) for(var src : layer.srcs) if(src.view.getVisibility()==VISIBLE) {
try {
if(src.view instanceof SrcVideo) {
@@ -240,7 +254,7 @@ public class SocketThread extends Thread {
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("OriginUrl: ").append(view.getOriginalUrl()).append("\n");
writer.append("Progress: ").append(String.valueOf(view.getProgress())).append("\n");
}
} catch (Exception ignored) {
@@ -275,13 +289,24 @@ public class SocketThread extends Thread {
}
}
} else if("GetJsonWithFileInfo".equals(_type)) {
+ var inse = new File(Util.programDir+"/insert");
+ var files = new File(Util.programDir).listFiles();
+ if(inse.isFile()) {
+ var json = IOs.readStrClose(new FileInputStream(inse));
+ if(files!=null) for(var file : files) if(! "program".equals(file.getName())) json = json.replace("\""+file.getName()+"\"", "\""+file.getName()+"\"/*"+file.length()+" "+fmt.format(new Date(file.lastModified()))+"*/");
+ var writer = new OutputStreamWriter(out);
+ writer.append("insert:\n");
+ writer.append(json);
+ if(! json.endsWith("\n")) writer.append("\n");
+ writer.flush();
+ }
var prog = new File(Util.programDir+"/program");
if(! prog.isFile()) new JSMap("msg", "'program' file not exist").write(out);
else {
var json = IOs.readStrClose(new FileInputStream(prog));
- var files = new File(Util.programDir).listFiles();
if(files!=null) for(var file : files) if(! "program".equals(file.getName())) json = json.replace("\""+file.getName()+"\"", "\""+file.getName()+"\"/*"+file.length()+" "+fmt.format(new Date(file.lastModified()))+"*/");
var writer = new OutputStreamWriter(out);
+ writer.append("\nprogram:\n");
writer.append(json);
writer.flush();
}
@@ -295,7 +320,7 @@ public class SocketThread extends Thread {
Util.println(emsg);
return;
}
- main.runOnUiThread(() -> Util.makeText(main, Util.toStr(e)).show());
+ if(main!=null) main.runOnUiThread(() -> Util.makeText(main, Util.toStr(e)).show());
Util.printStackTrace(e);
} finally {
Util.socketThreads.remove(this);
diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcScroll.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcScroll.java
index dce12f1..d7a1260 100644
--- a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcScroll.java
+++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcScroll.java
@@ -25,15 +25,19 @@ public class SrcScroll extends View implements Choreographer.FrameCallback {
public SrcScroll(Prog prog, JSMap json, Bitmap img) {
super(prog.getContext());
if(img==null) img = BitmapFactory.decodeFile(Util.programDir+"/"+json.stnn("id"));
- var imgsWidth = img.getWidth();
- if(imgsWidth <= 8192) imgs.add(img);
- else {
+ if(img.getWidth() > 8192) {
var rem = img.getWidth();
do {
imgs.add(Bitmap.createBitmap(img, img.getWidth()-rem, 0, Math.min(8192, rem), img.getHeight()));
rem -= 8192;
} while (rem>0);
- }
+ } else if(img.getHeight() > 8192) {
+ var rem = img.getHeight();
+ do {
+ imgs.add(Bitmap.createBitmap(img, 0, img.getHeight()-rem, img.getWidth(), Math.min(8192, rem)));
+ rem -= 8192;
+ } while (rem>0);
+ } else imgs.add(img);
var effStr = json.str("effect");
if(effStr==null || effStr.equals("no")) return;
var scrollSpeed = json.dbl("scrollSpeed");
@@ -48,10 +52,10 @@ public class SrcScroll extends View implements Choreographer.FrameCallback {
int idx = effStr.lastIndexOf(' ');
if(idx > -1) {
effect = effStr.charAt(idx+1);
- if(effect=='l') end = -(imgsWidth-step);
- else if(effect=='r') end = imgsWidth-step;
- else if(effect=='t') end = -(imgs.get(0).getHeight()-step);
- else if(effect=='b') end = imgs.get(0).getHeight()-step;
+ if(effect=='l') end = -(img.getWidth()-step);
+ else if(effect=='r') end = img.getWidth()-step;
+ else if(effect=='t') end = -(img.getHeight()-step);
+ else if(effect=='b') end = img.getHeight()-step;
else effect = 0;
}
if(effect!=0) prog.calls.add(this);
diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcVideo.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcVideo.java
index d1c0cd8..32bff96 100644
--- a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcVideo.java
+++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcVideo.java
@@ -21,17 +21,19 @@ public class SrcVideo extends TextureView implements TextureView.SurfaceTextureL
String path;
float vol;
+ int dur;
IjkMediaPlayer ijkPlayer;
ExoPlayer exoPlayer;
long bitRate;
boolean isLive;
- public SrcVideo(Context context, String path, float vol, boolean isLive) {
+ public SrcVideo(Context context, String path, float vol, int dur, boolean useHW, boolean isLive) {
super(context);
this.path = path;
this.vol = vol;
+ this.dur = dur;
this.isLive = isLive;
- initIjk();
+ initIjk(useHW);
}
@OptIn(markerClass = UnstableApi.class)
@@ -44,9 +46,12 @@ public class SrcVideo extends TextureView implements TextureView.SurfaceTextureL
exoPlayer.setVideoTextureView(this);
exoPlayer.prepare();
}
- void initIjk() {
+ void initIjk(boolean useHW) {
ijkPlayer = new IjkMediaPlayer();
- //ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-avc", 1);
+ if(useHW) {
+ ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-avc", 1);
+ ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-hevc", 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);
@@ -62,6 +67,9 @@ public class SrcVideo extends TextureView implements TextureView.SurfaceTextureL
setSurfaceTextureListener(null);
release();
initExo();
+ } else {
+ var diff = dur - ijkPlayer.getDuration();
+ if(diff>0 && diff<=1000) ijkPlayer.setLooping(false);
}
if(isShown()) start();
});
diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcWeb.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcWeb.java
new file mode 100644
index 0000000..71c8203
--- /dev/null
+++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcWeb.java
@@ -0,0 +1,55 @@
+package com.xixun.xixunplayer;
+
+import android.annotation.SuppressLint;
+import android.graphics.Color;
+import android.view.Choreographer;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import gnph.util.JSMap;
+import gnph.util.URLConn;
+
+@SuppressLint("ViewConstructor")
+public class SrcWeb extends WebView implements Choreographer.FrameCallback {
+
+ String url;
+ int refresh;
+
+ @SuppressLint("SetJavaScriptEnabled")
+ public SrcWeb(Prog prog, JSMap json) {
+ super(prog.getContext());
+ var settings = getSettings();
+ settings.setJavaScriptEnabled(true);
+ settings.setDomStorageEnabled(true);
+ settings.setLoadsImagesAutomatically(true);
+ setVerticalScrollBarEnabled(false);
+ setHorizontalScrollBarEnabled(false);
+ setBackgroundColor(Color.TRANSPARENT);
+ setInitialScale(json.intg("zoom", 100));
+ setWebViewClient(new WebViewClient() {
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ return false;
+ }
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ view.loadUrl("javascript:window.scrollTo("+json.str("offX", "0")+", "+json.str("offY", "0")+")");
+ }
+ });
+ loadUrl(url = json.str("url"));
+ refresh = json.intg("refreshSec")*1000;
+ if(refresh>0 && url!=null) prog.calls.add(this);
+ nextMs = System.currentTimeMillis() + refresh;
+ }
+
+ long nextMs;
+
+ @Override
+ public void doFrame(long ms) {
+ if(! isShown()) return;
+ if(ms>=nextMs) {
+ nextMs = ms + refresh;
+ loadUrl(url);
+ }
+ }
+}