player
This commit is contained in:
parent
c5e8aa2b22
commit
83fae2c155
|
@ -4,12 +4,12 @@ plugins {
|
|||
|
||||
android {
|
||||
namespace 'com.xixun.xixunplayer'
|
||||
compileSdk 33
|
||||
compileSdk 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.xixun.xixunplayer"
|
||||
minSdk 28
|
||||
targetSdk 33
|
||||
minSdk 26
|
||||
targetSdk 34
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
|
@ -35,7 +35,12 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation files('libs\\gnph.jar')
|
||||
// implementation 'androidx.media3:media3-exoplayer:1.2.0'
|
||||
// implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
|
||||
// implementation 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
|
||||
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25'
|
||||
implementation files('libs\\xixun_card_settings_1.2.4.jar')
|
||||
implementation files('libs/gnph.jar')
|
||||
implementation files('libs/xixun_card_settings_1.2.4.jar')
|
||||
implementation files('libs/ijkplayer-java-0.8.8.aar')
|
||||
implementation files('libs/ijkplayer-arm64-0.8.8.aar')
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"version": 3,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "com.xixun.xixunplayer",
|
||||
"variantName": "release",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 1,
|
||||
"versionName": "1.0",
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
],
|
||||
"elementType": "File"
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
|
@ -52,6 +53,7 @@
|
|||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<meta-data android:name="android.max_aspect" android:value="2.1" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -6,7 +6,6 @@ import android.graphics.BitmapFactory;
|
|||
import android.graphics.Canvas;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import gnph.util.JSMap;
|
||||
|
||||
public class EleScrollAny extends View implements DrawOther, Choreographer.FrameCallback {
|
||||
|
||||
ArrayList<EleOtherPart> others;
|
||||
Bitmap img;
|
||||
float cur, end, step;
|
||||
char effect;
|
||||
|
||||
public EleScrollAny(String dirPre, JSMap json, Context context) {
|
||||
super(context);
|
||||
img = BitmapFactory.decodeFile(dirPre + json.stnn("id"));
|
||||
var effStr = json.str("effect");
|
||||
if(effStr==null || effStr.equals("no")) return;
|
||||
var scrollSpeed = json.dbl("scrollSpeed");
|
||||
if(scrollSpeed==0) {
|
||||
var scrollDur = json.dbl("effectSpeed");
|
||||
if(scrollDur==0) return;
|
||||
scrollSpeed = 1000 / scrollDur;
|
||||
}
|
||||
step = (float) (scrollSpeed / 60);
|
||||
int idx = effStr.lastIndexOf(' ');
|
||||
if(idx > -1) {
|
||||
effect = effStr.charAt(idx+1);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if(img==null) return;
|
||||
try {
|
||||
drawOther(canvas);
|
||||
if(freshCnt==0 && effect!=0 && step!=0) choreographer.postFrameCallback(this);
|
||||
} catch (Throwable e) {
|
||||
setVisibility(GONE);
|
||||
img = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void drawOther(Canvas canvas) {
|
||||
if(img==null) return;
|
||||
if(effect=='l') {
|
||||
canvas.drawBitmap(img, cur, 0, null);
|
||||
canvas.drawBitmap(img, cur+img.getWidth(), 0, null);
|
||||
} else if(effect=='r') {
|
||||
var x = cur-img.getWidth()+getWidth();
|
||||
canvas.drawBitmap(img, x, 0, null);
|
||||
canvas.drawBitmap(img, x-img.getWidth(), 0, null);
|
||||
} else if(effect=='t') {
|
||||
canvas.drawBitmap(img, 0, cur, null);
|
||||
canvas.drawBitmap(img, 0, cur+img.getHeight(), null);
|
||||
} else if(effect=='b') {
|
||||
canvas.drawBitmap(img, 0, cur, null);
|
||||
canvas.drawBitmap(img, 0, cur-img.getHeight(), null);
|
||||
} else canvas.drawBitmap(img, 0, 0, null);
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
int freshCnt;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(! isShown()) {
|
||||
cur = freshCnt = 0;
|
||||
return;
|
||||
}
|
||||
freshCnt = 1;
|
||||
if(effect=='t' || effect=='l') {
|
||||
if(cur <= end) cur -= end;
|
||||
else cur -= step;
|
||||
} else if(effect=='b' || effect=='r') {
|
||||
if(cur >= end) cur -= end;
|
||||
else cur += step;
|
||||
}
|
||||
invalidate();
|
||||
if(others!=null) for(var other : others) other.invalidate();
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
|
@ -1,77 +1,103 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
import android.view.Choreographer;
|
||||
import android.widget.VideoView;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
public class EleVideo extends VideoView implements Choreographer.FrameCallback {
|
||||
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
|
||||
|
||||
float vol = 1;
|
||||
public class EleVideo extends SurfaceView {
|
||||
|
||||
public EleVideo(String path, Context context) {
|
||||
IjkMediaPlayer ijkPlayer;
|
||||
|
||||
public EleVideo(Context context, String path, float vol) {
|
||||
super(context);
|
||||
setVideoPath(path);
|
||||
setOnPreparedListener((MediaPlayer player)->{
|
||||
player.setLooping(true);
|
||||
if(! isShown()) {
|
||||
player.seekTo(0);
|
||||
player.pause();
|
||||
}
|
||||
if(vol!=1) player.setVolume(vol, vol);
|
||||
setOnPreparedListener(null);
|
||||
});
|
||||
setOnErrorListener((MediaPlayer mp, int what, int extra)->{
|
||||
Util.makeText(getContext(), "Media Error: "+getErrorName(what)+". "+getErrorName(extra)).show();
|
||||
return true;
|
||||
});
|
||||
start();
|
||||
choreographer.postFrameCallback(this);
|
||||
initIjk(path, vol);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
|
||||
// @OptIn(markerClass = UnstableApi.class)
|
||||
// void initExo(String path, float vol) {
|
||||
// exoPlayer = new ExoPlayer.Builder(getContext()).build();
|
||||
// exoPlayer.setMediaItem(MediaItem.fromUri(path));
|
||||
// exoPlayer.setRepeatMode(ExoPlayer.REPEAT_MODE_ONE);
|
||||
// exoPlayer.setSeekParameters(SeekParameters.CLOSEST_SYNC);
|
||||
// exoPlayer.setVolume(vol);
|
||||
// exoPlayer.setVideoSurfaceView(this);
|
||||
// }
|
||||
void initIjk(String path, float vol) {
|
||||
ijkPlayer = new IjkMediaPlayer();
|
||||
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
|
||||
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", 1);
|
||||
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
|
||||
try {
|
||||
getHolder().addCallback(new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
ijkPlayer.setDisplay(holder);
|
||||
}
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
System.out.println("surfaceChanged");
|
||||
}
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
System.out.println("surfaceDestroyed");
|
||||
}
|
||||
});
|
||||
ijkPlayer.setDataSource(path);
|
||||
ijkPlayer.setLooping(true);
|
||||
ijkPlayer.setVolume(vol, vol);
|
||||
ijkPlayer.prepareAsync();
|
||||
} catch (Throwable e) {
|
||||
Util.makeText(getContext(), e.getMessage()).show();
|
||||
e.printStackTrace();
|
||||
ijkPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
void start() {
|
||||
if(ijkPlayer!=null) ijkPlayer.start();
|
||||
// else if(exoPlayer!=null) {
|
||||
// if(exoPlayer.getPlaybackState()==ExoPlayer.STATE_IDLE) exoPlayer.prepare();
|
||||
// exoPlayer.play();
|
||||
// }
|
||||
}
|
||||
void pause() {
|
||||
if(ijkPlayer!=null) {
|
||||
ijkPlayer.pause();
|
||||
ijkPlayer.seekTo(0);
|
||||
}
|
||||
// if(exoPlayer!=null && exoPlayer.isPlaying()) {
|
||||
// exoPlayer.pause();
|
||||
// exoPlayer.seekToDefaultPosition();
|
||||
// }
|
||||
}
|
||||
void release() {
|
||||
if(ijkPlayer!=null) {
|
||||
ijkPlayer.release();
|
||||
ijkPlayer = null;
|
||||
}
|
||||
// if(exoPlayer!=null) {
|
||||
// exoPlayer.release();
|
||||
// exoPlayer = null;
|
||||
// }
|
||||
}
|
||||
|
||||
String getState() {
|
||||
// else if(exoPlayer!=null) {
|
||||
// var state = exoPlayer.getPlaybackState();
|
||||
// if(state==ExoPlayer.STATE_IDLE) return "STATE_IDLE";
|
||||
// if(state==ExoPlayer.STATE_BUFFERING) return "STATE_BUFFERING";
|
||||
// if(state==ExoPlayer.STATE_READY) return "STATE_READY";
|
||||
// if(state==ExoPlayer.STATE_ENDED) return "STATE_ENDED";
|
||||
// }
|
||||
return "null";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVisibilityAggregated(boolean isVisible) {
|
||||
super.onVisibilityAggregated(isVisible);
|
||||
if(isVisible) {
|
||||
if(! isPlaying()) start();
|
||||
} else {
|
||||
seekTo(0);
|
||||
pause();
|
||||
showCnt = 5;
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
int showCnt;
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(isShown()) {
|
||||
seekTo(0);
|
||||
if(showCnt>0) showCnt--;
|
||||
else return;
|
||||
} else if(isPlaying()) {
|
||||
seekTo(0);
|
||||
pause();
|
||||
System.out.println("pause in doFrame()");
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
|
||||
static String getErrorName(int code) {
|
||||
if(code==MediaPlayer.MEDIA_ERROR_UNKNOWN) return "UNKNOWN";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_SERVER_DIED) return "SERVER_DIED";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) return "NOT_VALID_FOR_PROGRESSIVE_PLAYBACK";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_IO) return "IO";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_MALFORMED) return "MALFORMED";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_UNSUPPORTED) return "UNSUPPORTED";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_TIMED_OUT) return "TIMED_OUT";
|
||||
if(code==-2147483648) return "SYSTEM";
|
||||
return "Unknown ("+code+")";
|
||||
if(isVisible) start();
|
||||
else pause();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
import android.view.Choreographer;
|
||||
import android.widget.VideoView;
|
||||
|
||||
public class EleVideo2 extends VideoView implements Choreographer.FrameCallback {
|
||||
|
||||
float vol = 1;
|
||||
|
||||
public EleVideo2(String path, Context context) {
|
||||
super(context);
|
||||
setVideoPath(path);
|
||||
setOnPreparedListener((MediaPlayer player)->{
|
||||
player.setLooping(true);
|
||||
if(! isShown()) {
|
||||
player.seekTo(0);
|
||||
player.pause();
|
||||
}
|
||||
if(vol!=1) player.setVolume(vol, vol);
|
||||
setOnPreparedListener(null);
|
||||
});
|
||||
setOnErrorListener((MediaPlayer mp, int what, int extra)->{
|
||||
var err = "Media Error: "+getErrorName(what)+". "+getErrorName(extra);
|
||||
Util.makeText(getContext(), err).show();
|
||||
MainActivity.ins.buf.append(err+'\n');
|
||||
return true;
|
||||
});
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVisibilityAggregated(boolean isVisible) {
|
||||
super.onVisibilityAggregated(isVisible);
|
||||
if(isVisible) {
|
||||
MainActivity.ins.buf.append("Video Show\n");
|
||||
if(! isPlaying()) {
|
||||
seekTo(0);
|
||||
start();
|
||||
seekTo(0);
|
||||
if(! isPlaying()) MainActivity.ins.buf.append("Video isn't Playing on Show\n");
|
||||
}
|
||||
} else {
|
||||
MainActivity.ins.buf.append("Video Hide\n");
|
||||
seekTo(0);
|
||||
pause();
|
||||
seekTo(0);
|
||||
showCnt = 3;
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
int showCnt;
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(isShown()) {
|
||||
seekTo(0);
|
||||
if(! isPlaying()) {
|
||||
start();
|
||||
seekTo(0);
|
||||
if(! isPlaying()) {
|
||||
MainActivity.ins.buf.append("Video isn't Playing on doFrame ").append(showCnt).append('\n');
|
||||
if(showCnt==0) {
|
||||
suspend();
|
||||
resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(showCnt>0) showCnt--;
|
||||
else return;
|
||||
} else if(isPlaying()) {
|
||||
seekTo(0);
|
||||
pause();
|
||||
seekTo(0);
|
||||
System.out.println("pause in doFrame()");
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
|
||||
static String getErrorName(int code) {
|
||||
if(code==MediaPlayer.MEDIA_ERROR_UNKNOWN) return "UNKNOWN";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_SERVER_DIED) return "SERVER_DIED";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) return "NOT_VALID_FOR_PROGRESSIVE_PLAYBACK";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_IO) return "IO";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_MALFORMED) return "MALFORMED";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_UNSUPPORTED) return "UNSUPPORTED";
|
||||
if(code==MediaPlayer.MEDIA_ERROR_TIMED_OUT) return "TIMED_OUT";
|
||||
if(code==-2147483648) return "SYSTEM";
|
||||
return "Unknown ("+code+")";
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
|
@ -18,9 +18,11 @@ import android.os.IBinder;
|
|||
import android.os.RemoteException;
|
||||
import android.os.StatFs;
|
||||
import android.view.Choreographer;
|
||||
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;
|
||||
|
@ -34,25 +36,29 @@ import java.io.FileNotFoundException;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import gnph.util.Dates;
|
||||
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 {
|
||||
public class MainActivity extends ComponentActivity implements Choreographer.FrameCallback, Runnable {
|
||||
|
||||
public static MainActivity ins;
|
||||
public Intent environIntent = new Intent();
|
||||
HashSet<EleEnviron> environs = new HashSet<>();
|
||||
BackView backView;
|
||||
ProgView progView;
|
||||
Prog progView;
|
||||
long launchMilli = System.currentTimeMillis();
|
||||
long syncMs;
|
||||
int state;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.R)
|
||||
|
@ -61,7 +67,9 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
|||
super.onCreate(savedInstanceState);
|
||||
startService(new Intent(this, RestartService.class));
|
||||
|
||||
System.out.println("---- MainActivity onCreate ---- UI Thread: "+Thread.currentThread().getId());
|
||||
var msg = "---- MainActivity onCreate ---- UI Thread: "+Thread.currentThread().getId();
|
||||
System.out.println(msg);
|
||||
buf.append(msg).append('\n');
|
||||
ins = this;
|
||||
if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) init();
|
||||
else {
|
||||
|
@ -87,10 +95,9 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
|||
|
||||
var program = new File(Util.programDir);
|
||||
if(program.isFile()) program.delete();
|
||||
System.out.println("mkdir: "+program.mkdirs());
|
||||
|
||||
var aaafiles = new File(Environment.getExternalStorageDirectory()+"/XixunPlayer").listFiles();
|
||||
if(aaafiles != null) for(var file : aaafiles) if(file.isFile() && ! file.getName().startsWith("background")) file.delete();
|
||||
var msg = "mkdir: "+program.mkdirs();
|
||||
System.out.println(msg);
|
||||
buf.append(msg).append('\n');
|
||||
|
||||
var conn = new ServiceConnection() {
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
|
@ -99,17 +106,21 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
|||
|
||||
public void onServiceConnected(ComponentName name, IBinder iBinder) {
|
||||
System.out.println("Bind cardsystem aidl service success");
|
||||
buf.append("Bind cardsystem aidl service success\n");
|
||||
var service = CardService.Stub.asInterface(iBinder);
|
||||
try {
|
||||
Util.isScreenOn = service.isScreenOpen();
|
||||
buf.append("isScreenOn:").append(Util.isScreenOn).append("\n");
|
||||
backView = new BackView(MainActivity.this, service.getScreenWidth(), service.getScreenHeight());
|
||||
state = 5;
|
||||
if(Util.isScreenOn) initProg();
|
||||
else state = 8;
|
||||
if(progView==null) setContentView(backView);
|
||||
} catch (RemoteException e) {
|
||||
Util.makeText(MainActivity.this, e.getMessage()).show();
|
||||
Util.makeText(MainActivity.this, e.toString()).show();
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
unbindService(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -121,11 +132,13 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
|||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
System.out.println("Receive PAUSE_PLAYER");
|
||||
buf.append("Receive PAUSE_PLAYER\n");
|
||||
Util.isScreenOn = ! intent.getBooleanExtra("pause", false);
|
||||
buf.append("isScreenOn:").append(Util.isScreenOn).append("\n");
|
||||
if(! Util.isScreenOn) {
|
||||
state = 8;
|
||||
if(progView!=null) {
|
||||
progView.setVisibility(GONE);
|
||||
progView.release();
|
||||
progView = null;
|
||||
setContentView(backView);
|
||||
}
|
||||
|
@ -150,140 +163,46 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
|||
}
|
||||
}, new IntentFilter("xixun.intent.action.TEMPERATURE_HUMIDITY"), RECEIVER_EXPORTED);
|
||||
|
||||
new Thread(()->{
|
||||
try {
|
||||
var serverSocket = new ServerSocket(3333);
|
||||
while(true) {
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
try {
|
||||
System.out.println("Accept ...");
|
||||
final var socket = serverSocket.accept();
|
||||
System.out.println("Receiving ...");
|
||||
in = socket.getInputStream();
|
||||
out = socket.getOutputStream();
|
||||
JSList<String> hases = null;
|
||||
label:
|
||||
while(true) {
|
||||
var obj = JSMap.from(in);
|
||||
var _type = obj.stnn("_type");
|
||||
System.out.println("_type: "+_type);
|
||||
switch(_type) {
|
||||
case "consult":
|
||||
JSList<String> ids = obj.jslist("idList");
|
||||
hases = new JSList<>();
|
||||
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);
|
||||
break;
|
||||
case "proStart":
|
||||
var proSize = obj.intg("proSize");
|
||||
var statFs = new StatFs(Environment.getExternalStorageDirectory().getPath());
|
||||
var remain = statFs.getAvailableBytes() - proSize - 1048576;
|
||||
if(remain < 0) {
|
||||
var latch = new CountDownLatch(1);
|
||||
runOnUiThread(() -> {
|
||||
System.out.println("removeAllViews ...");
|
||||
if(progView!=null) {
|
||||
progView.setVisibility(GONE);
|
||||
progView = null;
|
||||
setContentView(backView);
|
||||
}
|
||||
latch.countDown();
|
||||
});
|
||||
var files = new File(Util.programDir).listFiles();
|
||||
if(files == null) return;
|
||||
Arrays.sort(files, (f1, f2) -> (int) (f1.lastModified() - f2.lastModified()));
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ignored) {}
|
||||
for(var file : files) {
|
||||
if(hases!=null && hases.contains(file.getName())) continue;
|
||||
var len = file.length();
|
||||
if(file.delete()) {
|
||||
remain += len;
|
||||
if(remain>=0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "fileStart":
|
||||
var size = obj.intg("size");
|
||||
var name = obj.stnn("id");
|
||||
System.out.println(" size: " + size + " name: " + name);
|
||||
var fout = new FileOutputStream(Util.programDir + "/" + name);
|
||||
IOs.write(fout, in, size);
|
||||
fout.flush();
|
||||
fout.getFD().sync();
|
||||
fout.close();
|
||||
break;
|
||||
case "imgFileStart":
|
||||
size = obj.intg("size");
|
||||
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();
|
||||
});
|
||||
break;
|
||||
case "imgFileEnd":
|
||||
new JSMap("success", true).writeClose(out);
|
||||
break label;
|
||||
case "proEnd":
|
||||
new JSMap("success", true).writeClose(out);
|
||||
runOnUiThread(this::initProg);
|
||||
break label;
|
||||
case "DelPrograms":
|
||||
var latch = new CountDownLatch(1);
|
||||
AtomicBoolean ok = new AtomicBoolean(false);
|
||||
runOnUiThread(() -> {
|
||||
ok.set(delProgFile());
|
||||
latch.countDown();
|
||||
});
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ignored) {}
|
||||
new JSMap("success", ok.get()).writeClose(out);
|
||||
break label;
|
||||
case "DelBackImg":
|
||||
MainActivity.ins.runOnUiThread(() -> {
|
||||
MainActivity.ins.backView.cosImg = null;
|
||||
MainActivity.ins.backView.invalidate();
|
||||
});
|
||||
new JSMap("success", new File(Util.backImgFile).delete()).writeClose(out);
|
||||
break label;
|
||||
case "getPlayerState":
|
||||
var descs = Util.getState(state);
|
||||
new JSMap("code", state, "des_en", descs[0], "des", descs[1]).writeClose(out);
|
||||
break label;
|
||||
}
|
||||
registerReceiver(new BroadcastReceiver(){
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
try {
|
||||
var code = intent.getIntExtra("code", 0);
|
||||
buf.append("remote_control ").append(code).append("\n");
|
||||
if(progView == null || code > progView.pages.size()) return;
|
||||
if(! progView.avas.isEmpty()) page(curAva).hide();
|
||||
var millis = (System.currentTimeMillis()+999)/1000*1000;
|
||||
if(code > 0) {
|
||||
progView.avas.clear();
|
||||
progView.avas.add(code-1);
|
||||
curAva = 0;
|
||||
curTimes = 1;
|
||||
waitTo = 0;
|
||||
var page = page(0);
|
||||
dur = page.tDur;
|
||||
progView.stopAndPrepare(curAva);
|
||||
page.setMillis(millis);
|
||||
if(state != 6) {
|
||||
setContentView(progView);
|
||||
state = 6;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainActivity.ins.runOnUiThread(() -> {
|
||||
Util.makeText(MainActivity.this, e.getMessage()).show();
|
||||
});
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
O.close(in, out);
|
||||
} else {
|
||||
waitTo = Long.MAX_VALUE;
|
||||
syncProg(millis);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Util.makeText(MainActivity.this, e.toString()).show();
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainActivity.ins.runOnUiThread(() -> {
|
||||
Util.makeText(MainActivity.this, e.getMessage()).show();
|
||||
});
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}, new IntentFilter("com.xixun.yzd.REMOTE_CONTROL"), RECEIVER_EXPORTED);
|
||||
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
||||
public boolean delProgFile() {
|
||||
if(progView!=null) {
|
||||
progView.setVisibility(GONE);
|
||||
progView.release();
|
||||
progView = null;
|
||||
setContentView(backView);
|
||||
}
|
||||
|
@ -308,14 +227,15 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
|||
state = 3;
|
||||
return;
|
||||
}
|
||||
var view = new ProgView(task, this);
|
||||
var view = new Prog(task, this);
|
||||
if(view.getChildCount()==0) {
|
||||
state = 3;
|
||||
return;
|
||||
}
|
||||
if(progView!=null) progView.setVisibility(GONE);
|
||||
if(progView!=null) progView.release();
|
||||
progView = view;
|
||||
setContentView(progView);
|
||||
buf.append("init sync\n");
|
||||
syncProg((System.currentTimeMillis()+999)/1000*1000);
|
||||
choreographer.postFrameCallback(this);
|
||||
} catch (FileNotFoundException e) {
|
||||
|
@ -323,50 +243,77 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
|||
e.printStackTrace();
|
||||
} catch (Throwable e) {
|
||||
state = 7;
|
||||
Util.makeText(this, e.toString()).show();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
ArrayList<Integer> avas = new ArrayList<>();
|
||||
int curAva, curTimes = 1;
|
||||
long syncMilli = Long.MAX_VALUE;
|
||||
int curAva, curTimes = 1, dur;
|
||||
long waitTo = Long.MAX_VALUE;
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(progView == null) return;
|
||||
var milli = System.currentTimeMillis();
|
||||
var lastPage = page(curAva);
|
||||
if(milli >= syncMilli) {
|
||||
lastPage.hide();
|
||||
syncProg(milli-syncMilli>=1000 ? milli : syncMilli);
|
||||
} else if(milli >= lastPage.endMilli) {
|
||||
lastPage.hide();
|
||||
if(curTimes < lastPage.repeatTimes) curTimes++;
|
||||
else {
|
||||
curTimes = 1;
|
||||
curAva++;
|
||||
if(curAva >= avas.size()) {
|
||||
syncProg(milli-lastPage.endMilli>=1000 ? milli : lastPage.endMilli);
|
||||
choreographer.postFrameCallback(this);
|
||||
return;
|
||||
}
|
||||
if(progView.avas.isEmpty()) {
|
||||
if(milli >= waitTo) {
|
||||
waitTo = Long.MAX_VALUE;
|
||||
buf.append("wait sync\n");
|
||||
syncProg(milli);
|
||||
}
|
||||
page(curAva).setMillis(lastPage.endMilli);
|
||||
} else {
|
||||
for(var layer : lastPage.layers) {
|
||||
for(var ele : layer.eles) {
|
||||
if(ele.view.getVisibility()==VISIBLE) {
|
||||
if(milli >= ele.endMilli) ele.hide();
|
||||
} else if(milli < ele.endMilli && milli >= ele.startMilli) ele.show();
|
||||
var lastPage = page(curAva);
|
||||
if(milli >= lastPage.endMilli) {
|
||||
lastPage.hide();
|
||||
if(waitTo>0) {
|
||||
if(curTimes < lastPage.repeatTimes) curTimes++;
|
||||
else {
|
||||
curTimes = 1;
|
||||
curAva++;
|
||||
if(curAva >= progView.avas.size()) {
|
||||
var isDiff = milli-lastPage.endMilli>=1000;
|
||||
if(buf.length()>1000000) buf.replace(0, 100000, "");
|
||||
buf.append("isDiff:").append(isDiff).append(" endMs:").append(lastPage.endMilli).append(" millis:").append(milli).append("\n");
|
||||
syncProg(isDiff ? milli : lastPage.endMilli);
|
||||
buf.append("after. curAva:").append(curAva).append(" endMs:").append(lastPage.endMilli).append("\n");
|
||||
choreographer.postFrameCallback(this);
|
||||
return;
|
||||
}
|
||||
progView.stopAndPrepare(curAva);
|
||||
}
|
||||
}
|
||||
if(milli >= layer.endMilli) {
|
||||
layer.endMilli += layer.dur;
|
||||
page(curAva).setMillis(lastPage.endMilli);
|
||||
buf.append("curAva:").append(curAva).append(" endMs:").append(lastPage.endMilli).append("\n");
|
||||
} else {
|
||||
for(var layer : lastPage.layers) {
|
||||
for(var ele : layer.eles) {
|
||||
ele.endMilli += layer.dur;
|
||||
ele.startMilli += layer.dur;
|
||||
if(ele.startTime > 0) ele.hide();
|
||||
else ele.show();
|
||||
if(ele.view.getVisibility()==VISIBLE) {
|
||||
if(milli >= ele.endMilli) ele.hide();
|
||||
// else if(ele.needLoop) {
|
||||
// try {
|
||||
// var vv = (EleVideo) ele.view;
|
||||
// var vdur = vv.getDuration();
|
||||
// if(vdur>=1000) {
|
||||
// ele.needLoop = false;
|
||||
// if(ele.endTime-ele.startTime-vdur>=1000) vv.exoPlayer.setRepeatMode(ExoPlayer.REPEAT_MODE_ONE);
|
||||
// }
|
||||
// } catch (Throwable e) {
|
||||
// Util.makeText(this, e.toString()).show();
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
} else if(milli < ele.endMilli && milli >= ele.startMilli) ele.show();
|
||||
}
|
||||
if(milli >= layer.endMilli) {
|
||||
layer.endMilli += layer.dur;
|
||||
for(var ele : layer.eles) {
|
||||
ele.endMilli += layer.dur;
|
||||
ele.startMilli += layer.dur;
|
||||
if(ele.startTime > 0) ele.hide();
|
||||
else ele.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -376,35 +323,234 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
|
|||
|
||||
void syncProg(long milli) {
|
||||
curTimes = 1;
|
||||
var dur = calAvas(milli);
|
||||
progView.avas.clear();
|
||||
dur = 0;
|
||||
Prog.Page page;
|
||||
for(int i=0; i<progView.pages.size(); i++) if((page = progView.pages.get(i)).isSchedule(milli+dur)) {
|
||||
progView.avas.add(i);
|
||||
dur += page.tDur;
|
||||
}
|
||||
if(dur==0) {
|
||||
syncMilli = milli + 1000;
|
||||
waitTo = milli + 1000;
|
||||
if(state!=2) {
|
||||
setContentView(backView);
|
||||
state = 2;
|
||||
}
|
||||
} else {
|
||||
var page = page(curAva = 0);
|
||||
syncMilli = milli / dur * dur + dur;
|
||||
if(syncMilli - milli >= 500) page.setMillis(milli);
|
||||
var start = milli / dur * dur;
|
||||
curAva = 0;
|
||||
if(start < milli) {
|
||||
do {
|
||||
start += page(curAva++).tDur;
|
||||
} while(curAva < progView.avas.size() && start<=milli);
|
||||
start -= page(--curAva).tDur;
|
||||
syncMs = milli;
|
||||
buf.append("Sync. milli:").append(milli).append(" start:").append(start).append(" diff:").append(milli - start).append("\n");
|
||||
}
|
||||
progView.stopAndPrepare(curAva);
|
||||
page(curAva).setMillis(start);
|
||||
if(state != 6) {
|
||||
setContentView(progView);
|
||||
state = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
int calAvas(long milli) {
|
||||
avas.clear();
|
||||
var dur = 0;
|
||||
Page page;
|
||||
for(int i=0; i<progView.pages.size(); i++) if((page = progView.pages.get(i)).isSchedule(milli+dur)) {
|
||||
avas.add(i);
|
||||
dur += page.dur * page.repeatTimes;
|
||||
}
|
||||
return dur;
|
||||
|
||||
Prog.Page page(int i) {
|
||||
return progView.pages.get(progView.avas.get(i));
|
||||
}
|
||||
|
||||
Page page(int i) {
|
||||
return progView.pages.get(avas.get(i));
|
||||
public void run() {
|
||||
try {
|
||||
var serverSocket = new ServerSocket(3333);
|
||||
while(true) {
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
try {
|
||||
System.out.println("Accept ...");
|
||||
final var socket = serverSocket.accept();
|
||||
System.out.println("Receiving ...");
|
||||
in = socket.getInputStream();
|
||||
out = socket.getOutputStream();
|
||||
JSList<String> hases = null;
|
||||
while(true) {
|
||||
var obj = JSMap.from(in);
|
||||
var _type = obj.stnn("_type");
|
||||
System.out.println("_type: "+_type);
|
||||
if("consult".equals(_type)) {
|
||||
JSList<String> ids = obj.jslist("idList");
|
||||
hases = new JSList<>();
|
||||
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)) {
|
||||
var proSize = obj.intg("proSize");
|
||||
var statFs = new StatFs(Environment.getExternalStorageDirectory().getPath());
|
||||
var remain = statFs.getAvailableBytes() - proSize - 1048576;
|
||||
if(remain < 0) {
|
||||
var latch = new CountDownLatch(1);
|
||||
runOnUiThread(() -> {
|
||||
System.out.println("removeAllViews ...");
|
||||
if(progView!=null) {
|
||||
progView.release();
|
||||
progView = null;
|
||||
setContentView(backView);
|
||||
}
|
||||
latch.countDown();
|
||||
});
|
||||
var files = new File(Util.programDir).listFiles();
|
||||
if(files == null) return;
|
||||
Arrays.sort(files, (f1, f2) -> (int) (f1.lastModified() - f2.lastModified()));
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException ignored) {}
|
||||
for(var file : files) {
|
||||
if(hases!=null && hases.contains(file.getName())) continue;
|
||||
var len = file.length();
|
||||
if(file.delete()) {
|
||||
remain += len;
|
||||
if(remain>=0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if("fileStart".equals(_type)) {
|
||||
var size = obj.intg("size");
|
||||
var name = obj.stnn("id");
|
||||
System.out.println(" size: " + size + " name: " + name);
|
||||
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", true).write(out);
|
||||
buf.append("proEnd\n");
|
||||
runOnUiThread(this::initProg);
|
||||
} 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 = "yy-MM-dd HH:mm:ss.SSS";
|
||||
writer.append("ProgSend: ").append(Dates.fmt(new File(Util.programDir + "/program").lastModified(), fmt)).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(Dates.fmt(launchMilli, fmt)).append("\n");
|
||||
writer.append(" Sync: ").append(Dates.fmt(syncMs, fmt)).append("\n");
|
||||
writer.append("Page End: ").append(progView==null || progView.avas.isEmpty() ? "0" : Dates.fmt(page(curAva).endMilli, fmt)).append(" CurPage: ").append(String.valueOf(curAva)).append(" / ").append(progView==null || progView.avas.isEmpty() ? "0" : String.valueOf(progView.avas.get(curAva))).append("\n");
|
||||
writer.append(" Current: ").append(Dates.fmt(System.currentTimeMillis(), fmt)).append("\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 Memory: ").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");
|
||||
var latch = new CountDownLatch(1);
|
||||
runOnUiThread(() -> {
|
||||
if(! progView.avas.isEmpty()) {
|
||||
var page = page(curAva);
|
||||
for(var layer : page.layers) for(var ele : layer.eles) if(ele.view.getVisibility()==VISIBLE) {
|
||||
try {
|
||||
if(ele.view instanceof EleVideo) {
|
||||
var view = (EleVideo) ele.view;
|
||||
if(view.ijkPlayer!=null) {
|
||||
writer.append("isVideoPlaying: ").append(String.valueOf(view.ijkPlayer.isPlaying())).append("\n");
|
||||
writer.append("getVideoDecoder: ").append(String.valueOf(view.ijkPlayer.getVideoDecoder())).append("\n");
|
||||
var MediaInfo = view.ijkPlayer.getMediaInfo();
|
||||
writer.append("mMediaPlayerName: ").append(MediaInfo.mMediaPlayerName).append("\n");
|
||||
writer.append("mVideoDecoder: ").append(MediaInfo.mVideoDecoder).append("\n");
|
||||
writer.append("mVideoDecoderImpl: ").append(MediaInfo.mVideoDecoderImpl).append("\n");
|
||||
writer.append("mAudioDecoder: ").append(MediaInfo.mAudioDecoder).append("\n");
|
||||
writer.append("mAudioDecoderImpl: ").append(MediaInfo.mAudioDecoderImpl).append("\n");
|
||||
writer.append("mFormat: ").append(MediaInfo.mMeta.mFormat).append("\n");
|
||||
}
|
||||
// else if(view.exoPlayer!=null) {
|
||||
// writer.append("isVideoPlaying: ").append(String.valueOf(view.exoPlayer.isPlaying())).append(String.valueOf(view.exoPlayer.getCurrentPosition())).append("/").append(String.valueOf(view.exoPlayer.getDuration())).append("\n");
|
||||
// writer.append("getPlaybackState: ").append(view.getState()).append("\n");
|
||||
// writer.append("getPlayerError: ").append(String.valueOf(view.exoPlayer.getPlayerError())).append("\n");
|
||||
// writer.append("getPlaybackSuppressionReason: ").append(String.valueOf(view.exoPlayer.getPlaybackSuppressionReason())).append("\n");
|
||||
// writer.append("getVideoFormat: ").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");
|
||||
// }
|
||||
} else if(ele.view instanceof WebView) {
|
||||
var view = (WebView) ele.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(buf.toString().getBytes());
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
var emsg = e.getMessage();
|
||||
if(emsg!=null && ("Socket closed".equals(emsg) || emsg.endsWith("end-of-input"))) continue;
|
||||
MainActivity.ins.runOnUiThread(() -> {
|
||||
Util.makeText(MainActivity.this, e.getMessage()).show();
|
||||
});
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
O.close(in, out);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
MainActivity.ins.runOnUiThread(() -> {
|
||||
Util.makeText(MainActivity.this, e.toString()).show();
|
||||
});
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import gnph.util.Dates;
|
||||
import gnph.util.JSList;
|
||||
import gnph.util.JSMap;
|
||||
|
||||
public class Page {
|
||||
|
||||
public static class EleBase {
|
||||
View view;
|
||||
long startMilli;
|
||||
long endMilli = Long.MAX_VALUE;
|
||||
int startTime;
|
||||
int endTime;
|
||||
String id;
|
||||
String type;
|
||||
boolean isVideo;
|
||||
|
||||
void show() {
|
||||
if(view.getVisibility()==VISIBLE) return;
|
||||
view.setVisibility(VISIBLE);
|
||||
if(isVideo) view.setLeft(0);
|
||||
}
|
||||
void hide() {
|
||||
if(view.getVisibility()!=VISIBLE) return;
|
||||
if(isVideo) view.setLeft(8000);
|
||||
view.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Layer {
|
||||
ArrayList<EleBase> eles = new ArrayList<>();
|
||||
long endMilli = Long.MAX_VALUE;
|
||||
int dur;
|
||||
boolean isLoop;
|
||||
}
|
||||
|
||||
public static class Sche {
|
||||
long startDate = -1, endDate = -1;
|
||||
int startTime = -1, endTime = -1;
|
||||
JSList<Integer> weeks;
|
||||
}
|
||||
|
||||
ArrayList<Layer> layers = new ArrayList<>();
|
||||
ArrayList<Sche> sches;
|
||||
long endMilli = Long.MAX_VALUE;
|
||||
int dur, repeatTimes;
|
||||
|
||||
void hide() {
|
||||
for(var layer : layers) for(var ele : layer.eles) ele.hide();
|
||||
}
|
||||
|
||||
public void setMillis(long milli) {
|
||||
endMilli = milli + dur;
|
||||
for(var layer : layers) {
|
||||
if(layer.isLoop) layer.endMilli = milli + layer.dur;
|
||||
for(var ele : layer.eles) {
|
||||
ele.endMilli = milli + ele.endTime;
|
||||
ele.startMilli = milli + ele.startTime;
|
||||
if(ele.startTime == 0) ele.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean isSchedule(long milli) {
|
||||
if(sches==null) return true;
|
||||
var local = milli + Dates.zoneOff;
|
||||
var time = local % 86400000L;
|
||||
var week = -1;
|
||||
for(var sche : sches) {
|
||||
if(notInRange(sche.startDate, local, sche.endDate)) continue;
|
||||
if(notInRange(sche.startTime, time, sche.endTime)) continue;
|
||||
if(sche.weeks==null) return true;
|
||||
if(week==-1) week = LocalDate.ofEpochDay(local / 86400000L).getDayOfWeek().getValue();
|
||||
if(sche.weeks.contains(week)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean notInRange(long start, long val, long end) {
|
||||
if(end==-1) return false;
|
||||
return start <= end ? !(val >= start && val < end) : val >= end && val < start;
|
||||
}
|
||||
|
||||
public void parse(JSList<JSMap> schedules) {
|
||||
if(schedules!=null) for(var schedule : schedules) {
|
||||
var sche = new Sche();
|
||||
var startTime = schedule.str("startTime");
|
||||
if(startTime!=null) sche.startTime = LocalTime.parse(startTime).toSecondOfDay()*1000;
|
||||
var endTime = schedule.str("endTime");
|
||||
if(endTime!=null) sche.endTime = LocalTime.parse(endTime).toSecondOfDay()*1000;
|
||||
if(sche.startTime==sche.endTime) sche.startTime = sche.endTime = -1;
|
||||
var startDate = schedule.str("startDate");
|
||||
if(startDate!=null) sche.startDate = LocalDate.parse(startDate).toEpochDay() * 86400000L;
|
||||
var endDate = schedule.str("endDate");
|
||||
if(endDate!=null) sche.endDate = (LocalDate.parse(endDate).toEpochDay() + 1) * 86400000L;
|
||||
if(sche.startDate==sche.endDate) sche.startDate = sche.endDate = -1;
|
||||
JSList<Integer> weekFilter = schedule.jslist("weekFilter");
|
||||
if(weekFilter!=null && ! weekFilter.isEmpty() && weekFilter.size() < 7) sche.weeks = weekFilter;
|
||||
if(sches==null) sches = new ArrayList<>();
|
||||
sches.add(sche);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,23 +3,30 @@ package com.xixun.xixunplayer;
|
|||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.view.View;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import gnph.util.Dates;
|
||||
import gnph.util.JSList;
|
||||
import gnph.util.JSMap;
|
||||
import pl.droidsonroids.gif.GifImageView;
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
public class ProgView extends AbsLayout {
|
||||
public class Prog extends AbsLayout {
|
||||
|
||||
ArrayList<Page> pages = new ArrayList<>();
|
||||
ArrayList<Integer> avas = new ArrayList<>();
|
||||
HashSet<Source> toBeHided = new HashSet<>();
|
||||
|
||||
public ProgView(JSMap task, Context context) {
|
||||
public Prog(JSMap task, Context context) {
|
||||
super(context);
|
||||
JSList<JSMap> jpages = task.jslist("items");
|
||||
for(var pageMap : jpages) {
|
||||
|
@ -31,7 +38,7 @@ public class ProgView extends AbsLayout {
|
|||
page.repeatTimes = pageMap.intg("repeatTimes");
|
||||
page.parse(pageMap.jslist("schedules"));
|
||||
for(int ll=layers.size()-1; ll>=0; ll--) {
|
||||
var layer = new Page.Layer();
|
||||
var layer = new Layer();
|
||||
layer.isLoop = layers.get(ll).bool("repeat");
|
||||
JSList<JSMap> sources = layers.get(ll).jslist("sources");
|
||||
var border = layers.get(ll).jsmap("border");
|
||||
|
@ -41,8 +48,9 @@ public class ProgView extends AbsLayout {
|
|||
bdEle = new EleBorder(Util.programDir+"/"+border.stnn("img"), border.stnn("eff"), border.intg("speed"), context);
|
||||
bdWidth = bdEle.img.getHeight();
|
||||
}
|
||||
var ele = new Page.EleBase();
|
||||
var ele = new Source();
|
||||
int x, y, w, h;
|
||||
String id;
|
||||
for(var source : sources) {
|
||||
ele.type = source.stnn("_type");
|
||||
if(ele.type.isEmpty()) continue;
|
||||
|
@ -59,13 +67,15 @@ public class ProgView extends AbsLayout {
|
|||
ele.endTime = ele.startTime + timeSpan;
|
||||
if(bdEnd < ele.endTime) bdEnd = ele.endTime;
|
||||
if(layer.dur < ele.endTime) layer.dur = ele.endTime;
|
||||
if(page.dur < ele.endTime && notAudio) page.dur = ele.endTime;
|
||||
ele.id = source.stnn("id");
|
||||
if(page.sDur < ele.endTime && notAudio) page.sDur = ele.endTime;
|
||||
id = source.stnn("id");
|
||||
ele.view = null;
|
||||
if(ele.type.equals("Image")) {
|
||||
ImageView imgView = source.stnn("fileExt").equalsIgnoreCase("gif") ? new GifImageView(context) : new ImageView(context);
|
||||
imgView.setImageURI(Uri.fromFile(new File(Util.programDir+"/"+ele.id)));
|
||||
var isGif = source.stnn("fileExt").equalsIgnoreCase("gif");
|
||||
ImageView imgView = isGif ? new GifImageView(context) : new ImageView(context);
|
||||
imgView.setImageURI(ele.uri = Uri.fromFile(new File(Util.programDir + "/" + id)));
|
||||
imgView.setScaleType(ImageView.ScaleType.FIT_XY);
|
||||
if(! isGif) ele.uri = null;
|
||||
ele.view = imgView;
|
||||
} else if(ele.type.equals("MultiPng")) {
|
||||
JSList<JSMap> imgs = source.jslist("arrayPics");
|
||||
|
@ -102,21 +112,9 @@ public class ProgView extends AbsLayout {
|
|||
}
|
||||
w = 0;
|
||||
} else if(ele.type.equals("DigitalClockNew")) ele.view = new EleDigiClock(Util.programDir+"/", source, context);
|
||||
else if(ele.type.equals("AnalogClock")) ele.view = new EleAnaClock(w, h, Util.programDir+"/"+ele.id, source, context);
|
||||
else if(ele.type.equals("Video")) {
|
||||
ele.isVideo = true;
|
||||
var videoView = new EleVideo(Util.programDir + "/" + ele.id, context);
|
||||
ele.view = new AbsLayout(context);
|
||||
((AbsLayout) ele.view).addView(videoView, new AbsLayout.LayoutParams(x, y, w, h));
|
||||
var vol = source.intg("vol", 100);
|
||||
if(vol < 100) videoView.vol = vol / 100.0f;
|
||||
w = 0;
|
||||
} else if(ele.type.equals("Audio")) {
|
||||
var videoView = new EleVideo(Util.programDir+"/"+ele.id, context);
|
||||
ele.view = videoView;
|
||||
var vol = source.intg("vol", 100);
|
||||
if(vol<100) videoView.vol = vol/100.0f;
|
||||
} else if(ele.type.equals("WebURL")) {
|
||||
else if(ele.type.equals("AnalogClock")) ele.view = new EleAnaClock(w, h, Util.programDir + "/" + id, source, context);
|
||||
else if(ele.type.equals("Video") || ele.type.equals("Audio")) ele.view = new EleVideo(context, Util.programDir + "/" +id, source.intg("vol", 100) / 100.0f);
|
||||
else if(ele.type.equals("WebURL")) {
|
||||
var webView = new WebView(context);
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
|
@ -135,7 +133,7 @@ public class ProgView extends AbsLayout {
|
|||
ele.view.setVisibility(GONE);
|
||||
addView(ele.view);
|
||||
layer.eles.add(ele);
|
||||
ele = new Page.EleBase();
|
||||
ele = new Source();
|
||||
}
|
||||
if(bdEle!=null && ! sources.isEmpty()) {
|
||||
JSList<Long> geometry = border.jslist("geometry");
|
||||
|
@ -152,23 +150,129 @@ public class ProgView extends AbsLayout {
|
|||
}
|
||||
if(! layer.eles.isEmpty()) page.layers.add(layer);
|
||||
}
|
||||
if(page.dur==0) continue;
|
||||
if(page.sDur==0) continue;
|
||||
page.tDur = page.sDur * page.repeatTimes;
|
||||
for_layer: for(int ll=0; ll<page.layers.size(); ll++) {
|
||||
var layer = page.layers.get(ll);
|
||||
for(int ee=0; ee<layer.eles.size(); ee++) {
|
||||
var ele = layer.eles.get(ee);
|
||||
if(ele.startTime >= page.dur) {
|
||||
if(ele.startTime >= page.sDur) {
|
||||
if(layer.eles.size() > 1) layer.eles.remove(ee--);
|
||||
else {
|
||||
page.layers.remove(ll--);
|
||||
continue for_layer;
|
||||
}
|
||||
} else if(ele.endTime > page.dur) ele.endTime = page.dur;
|
||||
} else if(ele.endTime > page.sDur) ele.endTime = page.sDur;
|
||||
}
|
||||
if(layer.dur > page.dur) layer.dur = page.dur;
|
||||
if(layer.dur == page.dur) layer.isLoop = false;
|
||||
if(layer.dur > page.sDur) layer.dur = page.sDur;
|
||||
if(layer.dur == page.sDur) layer.isLoop = false;
|
||||
}
|
||||
pages.add(page);
|
||||
}
|
||||
}
|
||||
|
||||
void release() {
|
||||
try {
|
||||
setVisibility(GONE);
|
||||
View view;
|
||||
for(int cc=0; cc<getChildCount(); cc++) if((view = getChildAt(cc)) instanceof EleVideo) ((EleVideo) view).release();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Source {
|
||||
View view;
|
||||
long prepareMilli;
|
||||
long startMilli;
|
||||
long endMilli = Long.MAX_VALUE;
|
||||
int startTime;
|
||||
int endTime;
|
||||
String type;
|
||||
Uri uri;
|
||||
|
||||
void show() {
|
||||
if(view.getVisibility()==VISIBLE) return;
|
||||
view.setVisibility(VISIBLE);
|
||||
}
|
||||
void hide() {
|
||||
if(view.getVisibility()!=VISIBLE) return;
|
||||
view.setVisibility(GONE);
|
||||
if(uri!=null) ((GifImageView) view).setImageURI(uri);
|
||||
}
|
||||
}
|
||||
public static class Layer {
|
||||
ArrayList<Source> eles = new ArrayList<>();
|
||||
long endMilli = Long.MAX_VALUE;
|
||||
int dur;
|
||||
boolean isLoop;
|
||||
}
|
||||
|
||||
public static class Sche {
|
||||
long startDate = -1, endDate = -1;
|
||||
int startTime = -1, endTime = -1;
|
||||
JSList<Integer> weeks;
|
||||
}
|
||||
|
||||
public static class Page {
|
||||
ArrayList<Layer> layers = new ArrayList<>();
|
||||
ArrayList<Sche> sches;
|
||||
long endMilli = Long.MAX_VALUE;
|
||||
int sDur, tDur, repeatTimes;
|
||||
|
||||
void hide() {
|
||||
for(var layer : layers) for(var ele : layer.eles) ele.hide();
|
||||
}
|
||||
|
||||
public void setMillis(long milli) {
|
||||
endMilli = milli + sDur;
|
||||
for(var layer : layers) {
|
||||
if(layer.isLoop) layer.endMilli = milli + layer.dur;
|
||||
for(var ele : layer.eles) {
|
||||
ele.endMilli = milli + ele.endTime;
|
||||
ele.startMilli = milli + ele.startTime;
|
||||
if(ele.startTime == 0) ele.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean isSchedule(long milli) {
|
||||
if(sches==null) return true;
|
||||
var local = milli + Dates.zoneOff;
|
||||
var time = local % 86400000L;
|
||||
var week = -1;
|
||||
for(var sche : sches) {
|
||||
if(notInRange(sche.startDate, local, sche.endDate)) continue;
|
||||
if(notInRange(sche.startTime, time, sche.endTime)) continue;
|
||||
if(sche.weeks==null) return true;
|
||||
if(week==-1) week = LocalDate.ofEpochDay(local / 86400000L).getDayOfWeek().getValue();
|
||||
if(sche.weeks.contains(week)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean notInRange(long start, long val, long end) {
|
||||
if(end==-1) return false;
|
||||
return start <= end ? !(val >= start && val < end) : val >= end && val < start;
|
||||
}
|
||||
|
||||
public void parse(JSList<JSMap> schedules) {
|
||||
if(schedules!=null) for(var schedule : schedules) {
|
||||
var sche = new Sche();
|
||||
var startTime = schedule.str("startTime");
|
||||
if(startTime!=null) sche.startTime = LocalTime.parse(startTime).toSecondOfDay()*1000;
|
||||
var endTime = schedule.str("endTime");
|
||||
if(endTime!=null) sche.endTime = LocalTime.parse(endTime).toSecondOfDay()*1000;
|
||||
if(sche.startTime==sche.endTime) sche.startTime = sche.endTime = -1;
|
||||
var startDate = schedule.str("startDate");
|
||||
if(startDate!=null) sche.startDate = LocalDate.parse(startDate).toEpochDay() * 86400000L;
|
||||
var endDate = schedule.str("endDate");
|
||||
if(endDate!=null) sche.endDate = (LocalDate.parse(endDate).toEpochDay() + 1) * 86400000L;
|
||||
if(sche.startDate==sche.endDate) sche.startDate = sche.endDate = -1;
|
||||
JSList<Integer> weekFilter = schedule.jslist("weekFilter");
|
||||
if(weekFilter!=null && ! weekFilter.isEmpty() && weekFilter.size() < 7) sche.weeks = weekFilter;
|
||||
if(sches==null) sches = new ArrayList<>();
|
||||
sches.add(sche);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -97,7 +97,15 @@ public class Server extends Service {
|
|||
var json = JSMap.from(jsonstr.getBytes(StandardCharsets.UTF_8));
|
||||
var _type = json.stnn("_type");
|
||||
id = json.stnn("id");
|
||||
if(_type.equals("DeleteTask")) {
|
||||
if(_type.equals("PlayXixunTask")) {
|
||||
MainActivity.ins.runOnUiThread(() -> MainActivity.ins.delProgFile());
|
||||
return new JSMap(
|
||||
"_type", "DataCallback",
|
||||
"result", "received command",
|
||||
"cardId", Util.getCardId(),
|
||||
"commandId", id
|
||||
).toString();
|
||||
} else if(_type.equals("DeleteTask")) {
|
||||
MainActivity.ins.runOnUiThread(() -> MainActivity.ins.delProgFile());
|
||||
return new JSMap(
|
||||
"_type", "DataCallback",
|
||||
|
@ -145,6 +153,7 @@ public class Server extends Service {
|
|||
"commandId", id
|
||||
).toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return new JSMap(
|
||||
"_type", "Error",
|
||||
"errorMessage", e.toString(),
|
||||
|
@ -166,7 +175,7 @@ public class Server extends Service {
|
|||
|
||||
@Override
|
||||
public boolean clearTasks() throws RemoteException {
|
||||
System.out.println("Server clearTasks ...");
|
||||
MainActivity.ins.runOnUiThread(() -> MainActivity.ins.delProgFile());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ public class Util {
|
|||
}
|
||||
|
||||
public static String programDir, backImgFile;
|
||||
|
||||
public static String getCardId() {
|
||||
try {
|
||||
var bytes = IOs.readBytesClose(new FileInputStream(new File("/data/joey/signed/card.id")));
|
||||
|
|
|
@ -10,6 +10,7 @@ dependencyResolutionManagement {
|
|||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user