xixunplayer
|
@ -0,0 +1,15 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
|
@ -0,0 +1,3 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="GRADLE" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="jbr-17" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,9 @@
|
|||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,41 @@
|
|||
plugins {
|
||||
id 'com.android.application'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.xixun.xixunplayer'
|
||||
compileSdk 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.xixun.xixunplayer"
|
||||
minSdk 28
|
||||
targetSdk 33
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
aidl true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation files('libs\\gnph.jar')
|
||||
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25'
|
||||
implementation files('libs\\xixun_card_settings_1.2.4.jar')
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"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"
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.XixunPlayer">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<service android:name=".Server"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.xixun.action.PlayerInfo"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
<receiver android:name="com.xixun.xixunplayer.BootCompletedReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter android:priority="999">
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
</manifest>
|
|
@ -0,0 +1,47 @@
|
|||
// PlayerInfo.aidl
|
||||
package com.xixun.util;
|
||||
|
||||
// Declare any non-default types here with import statements
|
||||
|
||||
interface PlayerInfo {
|
||||
//***需要实现,用于外部接口获取当前播放的节目名
|
||||
String getProgramName();
|
||||
//不需要实现
|
||||
String getVersion();
|
||||
//外部接口通知播放器屏幕宽高发生变化
|
||||
void setScreenWidth(int w);
|
||||
void setScreenHeight(int h);
|
||||
//不需要
|
||||
void taskScreenshot(String cmdId);
|
||||
//不需要
|
||||
void setExternalTemperature(float t);
|
||||
void setInternalTemperature(float t);
|
||||
void setHumidity(float h);
|
||||
//暂时不需要
|
||||
boolean forcePlayProgram(String pid);
|
||||
boolean finishForcePlay();
|
||||
//需要实现,让其他进程获取到当前播放的节目id
|
||||
String getCurProgramId();
|
||||
//需要,外部进程设置播放器的USB节目解压密码
|
||||
void setUSBProgramPwd(String pwd);
|
||||
//***需要,接收平台节目接口
|
||||
String executeJosnCommand(String josn);
|
||||
//暂停播放,以前的版本没有实现
|
||||
void pausePlayer(boolean b);
|
||||
//查询节目是否暂停播放
|
||||
boolean isPause();
|
||||
//***需要,清空节目和下载的素材
|
||||
boolean clearTasks();
|
||||
//需要,返回当前已有的节目数量
|
||||
int countOfPrograms(int type);
|
||||
//需要,指定id播放插播节目
|
||||
void playInsertTask(String pid);
|
||||
//需要,指定id停止播放插播节目
|
||||
void stopInsertTask(String pid);
|
||||
//***需要,回读当前节目json
|
||||
String getProgramTask();
|
||||
//不需要
|
||||
void setUploadLogUrl(String playLog);
|
||||
//不需要
|
||||
String getUploadLogUrl();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Environment;
|
||||
import android.view.View;
|
||||
|
||||
public class BackView extends View {
|
||||
|
||||
public Bitmap img, cosImg;
|
||||
public int width, height;
|
||||
|
||||
public BackView(Context context, int width, int height) {
|
||||
super(context);
|
||||
img = BitmapFactory.decodeResource(context.getResources(), R.drawable.back);
|
||||
cosImg = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + "/XixunPlayer/background");
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if(cosImg!=null) canvas.drawBitmap(cosImg, new Rect(0, 0, cosImg.getWidth(), cosImg.getHeight()), new Rect(0, 0, width, height), null);
|
||||
else if(img!=null) for(int y=0; y<height; y+=img.getHeight()) for(int x=0; x<width; x+=img.getWidth()) canvas.drawBitmap(img, x, y, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
package com.xixun.xixunplayer;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
public class BootCompletedReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
System.out.println("BootCompletedReceiver onReceive ---- "+intent.getAction());
|
||||
intent = new Intent(context, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import static android.graphics.Paint.Join.ROUND;
|
||||
import static android.graphics.Paint.Style.FILL_AND_STROKE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
import gnph.util.JSMap;
|
||||
|
||||
public class EleAnaClock extends View implements Choreographer.FrameCallback {
|
||||
|
||||
ZoneId timeZone;
|
||||
Bitmap img;
|
||||
int pinHourColor, pinMinColor, pinSecColor;
|
||||
Path hPath, mPath, sPath;
|
||||
float hAngle, mAngle, sAngle;
|
||||
Paint paint = new Paint();
|
||||
boolean showSecHand;
|
||||
|
||||
public EleAnaClock(float w, float h, String path, JSMap layer, Context context) {
|
||||
super(context);
|
||||
timeZone = ZoneId.of(layer.stnn("timeZone"));
|
||||
img = BitmapFactory.decodeFile(path);
|
||||
pinHourColor = Color.parseColor(layer.stnn("pinHourColor"));
|
||||
pinMinColor = Color.parseColor(layer.stnn("pinMinColor"));
|
||||
pinSecColor = Color.parseColor(layer.stnn("pinSecColor"));
|
||||
var hhLen = layer.intg("pinHourLen");
|
||||
var mhLen = layer.intg("pinMinLen");
|
||||
var shLen = layer.intg("pinSecLen");
|
||||
var hhWidth = layer.intg("pinHourWidth");
|
||||
var mhWidth = layer.intg("pinMinWidth");
|
||||
var shWidth = layer.intg("pinSecWidth");
|
||||
showSecHand = layer.bool("showSecond");
|
||||
var sideLen = w;
|
||||
if(h < sideLen) sideLen = h;
|
||||
var lineWidth = sideLen/128;
|
||||
if(lineWidth < 1) lineWidth = 1;
|
||||
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStyle(FILL_AND_STROKE);
|
||||
paint.setStrokeWidth(lineWidth);
|
||||
paint.setStrokeJoin(ROUND);
|
||||
|
||||
var rx = hhWidth*sideLen/400;
|
||||
hPath = new Path();
|
||||
hPath.moveTo(rx, 0);
|
||||
hPath.lineTo(0, hhLen*sideLen/-200);
|
||||
hPath.lineTo(-rx, 0);
|
||||
hPath.close();
|
||||
|
||||
rx = mhWidth*sideLen/400;
|
||||
mPath = new Path();
|
||||
mPath.moveTo(rx, 0);
|
||||
mPath.lineTo(0, mhLen*sideLen/-200);
|
||||
mPath.lineTo(-rx, 0);
|
||||
mPath.close();
|
||||
rx = shWidth*sideLen/400;
|
||||
sPath = new Path();
|
||||
sPath.moveTo(rx, 0);
|
||||
sPath.lineTo(0, shLen*sideLen/-200);
|
||||
sPath.lineTo(-rx, 0);
|
||||
sPath.close();
|
||||
}
|
||||
void cal() {
|
||||
var time = LocalTime.now(timeZone);
|
||||
sAngle = time.getSecond() * 6;
|
||||
mAngle = time.getMinute() * 6 + sAngle/60;
|
||||
hAngle = time.getHour() * 30 + mAngle/12;
|
||||
}
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if(lastSec==0) {
|
||||
cal();
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
if(img != null) canvas.drawBitmap(img, new Rect(0,0,img.getWidth(), img.getHeight()), new RectF(0,0, getWidth(), getHeight()), paint);
|
||||
canvas.translate(getWidth()/2, getHeight()/2);
|
||||
|
||||
paint.setColor(pinHourColor);
|
||||
canvas.rotate(hAngle);
|
||||
canvas.drawPath(hPath, paint);
|
||||
|
||||
paint.setColor(pinMinColor);
|
||||
canvas.rotate(mAngle-hAngle);
|
||||
canvas.drawPath(mPath, paint);
|
||||
if(showSecHand) {
|
||||
paint.setColor(pinSecColor);
|
||||
canvas.rotate(sAngle-mAngle);
|
||||
canvas.drawPath(sPath, paint);
|
||||
}
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
long lastSec = 0;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(! isShown()) {
|
||||
lastSec = 0;
|
||||
return;
|
||||
}
|
||||
var sec = System.currentTimeMillis() / 1000;
|
||||
if(sec != lastSec) {
|
||||
lastSec = sec;
|
||||
cal();
|
||||
invalidate();
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
|
||||
public class EleBorder extends View implements Choreographer.FrameCallback {
|
||||
Bitmap img;
|
||||
int[] lens = new int[4];
|
||||
Path[] paths = new Path[4];
|
||||
int[] offs = new int[]{0,0,0,0};
|
||||
byte eff;
|
||||
int interval;
|
||||
|
||||
public EleBorder(String path, String eff, int speed, Context context) {
|
||||
super(context);
|
||||
img = BitmapFactory.decodeFile(path);
|
||||
if(eff.startsWith("ro")) this.eff = 'r';
|
||||
else if(eff.startsWith("bl")) this.eff = 'b';
|
||||
if(this.eff=='r') interval = speed==1 ? 4 : (speed==2 ? 2 : 1);
|
||||
else interval = speed==1 ? 30 : (speed==2 ? 15 : 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
lens[0] = lens[2] = w;
|
||||
lens[1] = lens[3] = h;
|
||||
int bdWidth = img.getHeight();
|
||||
for(int i=0; i<2; i++) {
|
||||
Path path = new Path();
|
||||
path.moveTo(0,0);
|
||||
path.lineTo(lens[i], 0);
|
||||
path.lineTo(lens[i] - bdWidth, bdWidth);
|
||||
path.lineTo(bdWidth, bdWidth);
|
||||
path.close();
|
||||
paths[i] = paths[i+2] = path;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if(eff!='b' || offs[0] <= 0) {
|
||||
int bdWidth = img.getHeight();
|
||||
int bdLen = img.getWidth();
|
||||
offs[1] = (offs[0] + lens[0]-bdWidth)%bdLen;
|
||||
offs[2] = (offs[0] + lens[0]+lens[1]-bdWidth*2)%bdLen;
|
||||
offs[3] = (offs[0] + lens[0]*2+lens[1]-bdWidth*3)%bdLen;
|
||||
for(int ll=0; ll<4; ll++) {
|
||||
canvas.save();
|
||||
canvas.clipPath(paths[ll]);
|
||||
for(int x=-offs[ll]; x<lens[ll]; x+=bdLen) canvas.drawBitmap(img, x, 0, null);
|
||||
canvas.restore();
|
||||
if(ll<3) {
|
||||
canvas.translate(lens[ll], 0);
|
||||
canvas.rotate(90);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(freshCnt==0 && eff!=0) choreographer.postFrameCallback(this);
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
int freshCnt;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(! isShown()) {
|
||||
freshCnt = offs[0] = 0;
|
||||
return;
|
||||
}
|
||||
if(freshCnt < interval) freshCnt++;
|
||||
else {
|
||||
freshCnt = 1;
|
||||
if(eff=='r') {
|
||||
if(offs[0] <= 0) offs[0] = img.getWidth()-1;
|
||||
else offs[0]--;
|
||||
} else offs[0] = offs[0]==0 ? 1 : 0;
|
||||
invalidate();
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.HashMap;
|
||||
|
||||
import gnph.android.LinearBox;
|
||||
import gnph.util.Dates;
|
||||
import gnph.util.JSList;
|
||||
import gnph.util.JSMap;
|
||||
import gnph.util.Sys;
|
||||
|
||||
public class EleDigiClock extends LinearBox implements Choreographer.FrameCallback {
|
||||
|
||||
static final String weeks[] = {"MON","TUE","WED","THU","FRI","SAT","SUN"};
|
||||
HashMap<String, Bitmap> imgs = new HashMap<>();
|
||||
ImageView yearComps[] = {new ImageView(getContext()), new ImageView(getContext()), new ImageView(getContext()), new ImageView(getContext())};
|
||||
ImageView monthComps[] = {new ImageView(getContext()), new ImageView(getContext())};
|
||||
ImageView dayComps[] = {new ImageView(getContext()), new ImageView(getContext())};
|
||||
ImageView weekComp = new ImageView(getContext()), ampmComp = new ImageView(getContext());
|
||||
ImageView hourComps[] = {new ImageView(getContext()), new ImageView(getContext())};
|
||||
ImageView minComps[] = {new ImageView(getContext()), new ImageView(getContext())};
|
||||
ImageView secComps[] = {new ImageView(getContext()), new ImageView(getContext())};
|
||||
|
||||
ZoneId timeZone;
|
||||
String timeptn;
|
||||
boolean multiline, weekly, isSingleMonth;
|
||||
|
||||
public EleDigiClock(String prefix, JSMap json, Context context) {
|
||||
super(context);
|
||||
setGravity(Gravity.CENTER);
|
||||
timeZone = ZoneId.of(json.stnn("timeZone"));
|
||||
var spaceWidth = json.dbl("spaceWidth");
|
||||
JSList<JSMap> pics = json.jslist("arrayPics");
|
||||
for(var pic : pics) imgs.put(pic.stnn("name"), BitmapFactory.decodeFile(prefix+pic.stnn("id")));
|
||||
int dateStyle = json.intg("dateStyle");
|
||||
isSingleMonth = dateStyle==1||dateStyle==2||dateStyle==4||dateStyle==6||dateStyle==8||dateStyle==10||dateStyle==12;
|
||||
var timeSep = imgs.get("maohao");
|
||||
weekly = json.bool("weekly");
|
||||
var hour12 = json.bool("hour12");
|
||||
var AmPm = hour12 ? json.bool("AmPm") : false;
|
||||
timeptn = hour12 ? "hhmmssa" : "HHmmss";
|
||||
var hour = json.bool("hour");
|
||||
var min = json.bool("min");
|
||||
var sec = json.bool("sec");
|
||||
multiline = json.bool("multiline");
|
||||
addStretch();
|
||||
if(multiline) {
|
||||
vertical();
|
||||
var hBox = new LinearBox(this).horizontal();
|
||||
hBox.addStretch();
|
||||
addDate(dateStyle, json, hBox);
|
||||
hBox.addStretch();
|
||||
if(weekly) {
|
||||
hBox = new LinearBox(this).horizontal();
|
||||
hBox.addStretch();
|
||||
hBox.addView(weekComp);
|
||||
hBox.addStretch();
|
||||
}
|
||||
hBox = new LinearBox(this).horizontal();
|
||||
hBox.addStretch();
|
||||
if(AmPm) {
|
||||
hBox.addView(ampmComp);
|
||||
hBox.addSpacing((int)spaceWidth);
|
||||
}
|
||||
if(hour) {
|
||||
hBox.addView(hourComps[0]);
|
||||
hBox.addView(hourComps[1]);
|
||||
}
|
||||
if(hour&&min) hBox.addView(newImgView(timeSep));
|
||||
if(min) {
|
||||
hBox.addView(minComps[0]);
|
||||
hBox.addView(minComps[1]);
|
||||
}
|
||||
if(min&&sec) hBox.addView(newImgView(timeSep));
|
||||
if(sec) {
|
||||
hBox.addView(secComps[0]);
|
||||
hBox.addView(secComps[1]);
|
||||
}
|
||||
hBox.addStretch();
|
||||
} else {
|
||||
setOrientation(HORIZONTAL);
|
||||
addDate(dateStyle, json, this);
|
||||
if(getChildCount()>1) addSpacing((int)spaceWidth*2);
|
||||
if(weekly) {
|
||||
addView(weekComp);
|
||||
addSpacing((int)spaceWidth*2);
|
||||
}
|
||||
if(AmPm) {
|
||||
addView(ampmComp);
|
||||
addSpacing((int)spaceWidth);
|
||||
}
|
||||
if(hour) {
|
||||
addView(hourComps[0]);
|
||||
addView(hourComps[1]);
|
||||
}
|
||||
if(hour&&min) addView(newImgView(timeSep));
|
||||
if(min) {
|
||||
addView(minComps[0]);
|
||||
addView(minComps[1]);
|
||||
}
|
||||
if(min&&sec) addView(newImgView(timeSep));
|
||||
if(sec) {
|
||||
addView(secComps[0]);
|
||||
addView(secComps[1]);
|
||||
}
|
||||
}
|
||||
addStretch();
|
||||
}
|
||||
|
||||
ImageView newImgView(Bitmap img) {
|
||||
var imgv = new ImageView(getContext());
|
||||
imgv.setImageBitmap(img);
|
||||
return imgv;
|
||||
}
|
||||
void addDate(int dateStyle, JSMap layer, LinearLayout tar) {
|
||||
if(dateStyle==0 || dateStyle==1) {
|
||||
addYear(layer, tar, imgs.get("YEAR"));
|
||||
if(layer.bool("month")) {
|
||||
tar.addView(monthComps[0]);
|
||||
tar.addView(monthComps[1]);
|
||||
tar.addView(newImgView(imgs.get("MONTH")));
|
||||
}
|
||||
if(layer.bool("day")) {
|
||||
tar.addView(dayComps[0]);
|
||||
tar.addView(dayComps[1]);
|
||||
tar.addView(newImgView(imgs.get("DAY")));
|
||||
}
|
||||
} else if(dateStyle==2 || dateStyle==3) {
|
||||
var sep = imgs.get("xiegang");
|
||||
if(layer.bool("month")) {
|
||||
tar.addView(monthComps[0]);
|
||||
tar.addView(monthComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
if(layer.bool("day")) {
|
||||
tar.addView(dayComps[0]);
|
||||
tar.addView(dayComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
addYear(layer, tar, null);
|
||||
} else if(dateStyle==4 || dateStyle==5) {
|
||||
var sep = imgs.get("xiegang");
|
||||
if(layer.bool("day")) {
|
||||
tar.addView(dayComps[0]);
|
||||
tar.addView(dayComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
if(layer.bool("month")) {
|
||||
tar.addView(monthComps[0]);
|
||||
tar.addView(monthComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
addYear(layer, tar, null);
|
||||
} else if(dateStyle==6 || dateStyle==7) {
|
||||
var sep = imgs.get("xiegang");
|
||||
addYear(layer, tar, sep);
|
||||
if(layer.bool("month")) {
|
||||
tar.addView(monthComps[0]);
|
||||
tar.addView(monthComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
if(layer.bool("day")) {
|
||||
tar.addView(dayComps[0]);
|
||||
tar.addView(dayComps[1]);
|
||||
}
|
||||
} else if(dateStyle==8 || dateStyle==9) {
|
||||
var sep = imgs.get("hengxian");
|
||||
if(layer.bool("month")) {
|
||||
tar.addView(monthComps[0]);
|
||||
tar.addView(monthComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
if(layer.bool("day")) {
|
||||
tar.addView(dayComps[0]);
|
||||
tar.addView(dayComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
addYear(layer, tar, null);
|
||||
} else if(dateStyle==10 || dateStyle==11) {
|
||||
var sep = imgs.get("hengxian");
|
||||
if(layer.bool("day")) {
|
||||
tar.addView(dayComps[0]);
|
||||
tar.addView(dayComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
if(layer.bool("month")) {
|
||||
tar.addView(monthComps[0]);
|
||||
tar.addView(monthComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
addYear(layer, tar, null);
|
||||
} else if(dateStyle==12 || dateStyle==13) {
|
||||
var sep = imgs.get("hengxian");
|
||||
addYear(layer, tar, sep);
|
||||
if(layer.bool("month")) {
|
||||
tar.addView(monthComps[0]);
|
||||
tar.addView(monthComps[1]);
|
||||
tar.addView(newImgView(sep));
|
||||
}
|
||||
if(layer.bool("day")) {
|
||||
tar.addView(dayComps[0]);
|
||||
tar.addView(dayComps[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addYear(JSMap layer, LinearLayout tar, Bitmap sep) {
|
||||
if(layer.bool("year")) {
|
||||
if(layer.bool("fullYear")) {
|
||||
tar.addView(yearComps[0]);
|
||||
tar.addView(yearComps[1]);
|
||||
}
|
||||
tar.addView(yearComps[2]);
|
||||
tar.addView(yearComps[3]);
|
||||
if(sep != null) tar.addView(newImgView(sep));
|
||||
}
|
||||
}
|
||||
|
||||
void cal() {
|
||||
var dt = LocalDateTime.now(timeZone);
|
||||
var time = dt.toLocalTime();
|
||||
var hms = Dates.fmt(time, timeptn);
|
||||
ampmComp.setImageBitmap(imgs.get(time.getHour()<12?"AM":"PM"));
|
||||
hourComps[0].setImageBitmap(imgs.get(hms.substring(0,1)));
|
||||
hourComps[1].setImageBitmap(imgs.get(hms.substring(1,2)));
|
||||
minComps[0].setImageBitmap(imgs.get(hms.substring(2,3)));
|
||||
minComps[1].setImageBitmap(imgs.get(hms.substring(3,4)));
|
||||
secComps[0].setImageBitmap(imgs.get(hms.substring(4,5)));
|
||||
secComps[1].setImageBitmap(imgs.get(hms.substring(5,6)));
|
||||
if(yearComps[0].getDrawable()==null || (time.getHour()==0 && time.getSecond()==0)) {
|
||||
var date = dt.toLocalDate();
|
||||
if(weekly) weekComp.setImageBitmap(imgs.get(weeks[date.getDayOfWeek().ordinal()]));
|
||||
var ymd = Dates.fmt(date, "yyyyMMdd");
|
||||
yearComps[0].setImageBitmap(imgs.get(ymd.substring(0,1)));
|
||||
yearComps[1].setImageBitmap(imgs.get(ymd.substring(1,2)));
|
||||
yearComps[2].setImageBitmap(imgs.get(ymd.substring(2,3)));
|
||||
yearComps[3].setImageBitmap(imgs.get(ymd.substring(3,4)));
|
||||
monthComps[0].setImageBitmap(isSingleMonth && ymd.charAt(4)=='0' ? null : imgs.get(ymd.substring(4,5)));
|
||||
monthComps[1].setImageBitmap(imgs.get(ymd.substring(5,6)));
|
||||
dayComps[0].setImageBitmap(isSingleMonth && ymd.charAt(6)=='0' ? null : imgs.get(ymd.substring(6,7)));
|
||||
dayComps[1].setImageBitmap(imgs.get(ymd.substring(7,8)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onVisibilityChanged(View changedView, int visibility) {
|
||||
super.onVisibilityChanged(changedView, visibility);
|
||||
if(visibility==View.VISIBLE) {
|
||||
if(lastSec==0) {
|
||||
cal();
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
long lastSec = 0;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(! isShown()) {
|
||||
lastSec = 0;
|
||||
return;
|
||||
}
|
||||
var sec = System.currentTimeMillis() / 1000;
|
||||
if(sec != lastSec) {
|
||||
lastSec = sec;
|
||||
cal();
|
||||
invalidate();
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import gnph.util.JSList;
|
||||
import gnph.util.JSMap;
|
||||
import gnph.util.NumFmts;
|
||||
import gnph.util.Sys;
|
||||
|
||||
public class EleEnviron extends View implements Choreographer.FrameCallback {
|
||||
class Item {
|
||||
String key;
|
||||
Bitmap lable;
|
||||
ArrayList<Bitmap> nums = new ArrayList<>();
|
||||
Bitmap unit;
|
||||
|
||||
public Item(String key, Bitmap lable, Bitmap unit) {
|
||||
this.key = key;
|
||||
this.lable = lable;
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
static String directs[] = {"NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW", "N"};
|
||||
HashMap<String, Bitmap> imgMap = new HashMap<>();
|
||||
Bitmap title;
|
||||
ArrayList<Item> items = new ArrayList<>();
|
||||
MainActivity act;
|
||||
int spaceWidth;
|
||||
int interval, cur, end, step;
|
||||
boolean isScroll, isFirst = true;
|
||||
|
||||
public EleEnviron(String prefix, JSMap json, Context context) {
|
||||
super(context);
|
||||
act = (MainActivity) context;
|
||||
spaceWidth = json.intg("spaceWidth");
|
||||
isScroll = json.bool("bSingleScroll");
|
||||
try {
|
||||
setBackgroundColor(Color.parseColor(json.stnn("backColor")));
|
||||
} catch (Exception ignored) {}
|
||||
var values = json.jsmap("values");
|
||||
JSList<JSMap> arrayPics = json.jslist("arrayPics");
|
||||
if(values!=null) {
|
||||
var entrys = values.entrySet();
|
||||
for(var entry : entrys) imgMap.put(entry.getKey(), BitmapFactory.decodeFile(prefix+entry.getValue()));
|
||||
JSList<JSMap> jitems = json.jslist("items");
|
||||
for(var jitem : jitems) {
|
||||
var unit = jitem.str("unit");
|
||||
items.add(new Item(jitem.str("name"), BitmapFactory.decodeFile(prefix+jitem.stnn("label")), unit==null ? null : BitmapFactory.decodeFile(prefix+unit)));
|
||||
}
|
||||
} else {
|
||||
for(var img : arrayPics) imgMap.put(img.str("name"), BitmapFactory.decodeFile(prefix+img.stnn("id")));
|
||||
imgMap.put("-", imgMap.remove("minus_sign"));
|
||||
title = imgMap.get("labeltitle");
|
||||
if(json.bool("bTemperature")) items.add(new Item("temperature", imgMap.remove("labeltemperature"), imgMap.remove("unit_celsius")));
|
||||
if(json.bool("bHumidity")) items.add(new Item("humidity", imgMap.remove("labelhumidity"), imgMap.remove("unit_humidity")));
|
||||
if(json.bool("bNoise")) items.add(new Item("noise", imgMap.remove("labelnoise"), imgMap.remove("unit_noise")));
|
||||
if(json.bool("bWindSpeed")) items.add(new Item("windSpeed", imgMap.remove("labelwindSpeed"), imgMap.remove("unit_windspeed")));
|
||||
if(json.bool("bWindDirection")) items.add(new Item("windDirection", imgMap.remove("labelwindDirection"), null));
|
||||
if(json.bool("bPM25")) items.add(new Item("pm2.5", imgMap.remove("labelpm25"), imgMap.get("unit_pm10")));
|
||||
if(json.bool("bPM10")) items.add(new Item("pm10", imgMap.remove("labelpm10"), imgMap.get("unit_pm10")));
|
||||
}
|
||||
var scrollSpeed = json.dbl("scrollSpeed");
|
||||
if(scrollSpeed==0) {
|
||||
var scrollDur = json.dbl("iScrollSpeed");
|
||||
if(scrollDur==0) return;
|
||||
scrollSpeed = 1000 / scrollDur;
|
||||
}
|
||||
interval = step = 1;
|
||||
if(scrollSpeed > 60) step = (int) Math.round(scrollSpeed/60);
|
||||
else if(scrollSpeed < 60) interval = (int) Math.round(60/scrollSpeed);
|
||||
}
|
||||
|
||||
public static Method method;
|
||||
static {
|
||||
try {
|
||||
method = Intent.class.getMethod("getExtra", String.class, Object.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void onReceive(Intent intent) {
|
||||
try {
|
||||
for(var item : items) {
|
||||
item.nums.clear();
|
||||
if(item.unit==null) {
|
||||
var num = intent.getIntExtra(item.key, -1);
|
||||
if(num>=0 && num<=15) item.nums.add(imgMap.get(directs[num]));
|
||||
else {
|
||||
var img = imgMap.get("-");
|
||||
item.nums.add(img);
|
||||
item.nums.add(img);
|
||||
}
|
||||
} else {
|
||||
var num = ((Number) method.invoke(intent, item.key, -999)).doubleValue();
|
||||
var str = num==-999 || (num==-1 && ! item.key.endsWith("rature")) ? "--" : NumFmts.zz().format(num);
|
||||
for(int cc=0; cc<str.length(); cc++) item.nums.add(imgMap.get(str.substring(cc, cc+1)));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if(isFirst) {
|
||||
isFirst = false;
|
||||
onReceive(act.environIntent);
|
||||
act.environs.add(this);
|
||||
}
|
||||
if(isScroll) {
|
||||
var x = cur;
|
||||
var cycCnt = cur==0 ? 1 : 2;
|
||||
for(int ccc=0; ccc<cycCnt; ccc++) {
|
||||
if(title!=null) {
|
||||
canvas.drawBitmap(title, x, Math.round((getHeight() - title.getHeight()) / 2), null);
|
||||
x += title.getWidth() + spaceWidth<<1;
|
||||
}
|
||||
for(var item : items) {
|
||||
var y = (int) Math.round((getHeight() - item.lable.getHeight()) / 2);
|
||||
canvas.drawBitmap(item.lable, x, y, null);
|
||||
x += item.lable.getWidth();
|
||||
for(var num : item.nums) {
|
||||
canvas.drawBitmap(num, x, y, null);
|
||||
x += num.getWidth();
|
||||
}
|
||||
if(item.unit!=null) {
|
||||
canvas.drawBitmap(item.unit, x, y, null);
|
||||
x += item.unit.getWidth();
|
||||
}
|
||||
x += spaceWidth<<1;
|
||||
}
|
||||
if(ccc==0) end = -(x-cur-step);
|
||||
}
|
||||
if(freshCnt==0 && interval!=0) choreographer.postFrameCallback(this);
|
||||
} else {
|
||||
var itemH = (double) getHeight() / (title!=null ? items.size()+1 : items.size());
|
||||
int i = 0;
|
||||
if(title!=null) canvas.drawBitmap(title, 0, Math.round(itemH * i++ + (itemH - title.getHeight()) / 2), null);
|
||||
for(var item : items) {
|
||||
var y = (int) Math.round(itemH * i++ + (itemH - item.lable.getHeight()) / 2);
|
||||
canvas.drawBitmap(item.lable, 0, y, null);
|
||||
var x = item.lable.getWidth();
|
||||
for(var num : item.nums) {
|
||||
canvas.drawBitmap(num, x, y, null);
|
||||
x += num.getWidth();
|
||||
}
|
||||
if(item.unit!=null) canvas.drawBitmap(item.unit, x, y, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVisibilityAggregated(boolean isVisible) {
|
||||
super.onVisibilityAggregated(isVisible);
|
||||
if(! isVisible) {
|
||||
act.environs.remove(this);
|
||||
isFirst = true;
|
||||
}
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
int freshCnt;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(! isShown()) {
|
||||
freshCnt = cur = 0;
|
||||
return;
|
||||
}
|
||||
if(freshCnt < interval) freshCnt++;
|
||||
else {
|
||||
freshCnt = 1;
|
||||
if(cur <= end) cur -= end;
|
||||
else cur -= step;
|
||||
invalidate();
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
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 java.util.Random;
|
||||
|
||||
import gnph.util.JSList;
|
||||
import gnph.util.JSMap;
|
||||
|
||||
public class EleFlip extends View implements Choreographer.FrameCallback {
|
||||
|
||||
static final char effTypes[] = {'l', 't', 'r', 'b'};
|
||||
Random rand = new Random();
|
||||
ArrayList<Bitmap> imgs = new ArrayList<>();
|
||||
int picDur, EffDur, AniInterval, step, imgc, imgx, imgy;
|
||||
char effType;
|
||||
boolean needRand = false;
|
||||
|
||||
public EleFlip(String dirPre, JSList<JSMap> maps, Context context) {
|
||||
super(context);
|
||||
var map = maps.get(0);
|
||||
picDur = map.intg("picDuration")*60;
|
||||
if(picDur==0) return;
|
||||
EffDur = map.intg("effectSpeed")*60;
|
||||
for(var amap : maps) imgs.add(BitmapFactory.decodeFile(dirPre+amap.stnn("id")));
|
||||
var effStr = map.str("effect");
|
||||
if(effStr == null || effStr.equals("no")) EffDur = 0;
|
||||
else if(effStr.endsWith("left")) effType = 'l';
|
||||
else if(effStr.endsWith("top")) effType = 't';
|
||||
else if(effStr.endsWith("right")) effType = 'r';
|
||||
else if(effStr.endsWith("bottom")) effType = 'b';
|
||||
else if(effStr.equals("random")) needRand = true;
|
||||
else EffDur = 0;
|
||||
}
|
||||
|
||||
void startMove() {
|
||||
if(EffDur==0) return;
|
||||
if(needRand) effType = effTypes[rand.nextInt(4)];
|
||||
double effDurD = EffDur;
|
||||
if(effType=='l') {
|
||||
imgx = getWidth();
|
||||
imgy = 0;
|
||||
effDurD /= getWidth();
|
||||
} else if(effType=='r') {
|
||||
imgx = -getWidth();
|
||||
imgy = 0;
|
||||
effDurD /= getWidth();
|
||||
} else if(effType=='t') {
|
||||
imgx = 0;
|
||||
imgy = getHeight();
|
||||
effDurD /= getHeight();
|
||||
} else if(effType=='b') {
|
||||
imgx = 0;
|
||||
imgy = -getHeight();
|
||||
effDurD /= getHeight();
|
||||
} else return;
|
||||
AniInterval = (int) Math.round(effDurD);
|
||||
if(AniInterval < 1) AniInterval = 1;
|
||||
step = (int) Math.round(AniInterval / effDurD);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if(freshCnt==0 && (EffDur!=0 || imgs.size()>1)) {
|
||||
startMove();
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
canvas.drawBitmap(imgs.get(imgc), imgx, imgy, null);
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
int freshCnt, curDur;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(! isShown()) {
|
||||
freshCnt = curDur = imgc = 0;
|
||||
return;
|
||||
}
|
||||
if(curDur < picDur) {
|
||||
curDur++;
|
||||
if(AniInterval > 0) {
|
||||
if(freshCnt < AniInterval) freshCnt++;
|
||||
else {
|
||||
freshCnt = 1;
|
||||
if(effType=='l') {
|
||||
imgx -= step;
|
||||
if(imgx < 0) imgx = 0;
|
||||
} else if(effType=='t') {
|
||||
imgy -= step;
|
||||
if(imgy < 0) imgy = 0;
|
||||
} else if(effType=='r') {
|
||||
imgx += step;
|
||||
if(imgx > 0) imgx = 0;
|
||||
} else if(effType=='b') {
|
||||
imgy += step;
|
||||
if(imgy > 0) imgy = 0;
|
||||
}
|
||||
if(imgx==0 && imgy==0) AniInterval = 0;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
curDur = 0;
|
||||
freshCnt = 1;
|
||||
if(imgc >= imgs.size()-1) imgc = 0;
|
||||
else imgc++;
|
||||
startMove();
|
||||
invalidate();
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
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 android.view.ViewGroup;
|
||||
|
||||
import gnph.util.JSMap;
|
||||
|
||||
public class EleScroll extends View implements Choreographer.FrameCallback {
|
||||
|
||||
Bitmap img;
|
||||
int interval, cur, end, step;
|
||||
char effect;
|
||||
|
||||
public EleScroll(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;
|
||||
}
|
||||
interval = step = 1;
|
||||
if(scrollSpeed > 60) step = (int) Math.round(scrollSpeed/60);
|
||||
else if(scrollSpeed < 60) interval = (int) Math.round(60/scrollSpeed);
|
||||
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 {
|
||||
if(effect=='l') {
|
||||
canvas.drawBitmap(img, cur, 0, null);
|
||||
canvas.drawBitmap(img, cur+img.getWidth(), 0, null);
|
||||
} else if(effect=='r') {
|
||||
canvas.drawBitmap(img, cur, 0, null);
|
||||
canvas.drawBitmap(img, cur-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);
|
||||
if(freshCnt==0 && effect!=0 && interval!=0) choreographer.postFrameCallback(this);
|
||||
} catch (RuntimeException e) {
|
||||
((Page) getParent()).remove(this);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
int freshCnt;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(! isShown()) {
|
||||
freshCnt = cur = 0;
|
||||
return;
|
||||
}
|
||||
if(freshCnt < interval) freshCnt++;
|
||||
else {
|
||||
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();
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import gnph.util.Dates;
|
||||
import gnph.util.JSList;
|
||||
import gnph.util.JSMap;
|
||||
import gnph.util.NumFmts;
|
||||
|
||||
public class EleTimer extends View implements Choreographer.FrameCallback {
|
||||
|
||||
HashMap<String, Bitmap> imgMap = new HashMap<>();
|
||||
ArrayList<Bitmap> imgs = new ArrayList<>();
|
||||
Bitmap text, day, hour, min, sec;
|
||||
int spaceWidth, len;
|
||||
Paint paint = new Paint();
|
||||
long targetTime;
|
||||
boolean isDown;
|
||||
boolean isMultiline;
|
||||
boolean hasDay;
|
||||
boolean hasHour;
|
||||
boolean hasMin;
|
||||
boolean hasSec;
|
||||
|
||||
public EleTimer(String prefix, JSMap json, Context context) {
|
||||
super(context);
|
||||
var imgEntrys = json.jsmap("imgs").entrySet();
|
||||
for(var imgEntry : imgEntrys) imgMap.put(imgEntry.getKey(), BitmapFactory.decodeFile(prefix+imgEntry.getValue()));
|
||||
text = imgMap.get("text");
|
||||
day = imgMap.get("day");
|
||||
hour = imgMap.get("hour");
|
||||
min = imgMap.get("min");
|
||||
sec = imgMap.get("sec");
|
||||
spaceWidth = (int) Math.round(json.dbl("spaceWidth"));
|
||||
isDown = json.bool("isDown");
|
||||
targetTime = Dates.milli(json.stnn("targetTime")) / 1000;
|
||||
hasDay = json.bool("hasDay");
|
||||
hasHour = json.bool("hasHour");
|
||||
hasMin = json.bool("hasMin");
|
||||
hasSec = json.bool("hasSec");
|
||||
isMultiline = json.bool("isMultiline");
|
||||
paint.setTextAlign(Paint.Align.CENTER);
|
||||
try {
|
||||
setBackgroundColor(Color.parseColor(json.stnn("backColor")));
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
void cal() {
|
||||
var cur = System.currentTimeMillis() / 1000;
|
||||
var secs = isDown ? targetTime - cur : cur - targetTime;
|
||||
if(secs < 0) secs = 0;
|
||||
len = 0;
|
||||
imgs.clear();
|
||||
if(text!=null && ! isMultiline) {
|
||||
imgs.add(text);
|
||||
imgs.add(null);
|
||||
len += text.getWidth();
|
||||
len += spaceWidth;
|
||||
}
|
||||
if(hasDay) {
|
||||
var str = Long.toString(secs/86400);
|
||||
for(int cc=0; cc<str.length(); cc++) {
|
||||
var img = imgMap.get(str.substring(cc, cc+1));
|
||||
imgs.add(img);
|
||||
len += img.getWidth();
|
||||
}
|
||||
imgs.add(null);
|
||||
imgs.add(day);
|
||||
imgs.add(null);
|
||||
len += day.getWidth();
|
||||
len += spaceWidth * 2;
|
||||
secs %= 86400;
|
||||
}
|
||||
if(hasHour) {
|
||||
var str = NumFmts.zz().format(secs/3600);
|
||||
for(int cc=0; cc<str.length(); cc++) {
|
||||
var img = imgMap.get(str.substring(cc, cc+1));
|
||||
imgs.add(img);
|
||||
len += img.getWidth();
|
||||
}
|
||||
imgs.add(hour);
|
||||
imgs.add(null);
|
||||
len += hour.getWidth();
|
||||
len += spaceWidth;
|
||||
secs %= 3600;
|
||||
}
|
||||
if(hasMin) {
|
||||
var str = NumFmts.zz().format(secs/60);
|
||||
for(int cc=0; cc<str.length(); cc++) {
|
||||
var img = imgMap.get(str.substring(cc, cc+1));
|
||||
imgs.add(img);
|
||||
len += img.getWidth();
|
||||
}
|
||||
imgs.add(min);
|
||||
imgs.add(null);
|
||||
len += min.getWidth();
|
||||
len += spaceWidth;
|
||||
secs %= 60;
|
||||
}
|
||||
if(hasSec) {
|
||||
var str = NumFmts.zz().format(secs);
|
||||
for(int cc=0; cc<str.length(); cc++) {
|
||||
var img = imgMap.get(str.substring(cc, cc+1));
|
||||
imgs.add(img);
|
||||
len += img.getWidth();
|
||||
}
|
||||
imgs.add(sec);
|
||||
imgs.add(null);
|
||||
len += sec.getWidth();
|
||||
len += spaceWidth;
|
||||
}
|
||||
imgs.remove(imgs.size()-1);
|
||||
len -= spaceWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if(lastSec==0) {
|
||||
cal();
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
int x = (getWidth()-len) / 2, y;
|
||||
if(text!=null && isMultiline) {
|
||||
y = getHeight() / 2;
|
||||
canvas.drawBitmap(text, (getWidth()-text.getWidth()) / 2, y-text.getHeight(), null);
|
||||
} else y = (getHeight() - imgs.get(0).getHeight()) / 2;
|
||||
for(var img : imgs) {
|
||||
if(img==null) x += spaceWidth;
|
||||
else {
|
||||
canvas.drawBitmap(img, x, y, null);
|
||||
x += img.getWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
long lastSec = 0;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(! isShown()) {
|
||||
lastSec = 0;
|
||||
return;
|
||||
}
|
||||
var sec = frameTimeNanos / 1000000000;
|
||||
if(sec != lastSec) {
|
||||
lastSec = sec;
|
||||
cal();
|
||||
invalidate();
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.view.Choreographer;
|
||||
import android.view.View;
|
||||
|
||||
import gnph.util.Dates;
|
||||
import gnph.util.JSMap;
|
||||
import gnph.util.NumFmts;
|
||||
|
||||
public class EleTimer2 extends View implements Choreographer.FrameCallback {
|
||||
|
||||
Paint paint = new Paint();
|
||||
long targetTime;
|
||||
String title, text;
|
||||
int x, y;
|
||||
boolean isDown;
|
||||
boolean isMultiline;
|
||||
boolean hasDay;
|
||||
boolean hasHour;
|
||||
boolean hasMin;
|
||||
boolean hasSec;
|
||||
|
||||
public EleTimer2(JSMap json, Context context) {
|
||||
super(context);
|
||||
isDown = json.bool("isDown");
|
||||
targetTime = Dates.milli(json.stnn("targetTime")) / 1000;
|
||||
hasDay = json.bool("hasDay");
|
||||
hasHour = json.bool("hasHour");
|
||||
hasMin = json.bool("hasMin");
|
||||
hasSec = json.bool("hasSec");
|
||||
title = json.stnn("text");
|
||||
isMultiline = json.bool("isMultiline");
|
||||
int style = 0;
|
||||
if(json.bool("fontBold")) style |= 1;
|
||||
if(json.bool("fontItalic")) style |= 2;
|
||||
@SuppressLint("WrongConstant") var font = Typeface.create(json.stnn("font"), style);
|
||||
paint.setTypeface(font);
|
||||
paint.setTextSize(json.intg("fontSize"));
|
||||
paint.setUnderlineText(json.bool("fontUnderline"));
|
||||
paint.setColor(Color.parseColor(json.stnn("textColor")));
|
||||
paint.setTextAlign(Paint.Align.CENTER);
|
||||
try {
|
||||
setBackgroundColor(Color.parseColor(json.stnn("backColor")));
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
x = getWidth() / 2;
|
||||
var fontMetrics = paint.getFontMetrics();
|
||||
y = (int) (getHeight() - fontMetrics.top - fontMetrics.bottom) / 2;
|
||||
}
|
||||
|
||||
void cal() {
|
||||
var cur = System.currentTimeMillis() / 1000;
|
||||
var secs = isDown ? targetTime - cur : cur - targetTime;
|
||||
if(secs < 0) secs = 0;
|
||||
var buf = new StringBuilder(title);
|
||||
if(buf.length() != 0) buf.append(isMultiline ? '\n' : ' ');
|
||||
if(hasDay) {
|
||||
buf.append(secs/86400).append(" ").append("day").append(" ");
|
||||
secs %= 86400;
|
||||
}
|
||||
if(hasHour) {
|
||||
buf.append(NumFmts.zz().format(secs/3600)).append("hour").append(" ");
|
||||
secs %= 3600;
|
||||
}
|
||||
if(hasMin) {
|
||||
buf.append(NumFmts.zz().format(secs/60)).append("min").append(" ");
|
||||
secs %= 60;
|
||||
}
|
||||
if(hasSec) buf.append(NumFmts.zz().format(secs)).append("sec").append(" ");
|
||||
text = buf.toString().trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if(lastSec==0) {
|
||||
cal();
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
canvas.drawText(text, x, y, paint);
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
long lastSec = 0;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(! isShown()) {
|
||||
lastSec = 0;
|
||||
return;
|
||||
}
|
||||
var sec = frameTimeNanos / 1000000000;
|
||||
if(sec != lastSec) {
|
||||
lastSec = sec;
|
||||
cal();
|
||||
invalidate();
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
import android.widget.VideoView;
|
||||
|
||||
public class EleVideo extends VideoView {
|
||||
|
||||
float vol = 1;
|
||||
|
||||
public EleVideo(String path, Context context) {
|
||||
super(context);
|
||||
setVideoPath(path);
|
||||
setOnPreparedListener((MediaPlayer player)->{
|
||||
if(! isShown()) {
|
||||
player.pause();
|
||||
player.seekTo(0);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@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) {
|
||||
if(! isPlaying()) start();
|
||||
} else {
|
||||
pause();
|
||||
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+")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,413 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.StatFs;
|
||||
import android.view.Choreographer;
|
||||
|
||||
import androidx.activity.ComponentActivity;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.xixun.joey.aidlset.CardService;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import gnph.util.IOs;
|
||||
import gnph.util.JSList;
|
||||
import gnph.util.JSMap;
|
||||
import gnph.util.O;
|
||||
|
||||
public class MainActivity extends ComponentActivity implements Choreographer.FrameCallback {
|
||||
|
||||
public static MainActivity ins;
|
||||
public Intent environIntent = new Intent();
|
||||
HashSet<EleEnviron> environs = new HashSet<>();
|
||||
BackView backView;
|
||||
ProgView progView;
|
||||
int state;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.R)
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
System.out.println("---- MainActivity onCreate ---- UI Thread: "+Thread.currentThread().getId());
|
||||
ins = this;
|
||||
if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) init();
|
||||
else {
|
||||
System.out.println("---- No permission, Try again ...");
|
||||
ActivityCompat.requestPermissions(this, new String[]{
|
||||
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
android.Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
android.Manifest.permission.MANAGE_EXTERNAL_STORAGE,
|
||||
android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
|
||||
android.Manifest.permission.INTERNET
|
||||
}, 999);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if(requestCode==999 && grantResults!=null && grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED && backView==null) init();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
Util.programDir = Environment.getExternalStorageDirectory() + "/XixunPlayer/program";
|
||||
Util.backImgFile = Environment.getExternalStorageDirectory() + "/XixunPlayer/background";
|
||||
|
||||
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 conn = new ServiceConnection() {
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
System.out.println("Disconnected cardsystem aidl service");
|
||||
}
|
||||
|
||||
public void onServiceConnected(ComponentName name, IBinder iBinder) {
|
||||
System.out.println("Bind cardsystem aidl service success");
|
||||
var service = CardService.Stub.asInterface(iBinder);
|
||||
try {
|
||||
backView = new BackView(MainActivity.this, service.getScreenWidth(), service.getScreenHeight());
|
||||
state = 5;
|
||||
initProg();
|
||||
if(progView==null) setContentView(backView);
|
||||
} catch (RemoteException e) {
|
||||
Util.makeText(MainActivity.this, e.getMessage()).show();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
var intent = new Intent("com.xixun.joey.aidlset.SettingsService");
|
||||
intent.setPackage("com.xixun.joey.cardsystem");
|
||||
bindService(intent, conn, Context.BIND_AUTO_CREATE);
|
||||
|
||||
registerReceiver(new BroadcastReceiver(){
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
System.out.println("Receive PAUSE_PLAYER");
|
||||
if(intent.getBooleanExtra("pause", false)) {
|
||||
state = 8;
|
||||
if(progView!=null) {
|
||||
progView.setVisibility(GONE);
|
||||
progView = null;
|
||||
setContentView(backView);
|
||||
}
|
||||
} else if(progView==null) initProg();
|
||||
}
|
||||
}, new IntentFilter("com.xixun.action.PAUSE_PLAYER"), RECEIVER_EXPORTED);
|
||||
|
||||
// registerReceiver(new BroadcastReceiver(){
|
||||
// @Override
|
||||
// public void onReceive(Context context, Intent intent) {
|
||||
// }
|
||||
// }, new IntentFilter("com.xixun.joey.CHANGE_COMPANYID"), RECEIVER_EXPORTED);
|
||||
|
||||
registerReceiver(new BroadcastReceiver(){
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
MainActivity.this.environIntent = intent;
|
||||
for(var environ : environs) {
|
||||
environ.onReceive(intent);
|
||||
environ.invalidate();
|
||||
}
|
||||
}
|
||||
}, 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;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
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.getMessage()).show();
|
||||
});
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public boolean delProgFile() {
|
||||
if(progView!=null) {
|
||||
progView.setVisibility(GONE);
|
||||
progView = null;
|
||||
setContentView(backView);
|
||||
}
|
||||
var files = new File(Util.programDir).listFiles();
|
||||
var ok = true;
|
||||
if(files != null) for(var file : files) if(! file.delete()) ok = false;
|
||||
state = 4;
|
||||
try {
|
||||
var out = new FileOutputStream(Util.programDir+"/program");
|
||||
out.write("{}".getBytes());
|
||||
out.flush();
|
||||
out.getFD().sync();
|
||||
out.close();
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
public void initProg() {
|
||||
try {
|
||||
var task = JSMap.fromClose(new BufferedInputStream(new FileInputStream(Util.programDir + "/program"))).jsmap("task");
|
||||
if(task==null) {
|
||||
state = 3;
|
||||
return;
|
||||
}
|
||||
var view = new ProgView(task, backView.width, backView.height, this);
|
||||
if(view.getChildCount()==0) {
|
||||
state = 3;
|
||||
return;
|
||||
}
|
||||
if(progView!=null) progView.setVisibility(GONE);
|
||||
progView = view;
|
||||
setContentView(progView);
|
||||
syncProg((System.currentTimeMillis()+999)/1000*1000);
|
||||
choreographer.postFrameCallback(this);
|
||||
} catch (FileNotFoundException e) {
|
||||
state = 3;
|
||||
e.printStackTrace();
|
||||
} catch (Throwable e) {
|
||||
state = 7;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Choreographer choreographer = Choreographer.getInstance();
|
||||
ArrayList<Integer> avas = new ArrayList<>();
|
||||
int curAva, curTimes = 1;
|
||||
long syncMilli = Long.MAX_VALUE;
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
if(progView == null) return;
|
||||
var milli = System.currentTimeMillis();
|
||||
var lastPage = page(curAva);
|
||||
if(milli >= syncMilli) {
|
||||
lastPage.setVisibility(GONE);
|
||||
if(lastPage.hasVideo && progView.getChildCount()>1) lastPage.setLeft(lastPage.getRight()+1);
|
||||
syncProg(milli-syncMilli>=1000 ? milli : syncMilli);
|
||||
} else if(milli >= lastPage.endMilli) {
|
||||
lastPage.setVisibility(GONE);
|
||||
if(lastPage.hasVideo && curTimes==lastPage.repeatTimes && progView.getChildCount()>1) lastPage.setLeft(lastPage.getRight()+1);
|
||||
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;
|
||||
}
|
||||
}
|
||||
page(curAva).setMillis(lastPage.endMilli);
|
||||
} else {
|
||||
for(var layer : lastPage.layers) {
|
||||
for(var ele : layer.eles) if(ele.isShort) {
|
||||
if(ele.view.getVisibility()!=VISIBLE) {
|
||||
if(milli < ele.endMilli && milli >= ele.startMilli) ele.view.setVisibility(VISIBLE);
|
||||
} else {
|
||||
if(milli >= ele.endMilli) ele.view.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
if(milli >= layer.endMilli) {
|
||||
layer.endMilli += layer.dur;
|
||||
for(var ele : layer.eles) {
|
||||
ele.endMilli += layer.dur;
|
||||
ele.startMilli += layer.dur;
|
||||
if(ele.view.getVisibility()!=VISIBLE) {
|
||||
if(milli < ele.endMilli && milli >= ele.startMilli) ele.view.setVisibility(VISIBLE);
|
||||
} else {
|
||||
if(milli >= ele.endMilli) ele.view.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
choreographer.postFrameCallback(this);
|
||||
}
|
||||
|
||||
void syncProg(long milli) {
|
||||
curTimes = 1;
|
||||
var dur = calAvas(milli);
|
||||
if(dur==0) {
|
||||
syncMilli = milli + 1000;
|
||||
if(state!=2) {
|
||||
setContentView(backView);
|
||||
state = 2;
|
||||
}
|
||||
} else {
|
||||
var page = page(curAva = 0);
|
||||
syncMilli = milli / dur * dur + dur;
|
||||
if(syncMilli - milli >= 2000) page.setMillis(milli);
|
||||
if(state != 6) {
|
||||
setContentView(progView);
|
||||
state = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
int calAvas(long milli) {
|
||||
avas.clear();
|
||||
var dur = 0;
|
||||
Page page;
|
||||
for(int i=0; i<progView.getChildCount(); i++) if((page = (Page)progView.getChildAt(i)).isSchedule(milli+dur)) {
|
||||
avas.add(i);
|
||||
dur += page.dur * page.repeatTimes;
|
||||
}
|
||||
return dur;
|
||||
}
|
||||
|
||||
Page page(int i) {
|
||||
return (Page) progView.getChildAt(avas.get(i));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.AbsoluteLayout;
|
||||
|
||||
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 extends AbsoluteLayout {
|
||||
|
||||
public static class EleBase {
|
||||
View view;
|
||||
long endMilli = Long.MAX_VALUE;
|
||||
long startMilli = Long.MAX_VALUE;
|
||||
int startTime;
|
||||
int endTime;
|
||||
String id;
|
||||
String type;
|
||||
boolean isShort;
|
||||
}
|
||||
public static class Layer {
|
||||
|
||||
ArrayList<EleBase> eles = new ArrayList<>();
|
||||
long endMilli = Long.MAX_VALUE;
|
||||
int dur;
|
||||
boolean repeat;
|
||||
}
|
||||
|
||||
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;
|
||||
boolean hasVideo = false;
|
||||
|
||||
public Page(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void setMillis(long milli) {
|
||||
endMilli = milli + dur;
|
||||
for(var layer : layers) {
|
||||
if(layer.repeat) layer.endMilli = milli + layer.dur;
|
||||
for(var ele : layer.eles) if(ele.isShort) {
|
||||
if(ele.startTime > 0) {
|
||||
ele.startMilli = milli + ele.startTime;
|
||||
ele.view.setVisibility(GONE);
|
||||
} else ele.view.setVisibility(VISIBLE);
|
||||
ele.endMilli = milli + ele.endTime;
|
||||
}
|
||||
}
|
||||
if(getLeft() != 0) setLeft(0);
|
||||
setVisibility(VISIBLE);
|
||||
}
|
||||
public void remove(View view) {
|
||||
view.setVisibility(GONE);
|
||||
removeView(view);
|
||||
for(int ll=0; ll<layers.size(); ll++) {
|
||||
var layer = layers.get(ll);
|
||||
for(int ee=0; ee<layer.eles.size(); ee++) if(layer.eles.get(ee).view == view) {
|
||||
if(layer.eles.size() > 1) layer.eles.remove(ee);
|
||||
else layers.remove(ll);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.AbsoluteLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import gnph.util.JSList;
|
||||
import gnph.util.JSMap;
|
||||
import pl.droidsonroids.gif.GifImageView;
|
||||
|
||||
public class ProgView extends AbsoluteLayout {
|
||||
|
||||
public ProgView(JSMap task, int width, int height, Context context) {
|
||||
super(context);
|
||||
JSList<JSMap> pages = task.jslist("items");
|
||||
for(var pageMap : pages) {
|
||||
var _program = pageMap.jsmap("_program");
|
||||
JSList<JSMap> layers = _program.jslist("layers");
|
||||
if(layers.isEmpty()) continue;
|
||||
var splitWidths = _program.jslist("splitWidths");
|
||||
var page = new Page(context);
|
||||
page.repeatTimes = pageMap.intg("repeatTimes");
|
||||
page.parse(pageMap.jslist("schedules"));
|
||||
for(int ll=layers.size()-1; ll>=0; ll--) {
|
||||
var layer = new Page.Layer();
|
||||
layer.repeat = layers.get(ll).bool("repeat");
|
||||
JSList<JSMap> sources = layers.get(ll).jslist("sources");
|
||||
var border = layers.get(ll).jsmap("border");
|
||||
EleBorder bdEle = null;
|
||||
int bdWidth = 0, bdStart = 0xffff, bdEnd = 0;
|
||||
if(border!=null) {
|
||||
bdEle = new EleBorder(Util.programDir+"/"+border.stnn("img"), border.stnn("eff"), border.intg("speed"), context);
|
||||
bdWidth = bdEle.img.getHeight();
|
||||
}
|
||||
var ele = new Page.EleBase();
|
||||
int x, y, w, h;
|
||||
for(var source : sources) {
|
||||
ele.type = source.stnn("_type");
|
||||
if(ele.type.isEmpty()) continue;
|
||||
var timeSpan = source.intg("timeSpan")*1000;
|
||||
if(timeSpan==0) continue;
|
||||
x = source.intg("left")+bdWidth;
|
||||
y = source.intg("top")+bdWidth;
|
||||
w = source.intg("width")-bdWidth-bdWidth;
|
||||
h = source.intg("height")-bdWidth-bdWidth;
|
||||
boolean notAudio = ! ele.type.equals("Audio");
|
||||
if((w<=0 || h<=0) && notAudio) continue;
|
||||
ele.startTime = source.intg("playTime")*1000;
|
||||
if(bdStart > ele.startTime) bdStart = ele.startTime;
|
||||
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");
|
||||
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)));
|
||||
imgView.setScaleType(ImageView.ScaleType.FIT_XY);
|
||||
ele.view = imgView;
|
||||
} else if(ele.type.equals("MultiPng")) {
|
||||
JSList<JSMap> imgs = source.jslist("arrayPics");
|
||||
if(imgs.isEmpty()) continue;
|
||||
if(imgs.size()==1 && imgs.get(0).intg("picDuration")==0) ele.view = new EleScroll(Util.programDir+"/", imgs.get(0), context);
|
||||
else ele.view = new EleFlip(Util.programDir+"/", imgs, context);
|
||||
} else if(ele.type.equals("SplitText")) {
|
||||
// JSList<JSMap> imgs = source.jslist("arrayPics");
|
||||
// if(imgs.isEmpty()) continue;
|
||||
// ele.wgt = new View(context);
|
||||
// page.addView(ele.wgt, new AbsoluteLayout.LayoutParams(width, height, 0, 0));
|
||||
// var pheight = _program.intg("height");
|
||||
// if(imgs.size()==1 && imgs.get(0).intg("picDuration")==0) {
|
||||
// var wgt = new EleScroll(ele.wgt, dir+"/", imgs.get(0), context);
|
||||
// wgt->setGeometry(ele.x, ele.y, ele.w, ele.h);
|
||||
// for(int i=1; i<splitWidths.size(); i++) {
|
||||
// ele.x -= splitWidths[i-1].toInt();
|
||||
// ele.y += height;
|
||||
// auto split = new EleSplitScroll(ele.wgt, wgt);
|
||||
// split->setGeometry(ele.x, ele.y, splitWidths[i].toInt()-ele.x, ele.h);
|
||||
// wgt->splits.append(split);
|
||||
// }
|
||||
// } else {
|
||||
// auto wgt = new EleFlip(dir+"/", imgs, ele.wgt);
|
||||
// wgt->setGeometry(ele.x, ele.y, ele.w, ele.h);
|
||||
// for(int i=1; i<splitWidths.size(); i++) {
|
||||
// ele.x -= splitWidths[i-1].toInt();
|
||||
// ele.y += height;
|
||||
// auto split = new EleSplitPng(wgt, ele.wgt);
|
||||
// split->setGeometry(ele.x, ele.y, splitWidths[i].toInt()-ele.x, ele.h);
|
||||
// wgt->splits.append(split);
|
||||
// }
|
||||
// }
|
||||
// ele.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")) {
|
||||
page.hasVideo = true;
|
||||
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("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")) {
|
||||
var webView = new WebView(context);
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
webView.loadUrl(source.stnn("url"));
|
||||
ele.view = webView;
|
||||
}
|
||||
else if(ele.type.equals("Timer")) ele.view = new EleTimer(Util.programDir+"/", source, context);
|
||||
else if(ele.type.equals("EnvironmentalMonitoring")) ele.view = new EleEnviron(Util.programDir+"/", source, context);
|
||||
else continue;
|
||||
if(ele.view==null) continue;
|
||||
if(w>0) page.addView(ele.view, new AbsoluteLayout.LayoutParams(w, h, x, y));
|
||||
layer.eles.add(ele);
|
||||
ele = new Page.EleBase();
|
||||
}
|
||||
if(bdEle!=null && ! sources.isEmpty()) {
|
||||
JSList<Long> geometry = border.jslist("geometry");
|
||||
x = geometry.get(0).intValue();
|
||||
y = geometry.get(1).intValue();
|
||||
w = geometry.get(2).intValue();
|
||||
h = geometry.get(3).intValue();
|
||||
ele.startTime = bdStart;
|
||||
ele.endTime = bdEnd;
|
||||
ele.view = bdEle;
|
||||
page.addView(ele.view, new AbsoluteLayout.LayoutParams(w, h, x, y));
|
||||
layer.eles.add(ele);
|
||||
}
|
||||
if(! layer.eles.isEmpty()) page.layers.add(layer);
|
||||
}
|
||||
if(page.dur==0) continue;
|
||||
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(layer.eles.size() > 1) {
|
||||
layer.eles.remove(ee--);
|
||||
continue;
|
||||
} else {
|
||||
page.layers.remove(ll--);
|
||||
continue for_layer;
|
||||
}
|
||||
} else if(ele.endTime > page.dur) ele.endTime = page.dur;
|
||||
ele.isShort = ele.startTime > 0 || ele.endTime < page.dur;
|
||||
}
|
||||
if(layer.dur > page.dur) layer.dur = page.dur;
|
||||
}
|
||||
page.setVisibility(GONE);
|
||||
addView(page, new AbsoluteLayout.LayoutParams(width, height, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Environment;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.xixun.util.PlayerInfo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
import gnph.util.IOs;
|
||||
import gnph.util.JSMap;
|
||||
import gnph.util.URLConn;
|
||||
|
||||
public class Server extends Service {
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return binder;
|
||||
}
|
||||
|
||||
PlayerInfo.Stub binder = new PlayerInfo.Stub() {
|
||||
@Override
|
||||
public String getProgramName() throws RemoteException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() throws RemoteException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScreenWidth(int w) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScreenHeight(int h) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void taskScreenshot(String cmdId) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExternalTemperature(float t) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInternalTemperature(float t) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHumidity(float h) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forcePlayProgram(String pid) throws RemoteException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean finishForcePlay() throws RemoteException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurProgramId() throws RemoteException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUSBProgramPwd(String pwd) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
@Override
|
||||
public String executeJosnCommand(String jsonstr) throws RemoteException {
|
||||
System.out.println("Server executeJsonCommand ..."+jsonstr);//{"_type":"DeleteTask","id":"652522a0e81d1e000009201a","sendTo":"yzd-player"}
|
||||
String id = null;
|
||||
try {
|
||||
var json = JSMap.from(jsonstr.getBytes(StandardCharsets.UTF_8));
|
||||
var _type = json.stnn("_type");
|
||||
id = json.stnn("id");
|
||||
if(_type.equals("DeleteTask")) {
|
||||
MainActivity.ins.runOnUiThread(() -> MainActivity.ins.delProgFile());
|
||||
return new JSMap(
|
||||
"_type", "DataCallback",
|
||||
"result", "received command",
|
||||
"cardId", Util.getCardId(),
|
||||
"commandId", id
|
||||
).toString();
|
||||
} else if(_type.equals("PlayerStateCommand")) {
|
||||
var descs = Util.getState(MainActivity.ins.state);
|
||||
return new JSMap(
|
||||
"_type", "Success",
|
||||
"cardId", Util.getCardId(),
|
||||
"commandId", id,
|
||||
"code", MainActivity.ins.state,
|
||||
"des_en", descs[0],
|
||||
"des", descs[1]
|
||||
).toString();
|
||||
} else if(_type.equals("SetPlayerBackground")) {
|
||||
var url = json.str("url");
|
||||
if(url==null) new File(Util.backImgFile).delete();
|
||||
else IOs.writeClose(new FileOutputStream(Util.backImgFile), new URLConn(url).in());
|
||||
MainActivity.ins.runOnUiThread(() -> {
|
||||
MainActivity.ins.backView.cosImg = url==null ? null : BitmapFactory.decodeFile(Util.backImgFile);
|
||||
MainActivity.ins.backView.invalidate();
|
||||
});
|
||||
return new JSMap(
|
||||
"_type", "Success",
|
||||
"cardId", Util.getCardId(),
|
||||
"commandId", id
|
||||
).toString();
|
||||
} else if(_type.equals("GetPlayerBackground")) {
|
||||
var backImg = new File(Util.backImgFile);
|
||||
var img = Base64.getEncoder().encodeToString(IOs.readBytesClose(backImg.exists() ? new FileInputStream(backImg) : MainActivity.ins.getResources().openRawResource(R.drawable.back)));
|
||||
return new JSMap(
|
||||
"_type", "DataCallback",
|
||||
"cardId", Util.getCardId(),
|
||||
"commandId", id,
|
||||
"img", img
|
||||
).toString();
|
||||
}
|
||||
return new JSMap(
|
||||
"_type", "Error",
|
||||
"errorMessage", "Unknow Type",
|
||||
"cardId", Util.getCardId(),
|
||||
"commandId", id
|
||||
).toString();
|
||||
} catch (Exception e) {
|
||||
return new JSMap(
|
||||
"_type", "Error",
|
||||
"errorMessage", e.toString(),
|
||||
"cardId", Util.getCardId(),
|
||||
"commandId", id
|
||||
).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pausePlayer(boolean b) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPause() throws RemoteException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearTasks() throws RemoteException {
|
||||
System.out.println("Server clearTasks ...");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countOfPrograms(int type) throws RemoteException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playInsertTask(String pid) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopInsertTask(String pid) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProgramTask() throws RemoteException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUploadLogUrl(String playLog) throws RemoteException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUploadLogUrl() throws RemoteException {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.xixun.xixunplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.Gravity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import gnph.util.IOs;
|
||||
|
||||
public class Util {
|
||||
|
||||
public static final HashMap<Integer, String[]> stateDescs = new HashMap<>();
|
||||
static {
|
||||
stateDescs.put(1, new String[]{"Initialize", "初始化"});
|
||||
stateDescs.put(2, new String[]{"Schedules is over", "定时节目结束"});
|
||||
stateDescs.put(3, new String[]{"No programs waiting to be played", "无待播放的节目"});
|
||||
stateDescs.put(4, new String[]{"Delete program", "删除节目"});
|
||||
stateDescs.put(5, new String[]{"Program processing", "处理节目中"});
|
||||
stateDescs.put(6, new String[]{"Program Processed", "处理节目完成"});
|
||||
stateDescs.put(7, new String[]{"Program maybe error", "节目可能有误"});
|
||||
stateDescs.put(8, new String[]{"Screen-off", "关屏"});
|
||||
stateDescs.put(9, new String[]{"Program's area hasn't arrived yet", "定点节目不在范围"});
|
||||
}
|
||||
public static final String[] stateDescsUnknow = {"Unknown", "未知"};
|
||||
|
||||
public static Toast makeText(Context context, CharSequence text) {
|
||||
var toast = Toast.makeText(context, text, Toast.LENGTH_LONG);
|
||||
toast.setGravity(Gravity.TOP | Gravity.LEFT, 0, 0);
|
||||
return toast;
|
||||
}
|
||||
|
||||
public static String[] getState(int state) {
|
||||
var descs = stateDescs.get(state);
|
||||
return descs!=null ? descs : stateDescsUnknow;
|
||||
}
|
||||
|
||||
public static String programDir, backImgFile;
|
||||
|
||||
public static String getCardId() {
|
||||
try {
|
||||
var bytes = IOs.readBytesClose(new FileInputStream(new File("/data/joey/signed/card.id")));
|
||||
if(bytes.length < 40) return "";
|
||||
byte[] cMyKey = new byte[]{97, 119, 38, 3, 46, 112, 36, 93, 58, 100, 103, 62, 115, 112, 114, 51, 43, 61, 2, 101, 119};
|
||||
for(int i=0; i<20; ++i) bytes[i] = (byte) (bytes[i * 2] - cMyKey[i] - i - (bytes[i * 2 + 1] - 3));
|
||||
var cardId = new String(bytes);
|
||||
if(cardId.length() > 13) cardId = cardId.substring(0, 13);
|
||||
return cardId;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package gnph.android;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
public class LinearBox extends LinearLayout {
|
||||
|
||||
public LinearBox(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public LinearBox(ViewGroup box) {
|
||||
super(box.getContext());
|
||||
box.addView(this);
|
||||
}
|
||||
|
||||
public LinearBox horizontal() {
|
||||
setOrientation(HORIZONTAL);
|
||||
return this;
|
||||
}
|
||||
public LinearBox vertical() {
|
||||
setOrientation(VERTICAL);
|
||||
return this;
|
||||
}
|
||||
|
||||
public LinearBox addSpacing(int spacing) {
|
||||
if(getOrientation()==HORIZONTAL) addView(new View(getContext()), new LayoutParams(spacing, 0));
|
||||
else addView(new View(getContext()), new LayoutParams(0, spacing));
|
||||
return this;
|
||||
}
|
||||
public LinearBox addStretch() {
|
||||
addView(new View(getContext()), new LayoutParams(0, 0,1));
|
||||
return this;
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,170 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
|
@ -0,0 +1,30 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 982 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 7.6 KiB |
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">XixunPlayer</string>
|
||||
</resources>
|
|
@ -0,0 +1,4 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<style name="Theme.XixunPlayer" parent="android:Theme.Black.NoTitleBar">
|
||||
</style>
|
||||
</resources>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
|
@ -0,0 +1,4 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id 'com.android.application' version '8.1.1' apply false
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
|
@ -0,0 +1,6 @@
|
|||
#Wed Oct 11 11:55:49 CST 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
|
@ -0,0 +1,185 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
|
@ -0,0 +1,89 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
|
@ -0,0 +1,17 @@
|
|||
pluginManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "XixunPlayer"
|
||||
include ':app'
|