This commit is contained in:
Gangphon 2024-03-26 15:15:57 +08:00
parent b8be2bfd5d
commit 6465b57b0a
10 changed files with 170 additions and 204 deletions

View File

@ -11,7 +11,7 @@ android {
minSdk 21
targetSdk 34
versionCode 1
versionName "2.0.1"
versionName "2.0.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

View File

@ -1,126 +0,0 @@
package com.xixun.xixunplayer;
import android.content.Context;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import androidx.annotation.OptIn;
import androidx.media3.common.MediaItem;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.SeekParameters;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
public class EleVVV extends SurfaceView implements SurfaceHolder.Callback {
String path;
float vol;
IjkMediaPlayer ijkPlayer;
ExoPlayer exoPlayer;
public EleVVV(Context context, String path, float vol) {
super(context);
this.path = path;
this.vol = vol;
initIjk();
}
@OptIn(markerClass = UnstableApi.class)
void initExo() {
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);
exoPlayer.prepare();
}
void initIjk() {
ijkPlayer = new IjkMediaPlayer();
//ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 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);
try {
getHolder().addCallback(this);
ijkPlayer.setDataSource(path);
ijkPlayer.setLooping(true);
ijkPlayer.setVolume(vol, vol);
ijkPlayer.setOnPreparedListener((IMediaPlayer var1)->{
if(ijkPlayer.getBitRate() > 12000000) {
getHolder().removeCallback(this);
release();
initExo();
}
if(isShown()) start();
});
ijkPlayer.prepareAsync();
} catch (Throwable e) {
Util.makeText(getContext(), Util.toStr(e)).show();
Util.printStackTrace(e);
ijkPlayer = null;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if(ijkPlayer!=null) 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");
}
void start() {
if(ijkPlayer!=null) {
ijkPlayer.seekTo(0);
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() {
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) start();
else pause();
}
}

View File

@ -100,7 +100,6 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
if(requestCode==999 && grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED && backView==null) init();
}
int receCnt;
ConnService connService;
@SuppressLint("UnspecifiedRegisterReceiverFlag")
@ -130,13 +129,11 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
Util.screenWidth = service.getScreenWidth();
Util.screenHeight = service.getScreenHeight();
Util.println(" IsScreenOn: "+Util.isScreenOn+" screen: "+Util.screenWidth+" x "+Util.screenHeight);
if(receCnt++>=1) {
backView = new BackView(MainActivity.this, Util.screenWidth, Util.screenHeight);
state = 5;
if(Util.isScreenOn) initProg();
else state = 8;
if(progView==null) setContentView(backView);
}
backView = new BackView(MainActivity.this, Util.screenWidth, Util.screenHeight);
state = 5;
if(Util.isScreenOn) initProg();
else state = 8;
if(progView==null) setContentView(backView);
} catch (Exception e) {
Util.makeText(MainActivity.this, Util.toStr(e)).show();
Util.printStackTrace(e);
@ -164,13 +161,6 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
if(! Util.serverURL.startsWith("http")) Util.serverURL = "http://"+Util.serverURL;
if(! Util.serverURL.endsWith("/")) Util.serverURL += "/";
}
if(receCnt++>=1) {
backView = new BackView(MainActivity.this, Util.screenWidth, Util.screenHeight);
state = 5;
if(Util.isScreenOn) initProg();
else state = 8;
if(progView==null) setContentView(backView);
}
} catch (Exception e) {
Util.makeText(MainActivity.this, Util.toStr(e)).show();
Util.printStackTrace(e);
@ -355,7 +345,7 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra
if(task==null) {
if(! root.containsKey("layers")) {
state = 3;
Util.println(" Error: task==null\n");
Util.println(root.isEmpty() ? " Empty program JSON\n" : " Error: task==null\n");
return;
}
task = new JSMap("items", new JSList<>(new JSMap("repeatTimes", 1, "_program", root)));

View File

@ -218,15 +218,13 @@ public class Prog extends AbsLayout {
}
}
} else {
var start = src.startTime;
var ele0 = src;
for(var map : imgs) {
var picDur = map.intg("picDuration")*1000;
if(picDur==0) picDur = timeSpan / imgs.size();
src.type = "Image";
src.startTime = start;
src.endTime = start = src.startTime + picDur;
if(src!=ele0) {
src.startTime = layer.srcs.get(layer.srcs.size()-1).endTime;
src.entryEff = ele0.entryEff;
src.exitEff = ele0.exitEff;
src.entryDur = ele0.entryDur;
@ -235,6 +233,7 @@ public class Prog extends AbsLayout {
src.isEntryRand = ele0.isEntryRand;
src.isExitRand = ele0.isExitRand;
}
src.endTime = src.startTime + picDur;
if(hasTTS) {
src.text = map.str("text");
if(src.text!=null) {
@ -279,7 +278,7 @@ public class Prog extends AbsLayout {
else if(src.type.startsWith("Environ")) src.view = new SrcEnviron(this, source);
else if(src.type.startsWith("Weather")) src.view = new SrcWeather(context, source);
else if(src.type.startsWith("VistorSource")) src.view = new SrcVisitor(this, source);
else if(src.type.startsWith("MultiLineText")) src.view = new SrcSensor(context, source);
else if(src.type.startsWith("MultiLineText")) src.view = new SrcSensor(this, source, geo.width, geo.height);
else continue;
if(src.view==null) continue;
src.view.setVisibility(GONE);

View File

@ -138,10 +138,7 @@ public class Server extends Service {
var filename = source.str("id");
if(filename==null) continue;
var url = source.stnn("url");
if(! url.startsWith("http")) {
if(preDownloadURL==null) continue;
url = preDownloadURL + filename;
}
if(! url.startsWith("http")) url = preDownloadURL + filename;
var file = new File(Util.programDir+"/"+filename);
if(file.exists() && file.length() > 0) {
proSize -= file.length();
@ -154,10 +151,7 @@ public class Server extends Service {
var filename = img.str("id");
if(filename==null) continue;
var url = img.stnn("url");
if(! url.startsWith("http")) {
if(preDownloadURL==null) continue;
url = preDownloadURL + filename;
}
if(! url.startsWith("http")) url = preDownloadURL + filename;
var file = new File(Util.programDir+"/"+filename);
if(file.exists() && file.length() > 0) {
proSize -= file.length();
@ -314,7 +308,12 @@ public class Server extends Service {
@Override
public String getProgramTask() throws RemoteException {
return null;
try {
return IOs.readStrClose(new FileInputStream(Util.programDir+"/program"));
} catch (Exception e) {
Util.printStackTrace(e);
return Util.toStr(e);
}
}
@Override

View File

@ -1,12 +1,7 @@
package com.xixun.xixunplayer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.Choreographer;
import android.view.SurfaceView;
import android.view.View;
import androidx.annotation.NonNull;

View File

@ -1,37 +1,41 @@
package com.xixun.xixunplayer;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.view.Choreographer;
import android.webkit.WebView;
import java.text.DecimalFormat;
import java.util.ArrayList;
import gnph.util.JSMap;
import gnph.util.NumFmts;
import gnph.util.Txts;
import gnph.util.URLConn;
public class SrcSensor extends WebView implements IntentReceiver, Choreographer.FrameCallback {
static String directs[] = {"NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW", "N"};
MainActivity act;
String html, prefix, url, text;
int interval;
boolean isFirst = true;
ArrayList<String> htmls;
String prefix, suffix, url, text;
int interval, pageDur, cur;
@SuppressLint("SetJavaScriptEnabled")
public SrcSensor(Context context, JSMap json) {
super(context);
act = (MainActivity) context;
public SrcSensor(Prog prog, JSMap json, int width, int height) {
super(prog.getContext());
act = (MainActivity) prog.getContext();
setBackgroundColor(Color.TRANSPARENT);
setVerticalScrollBarEnabled(false);
setHorizontalScrollBarEnabled(false);
setInitialScale(100);
getSettings().setJavaScriptEnabled(true);
html = json.stnn("html").replace("%Co2", "%CO2");
var html = json.stnn("html").replace("%Co2", "%CO2").replace("<p>", "").trim();
htmls = Txts.split(html, "</p>", 1);
pageDur = json.intg("speed")*1000;
if(pageDur==0) pageDur = json.intg("timeSpan")*1000 / htmls.size();
url = json.str("sUrl");
interval = json.intg("sInterval") * 1000;
if(url!=null && interval>0 && html.contains("%s")) {
@ -47,13 +51,18 @@ public class SrcSensor extends WebView implements IntentReceiver, Choreographer.
prefix = "<body style=\"color:#fff;margin:0;padding:0;";
var lineHeight = json.str("lineHeight");
if(lineHeight!=null) prefix += "line-height:"+lineHeight+";";
prefix += "\">";
prefix += "width:"+width+"; height:"+height+"; position:relative;\"><div id=\"ppp\" style=\"position:absolute;\">";
suffix = "</div></body>";
if(json.bool("center")) suffix += "<script>window.onload = function() { var ppp = document.getElementById(\"ppp\");\n" +
" ppp.style.top = ("+height+"-ppp.offsetHeight)/2+'px';\n" +
"};</script>";
prog.calls.add(this);
}
static DecimalFormat fmt0 = NumFmts.newDecFmt("0");
public void onReceive(Intent intent) {
try {
var htm = html;
var htm = htmls.get(cur);
var temp = intent.getFloatExtra("temperature", -99f);
var fa = temp * 1.8f + 32;
var noTemp = temp==-99f;
@ -106,39 +115,44 @@ public class SrcSensor extends WebView implements IntentReceiver, Choreographer.
.replace("%radiation", (radiation == -1 ? "--" : String.valueOf(radiation))+"W/m²")
.replace("%bm", (beam == -1 ? "--" : String.valueOf(beam))+"lux");
loadDataWithBaseURL(null, prefix+htm+"</body>", "text/html", "UTF-8", null);
loadDataWithBaseURL(null, prefix+htm+suffix, "text/html", "UTF-8", null);
} catch (Exception e) {
Util.printStackTrace(e);
}
}
long nextMs;
@Override
public void onVisibilityAggregated(boolean isVisible) {
super.onVisibilityAggregated(isVisible);
if(isVisible) {
if(isFirst) {
isFirst = false;
onReceive(act.environIntent);
act.environs.add(this);
}
} else {
act.environs.remove(this);
isFirst = true;
}
}
long nextPageMs, nextMs;
boolean isFirst = true;
@Override
public void doFrame(long ms) {
if(! isShown()) return;
if(! isShown()) {
act.environs.remove(this);
isFirst = true;
return;
}
boolean needRefresh = false;
if(isFirst) {
isFirst = false;
cur = 0;
nextPageMs = ms + pageDur;
act.environs.add(this);
needRefresh = true;
} else if(ms>=nextPageMs) {
nextPageMs += pageDur;
if(cur>=htmls.size()-1) cur = 0;
else cur++;
needRefresh = true;
}
if(text!=null && ms>=nextMs) {
nextMs = ms + interval;
try {
text = URLConn.send(url);
needRefresh = true;
} catch (Exception e) {
Util.printStackTrace(e);
}
}
if(needRefresh) onReceive(act.environIntent);
}
}

View File

@ -60,7 +60,7 @@ public class SrcVideo extends TextureView implements TextureView.SurfaceTextureL
release();
initExo();
}
if(isShown() || isLive) start();
if(isShown()) start();
});
ijkPlayer.prepareAsync();
} catch (Throwable e) {
@ -71,18 +71,17 @@ public class SrcVideo extends TextureView implements TextureView.SurfaceTextureL
}
@Override
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
setSurfaceTextureListener(null);
if(ijkPlayer!=null) ijkPlayer.setSurface(new Surface(surface));
}
@Override
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
}
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {}
@Override
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
}
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {}
void start() {
if(ijkPlayer!=null) {

View File

@ -0,0 +1,106 @@
package com.xixun.xixunplayer;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.view.Choreographer;
import android.view.Surface;
import android.view.TextureView;
import androidx.annotation.NonNull;
public class SrcVideo2 extends TextureView implements TextureView.SurfaceTextureListener, Choreographer.FrameCallback {
float vol;
MediaPlayer player;
char state;
boolean isLive;
public SrcVideo2(Prog prog, String path, float vol, boolean isLive) {
super(prog.getContext());
this.vol = vol;
this.isLive = isLive;
player = new MediaPlayer();
setSurfaceTextureListener(this);
player.setLooping(true);
player.setVolume(vol, vol);
player.setOnPreparedListener((MediaPlayer player)->{
player.setOnPreparedListener(null);
Util.println(" ------Prepared isShown"+isShown()+" "+this);
if(isShown()) {
player.start();
state = 'S';
} else state = 'P';
prog.calls.add(this);
});
player.setOnErrorListener((MediaPlayer mp, int what, int extra)->{
var err = "Media Error: "+getErrorName(what)+". "+getErrorName(extra);
Util.makeText(getContext(), err).show();
Util.println(err);
return true;
});
try {
player.setDataSource(path);
player.prepareAsync();
} catch (Exception e) {
Util.printStackTrace(e);
Util.makeText(getContext(), Util.toStr(e)).show();
}
}
@Override
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
setSurfaceTextureListener(null);
if(player!=null) player.setSurface(new Surface(surface));
}
@Override
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {}
@Override
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
return false;
}
@Override
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {}
@Override
public void onVisibilityAggregated(boolean isVisible) {
super.onVisibilityAggregated(isVisible);
if(state==0) return;
if(isVisible) {
Util.println(" ------start "+this);
player.seekTo(0);
player.start();
if(isLive) player.setVolume(vol, vol);
} else if(isLive) player.setVolume(0, 0);
else {
Util.println(" ------pause "+this);
player.pause();
player.seekTo(0);
}
}
void release() {
if(player!=null) {
player.release();
player = null;
}
}
@Override
public void doFrame(long ms) {
// if(isShown()) return;
// if(player!=null) {
// player.pause();
// player.seekTo(0);
// }
}
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+")";
}
}

View File

@ -1,21 +1,11 @@
package com.xixun.xixunplayer;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.view.Choreographer;
import android.webkit.WebView;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.regex.Pattern;
import gnph.util.IOs;
import gnph.util.JSList;
import gnph.util.JSMap;
import gnph.util.NumFmts;
import gnph.util.Txts;
import gnph.util.URLConn;
@SuppressLint("ViewConstructor")