diff --git a/XixunPlayer/app/build.gradle b/XixunPlayer/app/build.gradle index ab53e6d..e18d8b1 100644 --- a/XixunPlayer/app/build.gradle +++ b/XixunPlayer/app/build.gradle @@ -11,7 +11,7 @@ android { minSdk 24 targetSdk 34 versionCode 1 - versionName "1.0.20-sensor" + versionName "1.0.22-tts" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/XixunPlayer/app/src/main/assets/imgs/W0.png b/XixunPlayer/app/src/main/assets/imgs/W0.png new file mode 100644 index 0000000..3e37d21 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W0.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W1.png b/XixunPlayer/app/src/main/assets/imgs/W1.png new file mode 100644 index 0000000..5dee862 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W1.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W10.png b/XixunPlayer/app/src/main/assets/imgs/W10.png new file mode 100644 index 0000000..7d55efe Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W10.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W13.png b/XixunPlayer/app/src/main/assets/imgs/W13.png new file mode 100644 index 0000000..8577bdc Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W13.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W14.png b/XixunPlayer/app/src/main/assets/imgs/W14.png new file mode 100644 index 0000000..2537239 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W14.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W15.png b/XixunPlayer/app/src/main/assets/imgs/W15.png new file mode 100644 index 0000000..4be21b3 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W15.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W16.png b/XixunPlayer/app/src/main/assets/imgs/W16.png new file mode 100644 index 0000000..0f2e015 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W16.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W17.png b/XixunPlayer/app/src/main/assets/imgs/W17.png new file mode 100644 index 0000000..04f83db Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W17.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W18.png b/XixunPlayer/app/src/main/assets/imgs/W18.png new file mode 100644 index 0000000..a3aec72 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W18.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W19.png b/XixunPlayer/app/src/main/assets/imgs/W19.png new file mode 100644 index 0000000..32736e2 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W19.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W2.png b/XixunPlayer/app/src/main/assets/imgs/W2.png new file mode 100644 index 0000000..c27cea2 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W2.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W20.png b/XixunPlayer/app/src/main/assets/imgs/W20.png new file mode 100644 index 0000000..2b326a8 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W20.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W29.png b/XixunPlayer/app/src/main/assets/imgs/W29.png new file mode 100644 index 0000000..1178e2e Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W29.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W3.png b/XixunPlayer/app/src/main/assets/imgs/W3.png new file mode 100644 index 0000000..10e825b Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W3.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W30.png b/XixunPlayer/app/src/main/assets/imgs/W30.png new file mode 100644 index 0000000..de3615c Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W30.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W31.png b/XixunPlayer/app/src/main/assets/imgs/W31.png new file mode 100644 index 0000000..b4dd147 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W31.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W32.png b/XixunPlayer/app/src/main/assets/imgs/W32.png new file mode 100644 index 0000000..581663d Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W32.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W33.png b/XixunPlayer/app/src/main/assets/imgs/W33.png new file mode 100644 index 0000000..3b51e5a Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W33.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W34.png b/XixunPlayer/app/src/main/assets/imgs/W34.png new file mode 100644 index 0000000..0bc4e72 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W34.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W35.png b/XixunPlayer/app/src/main/assets/imgs/W35.png new file mode 100644 index 0000000..cfa67ec Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W35.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W36.png b/XixunPlayer/app/src/main/assets/imgs/W36.png new file mode 100644 index 0000000..2b326a8 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W36.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W4.png b/XixunPlayer/app/src/main/assets/imgs/W4.png new file mode 100644 index 0000000..17a05d8 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W4.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W44.png b/XixunPlayer/app/src/main/assets/imgs/W44.png new file mode 100644 index 0000000..d829389 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W44.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W45.png b/XixunPlayer/app/src/main/assets/imgs/W45.png new file mode 100644 index 0000000..9129ef8 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W45.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W46.png b/XixunPlayer/app/src/main/assets/imgs/W46.png new file mode 100644 index 0000000..9129ef8 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W46.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W5.png b/XixunPlayer/app/src/main/assets/imgs/W5.png new file mode 100644 index 0000000..5f7cbd7 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W5.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W6.png b/XixunPlayer/app/src/main/assets/imgs/W6.png new file mode 100644 index 0000000..2e1a63c Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W6.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W7.png b/XixunPlayer/app/src/main/assets/imgs/W7.png new file mode 100644 index 0000000..d37cc41 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W7.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W8.png b/XixunPlayer/app/src/main/assets/imgs/W8.png new file mode 100644 index 0000000..a3394db Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W8.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/W9.png b/XixunPlayer/app/src/main/assets/imgs/W9.png new file mode 100644 index 0000000..8e98a1c Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/W9.png differ diff --git a/XixunPlayer/app/src/main/assets/imgs/logo3.png b/XixunPlayer/app/src/main/assets/imgs/logo3.png new file mode 100644 index 0000000..3b4ea20 Binary files /dev/null and b/XixunPlayer/app/src/main/assets/imgs/logo3.png differ diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/EleVideo.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/EleVideo.java index ed044fa..f15c370 100644 --- a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/EleVideo.java +++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/EleVideo.java @@ -23,11 +23,13 @@ public class EleVideo extends TextureView implements TextureView.SurfaceTextureL IjkMediaPlayer ijkPlayer; ExoPlayer exoPlayer; long bitRate; + boolean isLive; - public EleVideo(Context context, String path, float vol) { + public EleVideo(Context context, String path, float vol, boolean isLive) { super(context); this.path = path; this.vol = vol; + this.isLive = isLive; initIjk(); } @@ -59,7 +61,7 @@ public class EleVideo extends TextureView implements TextureView.SurfaceTextureL release(); initExo(); } - if(isShown()) start(); + if(isShown() || isLive) start(); }); ijkPlayer.prepareAsync(); } catch (Throwable e) { @@ -127,7 +129,10 @@ public class EleVideo extends TextureView implements TextureView.SurfaceTextureL @Override public void onVisibilityAggregated(boolean isVisible) { super.onVisibilityAggregated(isVisible); - if(isVisible) start(); + if(isVisible) { + start(); + if(isLive) ijkPlayer.setVolume(vol, vol); + } else if(isLive) ijkPlayer.setVolume(0, 0); else pause(); } } \ No newline at end of file diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/MainActivity.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/MainActivity.java index d372637..040342f 100644 --- a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/MainActivity.java +++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/MainActivity.java @@ -18,6 +18,7 @@ import android.os.Environment; import android.os.IBinder; import android.os.RemoteException; import android.os.StatFs; +import android.os.StrictMode; import android.view.Choreographer; import android.view.View; import android.webkit.WebView; @@ -78,6 +79,8 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra ins = this; startService(new Intent(this, RestartService.class)); + StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build()); + if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) init(); else { Util.println("---- No permission, Try again ..."); @@ -142,7 +145,7 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra intentFilter.addDataScheme("file"); registerReceiver(new BroadcastReceiver(){ long lastMs; - char [] pass = {'8','8','8'}; + final char[] pass = {'8','8','8'}; @Override public void onReceive(Context context, Intent intent) { var path = intent.getData().getPath(); @@ -167,16 +170,12 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra } if(progJson==null) { Util.println("No program File"); - runOnUiThread(() -> { - Util.makeText(MainActivity.this, "No program File").show(); - }); + runOnUiThread(() -> Util.makeText(MainActivity.this, "No program File").show()); return; } if(size==0) { Util.println("zip size is 0"); - runOnUiThread(() -> { - Util.makeText(MainActivity.this, "zip size is 0").show(); - }); + runOnUiThread(() -> Util.makeText(MainActivity.this, "zip size is 0").show()); return; } Util.deleteFiles(size, null); @@ -189,9 +188,7 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra }); } catch (Exception e) { Util.printStackTrace(e); - runOnUiThread(() -> { - Util.makeText(MainActivity.this, Util.toStr(e)).show(); - }); + runOnUiThread(() -> Util.makeText(MainActivity.this, Util.toStr(e)).show()); } }).start(); } @@ -238,14 +235,14 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra var code = intent.getIntExtra("code", 0); Util.println(" remote_control "+code); if(progView == null || code > progView.pages.size()) return; - if(! progView.avas.isEmpty()) page(curAva).hide(); + if(! progView.avas.isEmpty()) page(progView.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; + progView.curAva = 0; + progView.curTimes = 1; + progView.waitTo = 0; //点播 var page = page(0); page.setMillis(millis); if(state != 6) { @@ -253,7 +250,7 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra state = 6; } } else { - waitTo = Long.MAX_VALUE; + progView.waitTo = Long.MAX_VALUE; syncProg(millis); } } catch (Throwable e) { @@ -360,8 +357,6 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra } Choreographer choreographer = Choreographer.getInstance(); - int curAva, curTimes = 1; - long waitTo = Long.MAX_VALUE; boolean canAdd = true; @Override @@ -372,34 +367,34 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra } var milli = System.currentTimeMillis(); if(progView.avas.isEmpty()) { - if(milli >= waitTo) { - waitTo = Long.MAX_VALUE; + if(milli >= progView.waitTo) { + progView.waitTo = Long.MAX_VALUE; Util.println("wait sync"); syncProg(milli); } } else { - var lastPage = page(curAva); + var lastPage = page(progView.curAva); if(milli >= lastPage.endMilli) { lastPage.hide(); - if(waitTo>0) { //waitTo==0 为点播,不换页 - if(curTimes < lastPage.repeatTimes) curTimes++; + if(progView.waitTo > 0) { //waitTo==0 为点播,不换页 + if(progView.curTimes < lastPage.repeatTimes) progView.curTimes++; else { - curTimes = 1; - curAva++; - if(curAva >= progView.avas.size()) { + progView.curTimes = 1; + progView.curAva++; + if(progView.curAva >= progView.avas.size()) { var isDiff = milli-lastPage.endMilli>=1000; if(Util.buf.length()>1000000) Util.buf.replace(0, 100000, ""); Util.println("isDiff: "+isDiff+" endMs: "+lastPage.endMilli+" millis:"+milli); syncProg(isDiff ? milli : lastPage.endMilli); - Util.println("after. curAva: "+curAva+" endMs: "+page(curAva).endMilli); + Util.println("after. curAva: "+progView.curAva+" endMs: "+page(progView.curAva).endMilli); choreographer.postFrameCallback(this); canAdd = false; return; } } } - page(curAva).setMillis(lastPage.endMilli); - Util.println("curAva: "+curAva+" endMs: "+page(curAva).endMilli); + page(progView.curAva).setMillis(lastPage.endMilli); + Util.println("curAva: "+progView.curAva+" endMs: "+page(progView.curAva).endMilli); } else { for(var layer : lastPage.layers) { for(var src : layer.srcs) { @@ -425,36 +420,42 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra } void syncProg(long milli) { - curTimes = 1; + progView.curTimes = 1; progView.avas.clear(); var dur = 0; - for(int i=0; i hases = null; @@ -557,7 +558,7 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra writer.append("\n"); writer.append(" Launch: ").append(Fmt.format(launchMilli)).append("\n"); writer.append(" Sync: ").append(Fmt.format(syncMs)).append("\n"); - writer.append("Page End: ").append(progView==null || progView.avas.isEmpty() ? "0" : Fmt.format(page(curAva).endMilli)).append(" CurPage: ").append(String.valueOf(curAva)).append(" / ").append(progView==null || progView.avas.isEmpty() ? "0" : String.valueOf(progView.avas.get(curAva))).append("\n"); + 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"); writer.append(" Current: ").append(Fmt.format(System.currentTimeMillis())).append("\n"); var statFs = new StatFs(Environment.getExternalStorageDirectory().getPath()); writer.append(" Disk: ").append(String.valueOf(statFs.getTotalBytes()/1000000)).append(" ").append(String.valueOf(statFs.getAvailableBytes()/1000000)).append(" ").append(String.valueOf(statFs.getFreeBytes()/1000000)).append(" (total avail free)\n"); @@ -573,7 +574,7 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra var latch = new CountDownLatch(1); runOnUiThread(() -> { if(progView!=null && ! progView.avas.isEmpty()) { - var page = page(curAva); + var page = page(progView.curAva); for(var layer : page.layers) for(var src : layer.srcs) if(src.view.getVisibility()==VISIBLE) { try { if(src.view instanceof EleVideo) { @@ -600,6 +601,9 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra writer.append("getPlaybackParameters: ").append(String.valueOf(view.exoPlayer.getPlaybackParameters())).append("\n"); } writer.append("\n"); + } else if(src.view instanceof SrcWeather) { + var view = (SrcWeather) src.view; + writer.append("SrcWeather html: ").append(view.html).append("\n"); } else if(src.view instanceof WebView) { var view = (WebView) src.view; writer.append("Title: ").append(view.getTitle()).append("\n"); @@ -624,10 +628,7 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra if(files == null) return; Arrays.sort(files, (f1, f2) -> (int) (f2.lastModified() - f1.lastModified())); var writer = new OutputStreamWriter(out); - for(var file : files) { - var len = file.length(); - writer.append(file.getName()).append(' ').append(String.valueOf(file.length())).append('\n'); - } + for(var file : files) writer.append(file.getName()).append(' ').append(String.valueOf(file.length())).append('\n'); writer.append('\n'); writer.flush(); } else if("GetFile".equals(_type)) { @@ -644,19 +645,15 @@ public class MainActivity extends ComponentActivity implements Choreographer.Fra Util.println(emsg); continue; } - MainActivity.ins.runOnUiThread(() -> { - Util.makeText(MainActivity.this, Util.toStr(e)).show(); - }); + MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.this, Util.toStr(e)).show()); Util.printStackTrace(e); } finally { O.close(in, out); - Util.println("conn end\n\n"); + Util.println("conn end\n"); } } } catch (Throwable e) { - MainActivity.ins.runOnUiThread(() -> { - Util.makeText(MainActivity.this, Util.toStr(e)).show(); - }); + MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.this, Util.toStr(e)).show()); Util.printStackTrace(e); } } diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/Prog.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/Prog.java index 7740973..b4377c1 100644 --- a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/Prog.java +++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/Prog.java @@ -3,6 +3,7 @@ package com.xixun.xixunplayer; import android.annotation.SuppressLint; import android.content.Context; import android.net.Uri; +import android.speech.tts.TextToSpeech; import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; @@ -24,6 +25,8 @@ public class Prog extends AbsLayout { ArrayList pages = new ArrayList<>(); ArrayList avas = new ArrayList<>(); + int curAva, curTimes = 1; + long waitTo = Long.MAX_VALUE; public Prog(JSMap task, Context context) { super(context); @@ -163,16 +166,30 @@ public class Prog extends AbsLayout { imgView.setScaleType(ImageView.ScaleType.FIT_XY); src.view = imgView; } - } else if(src.type.equals("MultiPng") || src.type.equals("SplitText")) { + } else if(src.type.startsWith("MultiPng") || src.type.equals("SplitText")) { JSList imgs = source.jslist("arrayPics"); if(imgs.isEmpty()) continue; - if(imgs.size()==1 && imgs.get(0).intg("picDuration")==0) src.view = new EleScroll(context, imgs.get(0)); - else { + var mode = source.str("curchange"); + var hasTTS = src.type.endsWith("Audio"); + var speechRate = (float) source.dbl("voiceRate"); + if(mode!=null ? mode.endsWith("roll") : (imgs.size()==1 && imgs.get(0).intg("picDuration")==0)) { + var img = imgs.get(0); + src.view = new EleScroll(context, img); + if(hasTTS) { + src.text = img.str("text"); + if(src.text!=null) { + src.tts = new TextToSpeech(context, (int status)->{ + Util.println("status: "+status+" "+(status==TextToSpeech.SUCCESS)); + }, "com.iflytek.speechcloud"); + src.tts.setSpeechRate(speechRate); + } + } + } else { var start = src.startTime; var ele0 = src; for(var map : imgs) { var picDur = map.intg("picDuration")*1000; - if(picDur==0) continue; + if(picDur==0) picDur = timeSpan / imgs.size(); src.type = "Image"; src.startTime = start; src.endTime = start = src.startTime + picDur; @@ -185,6 +202,15 @@ public class Prog extends AbsLayout { src.isEntryRand = ele0.isEntryRand; src.isExitRand = ele0.isExitRand; } + if(hasTTS) { + src.text = map.str("text"); + if(src.text!=null) { + src.tts = new TextToSpeech(context, (int status)->{ + Util.println("status: "+status+" "+(status==TextToSpeech.SUCCESS)); + }, "com.iflytek.speechcloud"); + src.tts.setSpeechRate(speechRate); + } + } var imgView = new ImageView(context); imgView.setImageURI(Uri.fromFile(new File(Util.programDir + "/" + map.stnn("id")))); imgView.setScaleType(ImageView.ScaleType.FIT_XY); @@ -199,9 +225,12 @@ public class Prog extends AbsLayout { } else if(src.type.equals("DigitalClock")) src.view = new SrcDigitalClock(context, source); else if(src.type.startsWith("DigitalClock")) src.view = new SrcDigiClock(context, source); else if(src.type.equals("AnalogClock")) src.view = new SrcAnaClock(geo.width, geo.height, Util.programDir + "/" + id, source, context); - else if(src.type.equals("Audio")) src.view = new EleVideo(context, Util.programDir + "/" +id, source.intg("vol", 100) / 100.0f); - else if(src.type.equals("Video")) { - var key = id + src.startTime + src.endTime; + else if(src.type.equals("Audio")) src.view = new EleVideo(context, Util.programDir + "/" +id, source.intg("vol", 100) / 100.0f, false); + else if(src.type.endsWith("Video")) { + var isLive = src.type.startsWith("Live"); + var url = source.str("url"); + if(isLive && url==null) continue; + var key = isLive?url:id + src.startTime + src.endTime; var videoView = videoMap.get(key); if(videoView!=null) { var geoOld = (AbsLayout.LayoutParams) videoView.getLayoutParams(); @@ -212,7 +241,7 @@ public class Prog extends AbsLayout { src.view = new SrcCopy(context, videoView); ((SrcCopy) src.view).scaleX = 0; } else { - src.view = new EleVideo(context, Util.programDir+"/"+id, source.intg("vol", 100) / 100.0f); + src.view = new EleVideo(context, isLive ? url : Util.programDir+"/"+id, source.intg("vol", 100) / 100.0f, isLive); videoMap.put(key, (EleVideo) src.view); } } else if(src.type.equals("WebURL")) { @@ -229,6 +258,7 @@ public class Prog extends AbsLayout { else if(src.type.equals("Timer")) src.view = new SrcTimer(context, source); else if(src.type.equals("Countdown")) src.view = new SrcCountdown(context, source); else if(src.type.startsWith("Environ")) src.view = new SrcEnviron(context, source); + else if(src.type.startsWith("Weather")) src.view = new SrcWeather(context, source); else if(src.type.startsWith("MultiLineText")) src.view = new SrcSensor(context, source); else continue; if(src.view==null) continue; @@ -278,6 +308,7 @@ public class Prog extends AbsLayout { setVisibility(GONE); View view; for(int cc=0; cc imgs = source.jslist("arrayPics"); if(imgs.isEmpty()) continue; for(var img : imgs) { diff --git a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcEnviron.java b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcEnviron.java index 06e03e6..4c70ba5 100644 --- a/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcEnviron.java +++ b/XixunPlayer/app/src/main/java/com/xixun/xixunplayer/SrcEnviron.java @@ -112,7 +112,7 @@ public class SrcEnviron extends View implements Choreographer.FrameCallback, Int item.nums.add(img); } } else { - var num = ((Number) method.invoke(intent, item.key, -999)).doubleValue(); + var num = ((Number) method.invoke(intent, item.key, -999)).floatValue(); var str = num==-999 || (num==-1 && ! item.key.endsWith("rature")) ? "--" : NumFmts.zz().format(num); for(int cc=0; cc"; + hasAQI = html.contains("%{aqi}"); + hasCur = html.contains("%{current}") || html.contains("%{arr.0."); + hasDays = html.contains("%{arr."); + + nextMs = System.currentTimeMillis() + 1800000; + refresh(); + } + + public void refresh() { + try { + var htm = html; + if(hasAQI) { + try { + JSList aqiForecast = JSMap.fromClose(new URLConn("https://www.ledokcloud.com/weather/whapi/json/alicityweather/aqiforecast5days").writeJson("{\"cityId\":"+code+"}").in()).jsmap("data").jslist("aqiForecast"); + htm = htm.replace("%{aqi}", aqiForecast.get(1).stnn("value")); + } catch (Exception e) { + Util.printStackTrace(e); + } + } + String type = null; + if(hasCur) { + try { + var condition = JSMap.fromClose(new URLConn("https://www.ledokcloud.com/weather/whapi/json/alicityweather/condition").writeJson("{\"cityId\":"+code+"}").in()).jsmap("data").jsmap("condition"); + htm = htm.replace("%{current}", condition.stnn("temp")); + htm = htm.replace("%{arr.0.type}", type = condition.stnn("condition")); + htm = htm.replace("%{arr.0.fx}", condition.stnn("windDir")); + htm = htm.replace("%{arr.0.fl}", condition.stnn("windLevel")); + } catch (Exception e) { + Util.printStackTrace(e); + } + } + if(hasDays) { + try { + JSList days = JSMap.fromClose(new URLConn("https://www.ledokcloud.com/weather/whapi/json/alicityweather/forecast15days").writeJson("{\"cityId\":"+code+"}").in()).jsmap("data").jslist("forecast"); + int lastEnd = 0, appendIdx = 0; + var buf = new StringBuilder(htm.length()*3/2); + int start; + while((start = htm.indexOf("%{arr.", lastEnd)) > -1) { + int idxS = start+6, idxE; + try { + if(htm.charAt(idxS+1)=='.') idxE = idxS+1; + else if(htm.charAt(idxS+2)=='.') idxE = idxS+2; + else { + lastEnd = idxS; + continue; + } + var dd = Integer.parseInt(htm.substring(idxS, idxE))+1; + if(dd>=days.size()) { + lastEnd = idxE+1; + continue; + } + int fds = idxE+1, fde = idxE+2; + for(; fde<=fds+16; fde++) if(htm.charAt(fde)=='}') break; + if(fde > fds+16) { + lastEnd = fds; + continue; + } + var fd = htm.substring(fds, fde); + String replace = null; + if(fd.equals("date")) replace = days.get(dd).stnn("predictDate"); + else if(fd.equals("type")) replace = days.get(dd).stnn("conditionDay"); + else if(fd.equals("high")) replace = days.get(dd).stnn("tempDay"); + else if(fd.equals("low")) replace = days.get(dd).stnn("tempNight"); + else if(fd.equals("fx")) replace = days.get(dd).stnn("windDirDay"); + else if(fd.equals("fl")) replace = days.get(dd).stnn("windLevelDay"); + else if(fd.startsWith("img-")) { + var parts = Txts.split(fd, "-", 1); + String w = "32", h = "32"; + if(parts.size()>=3) { + w = parts.get(1); + h = parts.get(2); + } + replace = ""; + } + lastEnd = fde+1; + if(replace!=null) { + buf.append(htm, appendIdx, start).append(replace); + appendIdx = lastEnd; + } + Util.println("Found: " + htm.substring(start, lastEnd)+" dd "+dd+" fd "+fd); + } catch (Exception e) { + lastEnd = idxS; + Util.printStackTrace(e); + } + } + if(buf.length()>0) { + if(appendIdx < htm.length()) buf.append(htm, appendIdx, htm.length()); + htm = buf.toString(); + } + } catch (Exception e) { + Util.printStackTrace(e); + } + } + loadDataWithBaseURL(null, prefix+htm+"", "text/html", "UTF-8", null); + } catch (Exception e) { + Util.printStackTrace(e); + } + } + + static HashMap dayImgMap = new HashMap<>(); + static HashMap nitImgMap = new HashMap<>(); + + static{ + dayImgMap.put("晴", "0"); + dayImgMap.put("大部晴朗", "0"); + dayImgMap.put("多云", "1"); + dayImgMap.put("少云", "1"); + dayImgMap.put("阴", "2"); + dayImgMap.put("阵雨", "3"); + dayImgMap.put("局部阵雨", "3"); + dayImgMap.put("小阵雨", "3"); + dayImgMap.put("强阵雨", "3"); + dayImgMap.put("阵雪", "13"); + dayImgMap.put("小阵雪", "13"); + dayImgMap.put("雾", "18"); + dayImgMap.put("冻雾", "18"); + dayImgMap.put("沙尘暴", "20"); + dayImgMap.put("浮尘", "29"); + dayImgMap.put("尘卷风", "29"); + dayImgMap.put("扬沙", "29"); + dayImgMap.put("强沙尘暴", "20"); + dayImgMap.put("霾", "45"); + dayImgMap.put("雷阵雨", "4"); + dayImgMap.put("雷电", "4"); + dayImgMap.put("雷暴", "4"); + dayImgMap.put("雷阵雨伴有冰雹", "5"); + dayImgMap.put("冰雹", "5"); + dayImgMap.put("冰针", "5"); + dayImgMap.put("冰粒", "5"); + dayImgMap.put("雨夹雪", "6"); + dayImgMap.put("小雨", "7"); + dayImgMap.put("中雨", "8"); + dayImgMap.put("大雨", "9"); + dayImgMap.put("暴雨", "10"); + dayImgMap.put("大暴雨", "10"); + dayImgMap.put("特大暴雨", "10"); + dayImgMap.put("小雪", "14"); + dayImgMap.put("中雪", "15"); + dayImgMap.put("大雪", "16"); + dayImgMap.put("暴雪", "17"); + dayImgMap.put("冻雨", "19"); + dayImgMap.put("雪", "15"); + dayImgMap.put("雨", "8"); + dayImgMap.put("小到中雨", "7"); + dayImgMap.put("中到大雨", "9"); + dayImgMap.put("大到暴雨", "10"); + dayImgMap.put("小到中雪", "15"); + dayImgMap.put("无天气类型", "unknown"); + + nitImgMap.put("晴", "30"); + nitImgMap.put("大部晴朗", "30"); + nitImgMap.put("多云", "31"); + nitImgMap.put("少云", "31"); + nitImgMap.put("阴", "2"); + nitImgMap.put("阵雨", "33"); + nitImgMap.put("局部阵雨", "33"); + nitImgMap.put("小阵雨", "33"); + nitImgMap.put("强阵雨", "33"); + nitImgMap.put("阵雪", "34"); + nitImgMap.put("小阵雪", "4"); + nitImgMap.put("雾", "32"); + nitImgMap.put("冻雾", "32"); + nitImgMap.put("沙尘暴", "36"); + nitImgMap.put("浮尘", "35"); + nitImgMap.put("尘卷风", "5"); + nitImgMap.put("扬沙", "35"); + nitImgMap.put("强沙尘暴", "36"); + nitImgMap.put("霾", "46"); + nitImgMap.put("雷阵雨", "4"); + nitImgMap.put("雷电", "4"); + nitImgMap.put("雷暴", "4"); + nitImgMap.put("雷阵雨伴有冰雹", "5"); + nitImgMap.put("冰雹", "5"); + nitImgMap.put("冰针", "5"); + nitImgMap.put("冰粒", "5"); + nitImgMap.put("雨夹雪", "6"); + nitImgMap.put("小雨", "7"); + nitImgMap.put("中雨", "8"); + nitImgMap.put("大雨", "9"); + nitImgMap.put("暴雨", "10"); + nitImgMap.put("大暴雨", "10"); + nitImgMap.put("特大暴雨", "10"); + nitImgMap.put("小雪", "14"); + nitImgMap.put("中雪", "15"); + nitImgMap.put("大雪", "16"); + nitImgMap.put("暴雪", "17"); + nitImgMap.put("冻雨", "19"); + nitImgMap.put("雪", "15"); + nitImgMap.put("雨", "8"); + nitImgMap.put("小到中雨", "7"); + nitImgMap.put("中到大雨", "9"); + nitImgMap.put("大到暴雨", "10"); + nitImgMap.put("小到中雪", "15"); + nitImgMap.put("无天气类型", "unknown"); + } + long nextMs; + + @Override + public void onVisibilityAggregated(boolean isVisible) { + super.onVisibilityAggregated(isVisible); + if(isVisible) { + var ms = System.currentTimeMillis(); + if(ms>=nextMs) { + nextMs += 1800000; + refresh(); + } + } + } +}