From a7a23e0b779be42faadb072f3d439e7840e259ee Mon Sep 17 00:00:00 2001 From: Gangphon Date: Thu, 22 Aug 2024 17:37:46 +0800 Subject: [PATCH] player --- XixunPlayer/app/build.gradle | 2 +- XixunPlayer/app/src/main/AndroidManifest.xml | 1 + .../com/xixun/xixunplayer/MainActivity.java | 288 +++++++++++------- .../com/xixun/xixunplayer/RestartService.java | 13 +- .../java/com/xixun/xixunplayer/Server.java | 6 +- .../com/xixun/xixunplayer/SocketThread.java | 81 +++-- .../java/com/xixun/xixunplayer/SrcScroll.java | 20 +- .../java/com/xixun/xixunplayer/SrcVideo.java | 16 +- .../java/com/xixun/xixunplayer/SrcWeb.java | 55 ++++ 9 files changed, 322 insertions(+), 160 deletions(-) create mode 100644 XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcWeb.java 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); + } + } +}