2023-11-09 08:37:59 +08:00
package com.xixun.xixunplayer ;
import static android.view.View.VISIBLE ;
2024-01-24 20:17:59 +08:00
import android.annotation.SuppressLint ;
2023-12-01 16:17:06 +08:00
import android.app.ActivityManager ;
2023-11-09 08:37:59 +08:00
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.RemoteException ;
import android.os.StatFs ;
2024-02-02 18:09:54 +08:00
import android.os.StrictMode ;
2023-11-09 08:37:59 +08:00
import android.view.Choreographer ;
2024-01-26 18:31:10 +08:00
import android.view.View ;
2023-12-01 16:17:06 +08:00
import android.webkit.WebView ;
2023-11-09 08:37:59 +08:00
import androidx.activity.ComponentActivity ;
2023-11-10 09:47:38 +08:00
import androidx.annotation.NonNull ;
2023-12-01 16:17:06 +08:00
import androidx.annotation.OptIn ;
2023-11-09 08:37:59 +08:00
import androidx.annotation.RequiresApi ;
import androidx.core.app.ActivityCompat ;
import androidx.core.content.ContextCompat ;
2023-12-11 15:17:48 +08:00
import androidx.media3.common.util.UnstableApi ;
2023-11-09 08:37:59 +08:00
import com.xixun.joey.aidlset.CardService ;
2024-01-24 20:17:59 +08:00
import net.lingala.zip4j.ZipFile ;
2023-11-09 08:37:59 +08:00
import java.io.BufferedInputStream ;
2024-01-26 21:35:38 +08:00
import java.io.ByteArrayOutputStream ;
2023-11-09 08:37:59 +08:00
import java.io.File ;
import java.io.FileInputStream ;
import java.io.FileNotFoundException ;
import java.io.FileOutputStream ;
2024-01-24 20:17:59 +08:00
import java.io.FileReader ;
2023-11-09 08:37:59 +08:00
import java.io.InputStream ;
import java.io.OutputStream ;
2023-12-01 16:17:06 +08:00
import java.io.OutputStreamWriter ;
2023-11-09 08:37:59 +08:00
import java.net.ServerSocket ;
2024-01-24 20:17:59 +08:00
import java.text.SimpleDateFormat ;
2023-11-09 08:37:59 +08:00
import java.util.Arrays ;
import java.util.HashSet ;
import java.util.concurrent.CountDownLatch ;
import java.util.concurrent.atomic.AtomicBoolean ;
2024-01-26 21:35:38 +08:00
import gnph.util.Chsets ;
2023-11-09 08:37:59 +08:00
import gnph.util.IOs ;
import gnph.util.JSList ;
import gnph.util.JSMap ;
2023-12-01 16:17:06 +08:00
import gnph.util.NumFmts ;
2023-11-09 08:37:59 +08:00
import gnph.util.O ;
2023-12-01 16:17:06 +08:00
public class MainActivity extends ComponentActivity implements Choreographer . FrameCallback , Runnable {
2023-11-09 08:37:59 +08:00
public static MainActivity ins ;
public Intent environIntent = new Intent ( ) ;
2024-01-26 18:31:10 +08:00
HashSet < IntentReceiver > environs = new HashSet < > ( ) ;
2023-11-09 08:37:59 +08:00
BackView backView ;
2023-12-01 16:17:06 +08:00
Prog progView ;
long launchMilli = System . currentTimeMillis ( ) ;
long syncMs ;
2023-11-09 08:37:59 +08:00
int state ;
@RequiresApi ( api = Build . VERSION_CODES . R )
@Override
public void onCreate ( Bundle savedInstanceState ) {
super . onCreate ( savedInstanceState ) ;
2024-01-24 20:17:59 +08:00
var msg = " ==== MainActivity onCreate ==== UI Thread: " + Thread . currentThread ( ) . getId ( ) ;
Util . println ( msg ) ;
ins = this ;
2023-11-10 21:45:00 +08:00
startService ( new Intent ( this , RestartService . class ) ) ;
2024-02-02 18:09:54 +08:00
StrictMode . setThreadPolicy ( new StrictMode . ThreadPolicy . Builder ( ) . permitAll ( ) . build ( ) ) ;
2023-11-09 08:37:59 +08:00
if ( ContextCompat . checkSelfPermission ( this , android . Manifest . permission . WRITE_EXTERNAL_STORAGE ) = = PackageManager . PERMISSION_GRANTED ) init ( ) ;
else {
2024-01-24 20:17:59 +08:00
Util . println ( " ---- No permission, Try again ... " ) ;
2023-11-09 08:37:59 +08:00
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 ) ;
}
}
2024-01-24 20:17:59 +08:00
2023-11-09 08:37:59 +08:00
@Override
2023-11-10 09:47:38 +08:00
public void onRequestPermissionsResult ( int requestCode , @NonNull String [ ] permissions , @NonNull int [ ] grantResults ) {
2023-11-09 08:37:59 +08:00
super . onRequestPermissionsResult ( requestCode , permissions , grantResults ) ;
2023-11-10 09:47:38 +08:00
if ( requestCode = = 999 & & grantResults . length > 0 & & grantResults [ 0 ] = = PackageManager . PERMISSION_GRANTED & & backView = = null ) init ( ) ;
2023-11-09 08:37:59 +08:00
}
2024-01-24 20:17:59 +08:00
@SuppressLint ( " UnspecifiedRegisterReceiverFlag " )
2023-11-09 08:37:59 +08:00
public void init ( ) {
2024-01-24 20:17:59 +08:00
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 " ;
2023-11-09 08:37:59 +08:00
var program = new File ( Util . programDir ) ;
if ( program . isFile ( ) ) program . delete ( ) ;
2024-01-24 20:17:59 +08:00
msg = " ---- mkdir: " + program . mkdirs ( ) ;
Util . println ( msg ) ;
2023-11-09 08:37:59 +08:00
var conn = new ServiceConnection ( ) {
public void onServiceDisconnected ( ComponentName name ) {
2024-01-24 20:17:59 +08:00
Util . println ( " Disconnected cardsystem aidl service " ) ;
2023-11-09 08:37:59 +08:00
}
public void onServiceConnected ( ComponentName name , IBinder iBinder ) {
2024-01-24 20:17:59 +08:00
Util . println ( " Bind cardsystem aidl service success " ) ;
2023-11-09 08:37:59 +08:00
var service = CardService . Stub . asInterface ( iBinder ) ;
try {
2023-11-10 09:47:38 +08:00
Util . isScreenOn = service . isScreenOpen ( ) ;
2024-01-24 20:17:59 +08:00
Util . println ( " isScreenOn: " + Util . isScreenOn ) ;
2023-11-09 08:37:59 +08:00
backView = new BackView ( MainActivity . this , service . getScreenWidth ( ) , service . getScreenHeight ( ) ) ;
state = 5 ;
2023-11-10 09:47:38 +08:00
if ( Util . isScreenOn ) initProg ( ) ;
else state = 8 ;
2023-11-09 08:37:59 +08:00
if ( progView = = null ) setContentView ( backView ) ;
} catch ( RemoteException e ) {
2024-01-24 20:17:59 +08:00
Util . makeText ( MainActivity . this , Util . toStr ( e ) ) . show ( ) ;
Util . printStackTrace ( e ) ;
2023-12-01 16:17:06 +08:00
} finally {
unbindService ( this ) ;
2023-11-09 08:37:59 +08:00
}
}
} ;
var intent = new Intent ( " com.xixun.joey.aidlset.SettingsService " ) ;
intent . setPackage ( " com.xixun.joey.cardsystem " ) ;
bindService ( intent , conn , Context . BIND_AUTO_CREATE ) ;
2024-01-24 20:17:59 +08:00
var intentFilter = new IntentFilter ( Intent . ACTION_MEDIA_MOUNTED ) ;
intentFilter . addDataScheme ( " file " ) ;
registerReceiver ( new BroadcastReceiver ( ) {
long lastMs ;
2024-02-02 18:09:54 +08:00
final char [ ] pass = { '8' , '8' , '8' } ;
2024-01-24 20:17:59 +08:00
@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 ;
2024-01-26 21:35:38 +08:00
ByteArrayOutputStream progJson = null ;
2024-01-24 20:17:59 +08:00
var headers = zip . getFileHeaders ( ) ;
2024-01-26 21:35:38 +08:00
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 " ) ;
2024-02-02 18:09:54 +08:00
runOnUiThread ( ( ) - > Util . makeText ( MainActivity . this , " No program File " ) . show ( ) ) ;
2024-01-26 21:35:38 +08:00
return ;
}
2024-01-24 20:17:59 +08:00
if ( size = = 0 ) {
Util . println ( " zip size is 0 " ) ;
2024-02-02 18:09:54 +08:00
runOnUiThread ( ( ) - > Util . makeText ( MainActivity . this , " zip size is 0 " ) . show ( ) ) ;
2024-01-24 20:17:59 +08:00
return ;
}
Util . deleteFiles ( size , null ) ;
2024-01-26 21:35:38 +08:00
for ( var header : headers ) if ( ! " program " . equals ( header . getFileName ( ) ) ) zip . extractFile ( header , Util . programDir ) ;
var json = progJson . toByteArray ( ) ;
2024-01-24 20:17:59 +08:00
runOnUiThread ( ( ) - > {
Util . println ( " Import Succeed " ) ;
Util . makeText ( MainActivity . this , " Import Succeed " ) . show ( ) ;
2024-01-26 21:35:38 +08:00
initProg ( json ) ;
2024-01-24 20:17:59 +08:00
} ) ;
} catch ( Exception e ) {
Util . printStackTrace ( e ) ;
2024-02-02 18:09:54 +08:00
runOnUiThread ( ( ) - > Util . makeText ( MainActivity . this , Util . toStr ( e ) ) . show ( ) ) ;
2024-01-24 20:17:59 +08:00
}
} ) . start ( ) ;
}
} , intentFilter ) ;
2023-11-09 08:37:59 +08:00
registerReceiver ( new BroadcastReceiver ( ) {
@Override
public void onReceive ( Context context , Intent intent ) {
2024-01-24 20:17:59 +08:00
Util . println ( " Receive PAUSE_PLAYER " ) ;
2023-11-10 09:47:38 +08:00
Util . isScreenOn = ! intent . getBooleanExtra ( " pause " , false ) ;
2024-01-24 20:17:59 +08:00
Util . println ( " isScreenOn: " + Util . isScreenOn ) ;
2023-11-10 09:47:38 +08:00
if ( ! Util . isScreenOn ) {
2023-11-09 08:37:59 +08:00
state = 8 ;
if ( progView ! = null ) {
2023-12-01 16:17:06 +08:00
progView . release ( ) ;
2023-11-09 08:37:59 +08:00
progView = null ;
setContentView ( backView ) ;
}
} else if ( progView = = null ) initProg ( ) ;
}
2024-01-24 20:17:59 +08:00
} , new IntentFilter ( " com.xixun.action.PAUSE_PLAYER " ) ) ;
2023-11-09 08:37:59 +08:00
// registerReceiver(new BroadcastReceiver(){
// @Override
// public void onReceive(Context context, Intent intent) {
// }
// }, new IntentFilter("com.xixun.joey.CHANGE_COMPANYID"), RECEIVER_EXPORTED);
registerReceiver ( new BroadcastReceiver ( ) {
@Override
public void onReceive ( Context context , Intent intent ) {
MainActivity . this . environIntent = intent ;
for ( var environ : environs ) {
environ . onReceive ( intent ) ;
2024-01-26 18:31:10 +08:00
( ( View ) environ ) . invalidate ( ) ;
2023-11-09 08:37:59 +08:00
}
}
2024-01-24 20:17:59 +08:00
} , new IntentFilter ( " xixun.intent.action.TEMPERATURE_HUMIDITY " ) ) ;
2023-11-09 08:37:59 +08:00
2023-12-01 16:17:06 +08:00
registerReceiver ( new BroadcastReceiver ( ) {
@Override
public void onReceive ( Context context , Intent intent ) {
try {
var code = intent . getIntExtra ( " code " , 0 ) ;
2024-01-24 20:17:59 +08:00
Util . println ( " remote_control " + code ) ;
2023-12-01 16:17:06 +08:00
if ( progView = = null | | code > progView . pages . size ( ) ) return ;
2024-02-02 18:09:54 +08:00
if ( ! progView . avas . isEmpty ( ) ) page ( progView . curAva ) . hide ( ) ;
2023-12-01 16:17:06 +08:00
var millis = ( System . currentTimeMillis ( ) + 999 ) / 1000 * 1000 ;
if ( code > 0 ) {
progView . avas . clear ( ) ;
progView . avas . add ( code - 1 ) ;
2024-02-02 18:09:54 +08:00
progView . curAva = 0 ;
progView . curTimes = 1 ;
progView . waitTo = 0 ; //点播
2023-12-01 16:17:06 +08:00
var page = page ( 0 ) ;
page . setMillis ( millis ) ;
if ( state ! = 6 ) {
setContentView ( progView ) ;
state = 6 ;
2023-11-09 08:37:59 +08:00
}
2023-12-01 16:17:06 +08:00
} else {
2024-02-02 18:09:54 +08:00
progView . waitTo = Long . MAX_VALUE ;
2023-12-01 16:17:06 +08:00
syncProg ( millis ) ;
2023-11-09 08:37:59 +08:00
}
2023-12-01 16:17:06 +08:00
} catch ( Throwable e ) {
2024-01-24 20:17:59 +08:00
Util . makeText ( MainActivity . this , Util . toStr ( e ) ) . show ( ) ;
Util . printStackTrace ( e ) ;
2023-11-09 08:37:59 +08:00
}
}
2024-01-24 20:17:59 +08:00
} , new IntentFilter ( " com.xixun.yzd.REMOTE_CONTROL " ) ) ;
2023-12-01 16:17:06 +08:00
new Thread ( this ) . start ( ) ;
2023-11-09 08:37:59 +08:00
}
2023-12-11 15:17:48 +08:00
public void stopProg ( ) {
if ( progView = = null ) return ;
progView . release ( ) ;
progView = null ;
setContentView ( backView ) ;
}
2023-11-09 08:37:59 +08:00
public boolean delProgFile ( ) {
2023-12-11 15:17:48 +08:00
stopProg ( ) ;
2023-11-09 08:37:59 +08:00
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 ;
}
2023-12-01 16:17:06 +08:00
var view = new Prog ( task , this ) ;
2023-11-09 08:37:59 +08:00
if ( view . getChildCount ( ) = = 0 ) {
state = 3 ;
return ;
}
2023-12-01 16:17:06 +08:00
if ( progView ! = null ) progView . release ( ) ;
2023-11-09 08:37:59 +08:00
progView = view ;
setContentView ( progView ) ;
2024-01-24 20:17:59 +08:00
state = 5 ;
Util . println ( " Init Sync " ) ;
2023-11-09 08:37:59 +08:00
syncProg ( ( System . currentTimeMillis ( ) + 999 ) / 1000 * 1000 ) ;
2024-01-24 20:17:59 +08:00
if ( canAdd ) {
choreographer . postFrameCallback ( this ) ;
canAdd = false ;
}
2023-11-09 08:37:59 +08:00
} catch ( FileNotFoundException e ) {
state = 3 ;
2024-01-24 20:17:59 +08:00
Util . printStackTrace ( e ) ;
2023-11-09 08:37:59 +08:00
} catch ( Throwable e ) {
state = 7 ;
2024-01-24 20:17:59 +08:00
Util . makeText ( this , Util . toStr ( e ) ) . show ( ) ;
Util . printStackTrace ( e ) ;
2023-11-09 08:37:59 +08:00
}
}
2024-01-26 21:35:38 +08:00
public void initProg ( byte [ ] json ) {
try {
Util . println ( " \ nParse Prog Json " ) ;
var task = JSMap . from ( json ) . jsmap ( " task " ) ;
if ( task = = null ) {
state = 7 ;
Util . println ( " Error: task==null \ n " ) ;
Util . println ( new String ( json , Chsets . UTF8 ) ) ;
return ;
}
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 ) ) ;
}
}
2023-11-09 08:37:59 +08:00
Choreographer choreographer = Choreographer . getInstance ( ) ;
2024-01-24 20:17:59 +08:00
boolean canAdd = true ;
2023-11-09 08:37:59 +08:00
@Override
public void doFrame ( long frameTimeNanos ) {
2024-01-24 20:17:59 +08:00
if ( progView = = null ) {
canAdd = true ;
return ;
}
2023-11-09 08:37:59 +08:00
var milli = System . currentTimeMillis ( ) ;
2023-12-01 16:17:06 +08:00
if ( progView . avas . isEmpty ( ) ) {
2024-02-02 18:09:54 +08:00
if ( milli > = progView . waitTo ) {
progView . waitTo = Long . MAX_VALUE ;
2024-01-24 20:17:59 +08:00
Util . println ( " wait sync " ) ;
2023-12-01 16:17:06 +08:00
syncProg ( milli ) ;
2023-11-09 08:37:59 +08:00
}
} else {
2024-02-02 18:09:54 +08:00
var lastPage = page ( progView . curAva ) ;
2023-12-01 16:17:06 +08:00
if ( milli > = lastPage . endMilli ) {
lastPage . hide ( ) ;
2024-02-02 18:09:54 +08:00
if ( progView . waitTo > 0 ) { //waitTo==0 为点播,不换页
if ( progView . curTimes < lastPage . repeatTimes ) progView . curTimes + + ;
2023-12-01 16:17:06 +08:00
else {
2024-02-02 18:09:54 +08:00
progView . curTimes = 1 ;
progView . curAva + + ;
if ( progView . curAva > = progView . avas . size ( ) ) {
2023-12-01 16:17:06 +08:00
var isDiff = milli - lastPage . endMilli > = 1000 ;
2024-01-24 20:17:59 +08:00
if ( Util . buf . length ( ) > 1000000 ) Util . buf . replace ( 0 , 100000 , " " ) ;
Util . println ( " isDiff: " + isDiff + " endMs: " + lastPage . endMilli + " millis: " + milli ) ;
2023-12-01 16:17:06 +08:00
syncProg ( isDiff ? milli : lastPage . endMilli ) ;
2024-02-02 18:09:54 +08:00
Util . println ( " after. curAva: " + progView . curAva + " endMs: " + page ( progView . curAva ) . endMilli ) ;
2023-12-01 16:17:06 +08:00
choreographer . postFrameCallback ( this ) ;
2024-01-24 20:17:59 +08:00
canAdd = false ;
2023-12-01 16:17:06 +08:00
return ;
}
}
2023-11-09 08:37:59 +08:00
}
2024-02-02 18:09:54 +08:00
page ( progView . curAva ) . setMillis ( lastPage . endMilli ) ;
Util . println ( " curAva: " + progView . curAva + " endMs: " + page ( progView . curAva ) . endMilli ) ;
2023-12-01 16:17:06 +08:00
} else {
for ( var layer : lastPage . layers ) {
2024-01-24 20:17:59 +08:00
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 ( ) ;
2023-12-01 16:17:06 +08:00
}
if ( milli > = layer . endMilli ) {
layer . endMilli + = layer . dur ;
2024-01-24 20:17:59 +08:00
for ( var src : layer . srcs ) {
src . endMilli + = layer . dur ;
src . startMilli + = layer . dur ;
if ( src . startTime > 0 ) src . hide ( ) ;
else src . show ( ) ;
2023-12-01 16:17:06 +08:00
}
2023-11-09 08:37:59 +08:00
}
}
}
}
choreographer . postFrameCallback ( this ) ;
2024-01-24 20:17:59 +08:00
canAdd = false ;
2023-11-09 08:37:59 +08:00
}
void syncProg ( long milli ) {
2024-02-02 18:09:54 +08:00
progView . curTimes = 1 ;
2023-12-01 16:17:06 +08:00
progView . avas . clear ( ) ;
2024-01-24 20:17:59 +08:00
var dur = 0 ;
2024-02-02 18:09:54 +08:00
for ( int i = 0 ; i < progView . pages . size ( ) ; i + + ) if ( progView . pages . get ( i ) . isScheOn ( milli + dur ) ) {
2023-12-01 16:17:06 +08:00
progView . avas . add ( i ) ;
2024-01-24 20:17:59 +08:00
dur + = progView . pages . get ( i ) . tDur ;
2023-12-01 16:17:06 +08:00
}
2023-11-09 08:37:59 +08:00
if ( dur = = 0 ) {
2024-02-02 18:09:54 +08:00
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 ;
2023-11-09 08:37:59 +08:00
}
2024-02-02 18:09:54 +08:00
if ( dur = = 0 ) {
progView . waitTo = milli + 1000 ;
if ( state ! = 2 ) {
setContentView ( backView ) ;
state = 2 ;
}
return ;
2023-11-09 08:37:59 +08:00
}
}
2024-02-02 18:09:54 +08:00
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 ;
}
2023-11-09 08:37:59 +08:00
}
2023-12-01 16:17:06 +08:00
Prog . Page page ( int i ) {
return progView . pages . get ( progView . avas . get ( i ) ) ;
2023-11-09 08:37:59 +08:00
}
2023-12-11 15:17:48 +08:00
@OptIn ( markerClass = UnstableApi . class ) public void run ( ) {
2023-12-01 16:17:06 +08:00
try {
var serverSocket = new ServerSocket ( 3333 ) ;
while ( true ) {
InputStream in = null ;
OutputStream out = null ;
try {
2024-02-02 18:09:54 +08:00
Util . println ( " \ nAccepting ... " ) ;
2023-12-01 16:17:06 +08:00
final var socket = serverSocket . accept ( ) ;
2024-02-02 18:09:54 +08:00
Util . println ( " \ nAccepted " ) ;
2023-12-01 16:17:06 +08:00
in = socket . getInputStream ( ) ;
out = socket . getOutputStream ( ) ;
2024-01-24 20:17:59 +08:00
HashSet < String > hases = null ;
2024-01-26 21:35:38 +08:00
ByteArrayOutputStream progJson = null ;
2023-12-01 16:17:06 +08:00
while ( true ) {
var obj = JSMap . from ( in ) ;
var _type = obj . stnn ( " _type " ) ;
2024-01-24 20:17:59 +08:00
Util . println ( " _type: " + _type ) ;
2023-12-01 16:17:06 +08:00
if ( " consult " . equals ( _type ) ) {
JSList < String > ids = obj . jslist ( " idList " ) ;
2024-01-24 20:17:59 +08:00
hases = new HashSet < > ( ) ;
2023-12-01 16:17:06 +08:00
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 ) ) {
2023-12-11 15:17:48 +08:00
Util . deleteFiles ( obj . intg ( " proSize " ) , hases ) ;
2023-12-01 16:17:06 +08:00
} else if ( " fileStart " . equals ( _type ) ) {
var size = obj . intg ( " size " ) ;
var name = obj . stnn ( " id " ) ;
2024-01-24 20:17:59 +08:00
Util . println ( " size: " + size + " name: " + name ) ;
2024-01-26 21:35:38 +08:00
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 ( ) ;
}
2023-12-01 16:17:06 +08:00
} 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 ) ) {
2024-01-26 21:35:38 +08:00
new JSMap ( " success " , progJson ! = null ) . write ( out ) ;
if ( progJson ! = null ) {
var json = progJson . toByteArray ( ) ;
progJson = null ;
runOnUiThread ( ( ) - > initProg ( json ) ) ;
}
2023-12-01 16:17:06 +08:00
} 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 ) ;
2024-01-24 20:17:59 +08:00
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 ) ) ;
2023-12-01 16:17:06 +08:00
if ( progView ! = null ) writer . append ( " Pages: " ) . append ( String . valueOf ( progView . avas . size ( ) ) ) . append ( " / " ) . append ( String . valueOf ( progView . pages . size ( ) ) ) ;
writer . append ( " \ n " ) ;
2024-01-24 20:17:59 +08:00
writer . append ( " Launch: " ) . append ( Fmt . format ( launchMilli ) ) . append ( " \ n " ) ;
writer . append ( " Sync: " ) . append ( Fmt . format ( syncMs ) ) . append ( " \ n " ) ;
2024-02-02 18:09:54 +08:00
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 " ) ;
2024-01-24 20:17:59 +08:00
writer . append ( " Current: " ) . append ( Fmt . format ( System . currentTimeMillis ( ) ) ) . append ( " \ n " ) ;
2023-12-11 15:17:48 +08:00
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 " ) ;
2023-12-01 16:17:06 +08:00
var actManager = ( ActivityManager ) getSystemService ( ACTIVITY_SERVICE ) ;
var memoryInfo = new ActivityManager . MemoryInfo ( ) ;
actManager . getMemoryInfo ( memoryInfo ) ;
2023-12-11 15:17:48 +08:00
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 " ) ;
2023-12-01 16:17:06 +08:00
var runtime = Runtime . getRuntime ( ) ;
2023-12-11 15:17:48 +08:00
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 " ) ;
2024-01-24 20:17:59 +08:00
writer . append ( " /proc/stat \ n " ) ;
IOs . writeCloseIn ( writer , new FileReader ( " /proc/stat " ) ) ;
writer . append ( " \ n " ) ;
2023-12-01 16:17:06 +08:00
var latch = new CountDownLatch ( 1 ) ;
runOnUiThread ( ( ) - > {
2024-01-24 20:17:59 +08:00
if ( progView ! = null & & ! progView . avas . isEmpty ( ) ) {
2024-02-02 18:09:54 +08:00
var page = page ( progView . curAva ) ;
2024-01-24 20:17:59 +08:00
for ( var layer : page . layers ) for ( var src : layer . srcs ) if ( src . view . getVisibility ( ) = = VISIBLE ) {
2023-12-01 16:17:06 +08:00
try {
2024-02-02 19:34:33 +08:00
if ( src . view instanceof SrcVideo ) {
var view = ( SrcVideo ) src . view ;
2023-12-01 16:17:06 +08:00
if ( view . ijkPlayer ! = null ) {
2024-01-24 20:17:59 +08:00
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 " ) ;
2023-12-11 15:17:48 +08:00
var mediaInfo = view . ijkPlayer . getMediaInfo ( ) ;
2024-01-24 20:17:59 +08:00
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 " ) ;
2023-12-11 15:17:48 +08:00
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 ) {
2024-01-24 20:17:59 +08:00
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 " ) ;
2023-12-11 15:17:48 +08:00
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 " ) ;
2023-12-01 16:17:06 +08:00
}
2023-12-11 15:17:48 +08:00
writer . append ( " \ n " ) ;
2024-02-02 18:09:54 +08:00
} else if ( src . view instanceof SrcWeather ) {
var view = ( SrcWeather ) src . view ;
writer . append ( " SrcWeather html: " ) . append ( view . html ) . append ( " \ n " ) ;
2024-01-24 20:17:59 +08:00
} else if ( src . view instanceof WebView ) {
var view = ( WebView ) src . view ;
2023-12-01 16:17:06 +08:00
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 ) ) {
2024-01-24 20:17:59 +08:00
out . write ( Util . buf . toString ( ) . getBytes ( ) ) ;
2023-12-11 15:17:48 +08:00
} 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 ) ;
2024-02-02 18:09:54 +08:00
for ( var file : files ) writer . append ( file . getName ( ) ) . append ( ' ' ) . append ( String . valueOf ( file . length ( ) ) ) . append ( '\n' ) ;
2023-12-11 15:17:48 +08:00
writer . append ( '\n' ) ;
writer . flush ( ) ;
2023-12-01 16:17:06 +08:00
} 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 ) ;
}
2024-01-24 20:17:59 +08:00
out . flush ( ) ;
Util . println ( " cmd end " ) ;
2023-12-01 16:17:06 +08:00
}
} catch ( Throwable e ) {
var emsg = e . getMessage ( ) ;
2024-01-24 20:17:59 +08:00
if ( emsg ! = null & & ( " Socket closed " . equals ( emsg ) | | emsg . endsWith ( " end-of-input " ) ) ) {
Util . println ( emsg ) ;
continue ;
}
2024-02-02 18:09:54 +08:00
MainActivity . ins . runOnUiThread ( ( ) - > Util . makeText ( MainActivity . this , Util . toStr ( e ) ) . show ( ) ) ;
2024-01-24 20:17:59 +08:00
Util . printStackTrace ( e ) ;
2023-12-01 16:17:06 +08:00
} finally {
O . close ( in , out ) ;
2024-02-02 18:09:54 +08:00
Util . println ( " conn end \ n " ) ;
2023-12-01 16:17:06 +08:00
}
}
} catch ( Throwable e ) {
2024-02-02 18:09:54 +08:00
MainActivity . ins . runOnUiThread ( ( ) - > Util . makeText ( MainActivity . this , Util . toStr ( e ) ) . show ( ) ) ;
2024-01-24 20:17:59 +08:00
Util . printStackTrace ( e ) ;
2023-12-01 16:17:06 +08:00
}
2023-11-09 08:37:59 +08:00
}
}