diff --git a/CountBoard/.gitignore b/CountBoard/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/CountBoard/.gitignore @@ -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 diff --git a/CountBoard/.idea/.gitignore b/CountBoard/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/CountBoard/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/CountBoard/.idea/.name b/CountBoard/.idea/.name new file mode 100644 index 0000000..d3f190d --- /dev/null +++ b/CountBoard/.idea/.name @@ -0,0 +1 @@ +XixunPlayer \ No newline at end of file diff --git a/CountBoard/.idea/compiler.xml b/CountBoard/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/CountBoard/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CountBoard/.idea/gradle.xml b/CountBoard/.idea/gradle.xml new file mode 100644 index 0000000..ae388c2 --- /dev/null +++ b/CountBoard/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/CountBoard/.idea/misc.xml b/CountBoard/.idea/misc.xml new file mode 100644 index 0000000..a25e2a9 --- /dev/null +++ b/CountBoard/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/CountBoard/.idea/vcs.xml b/CountBoard/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/CountBoard/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CountBoard/app/.gitignore b/CountBoard/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/CountBoard/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/CountBoard/app/build.gradle b/CountBoard/app/build.gradle new file mode 100644 index 0000000..1439462 --- /dev/null +++ b/CountBoard/app/build.gradle @@ -0,0 +1,53 @@ +plugins { + id 'com.android.application' +} + +android { + namespace 'com.xixun.xixunplayer' + compileSdk 34 + + defaultConfig { + applicationId "com.xixun.xixunplayer" + minSdk 26 + targetSdk 34 + versionCode 1 + versionName "1.0-timerboard" + 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 files('libs/xixun_card_settings_1.2.4.jar') +} + +def getAppName() { + def stringsFile = android.sourceSets.main.res.sourceFiles.find { it.name.equals 'strings.xml' } + String s = new XmlParser().parse(stringsFile).string.find { it.@name.equals 'app_name' }.text(); + return s.replaceAll("\"", ""); +} + +// Change the Apk name +android.applicationVariants.configureEach { variant -> + variant.outputs.configureEach { + def fileName = "${getAppName()}-${versionName}.apk" + outputFileName = fileName + } +} diff --git a/CountBoard/app/libs/connService2.jar b/CountBoard/app/libs/connService2.jar new file mode 100644 index 0000000..9bb1491 Binary files /dev/null and b/CountBoard/app/libs/connService2.jar differ diff --git a/CountBoard/app/libs/gnph.jar b/CountBoard/app/libs/gnph.jar new file mode 100644 index 0000000..49484bf Binary files /dev/null and b/CountBoard/app/libs/gnph.jar differ diff --git a/CountBoard/app/libs/ijkplayer-arm64-0.8.8.aar b/CountBoard/app/libs/ijkplayer-arm64-0.8.8.aar new file mode 100644 index 0000000..105f873 Binary files /dev/null and b/CountBoard/app/libs/ijkplayer-arm64-0.8.8.aar differ diff --git a/CountBoard/app/libs/ijkplayer-armv7a-0.8.8.aar b/CountBoard/app/libs/ijkplayer-armv7a-0.8.8.aar new file mode 100644 index 0000000..d84b81a Binary files /dev/null and b/CountBoard/app/libs/ijkplayer-armv7a-0.8.8.aar differ diff --git a/CountBoard/app/libs/ijkplayer-java-0.8.8.aar b/CountBoard/app/libs/ijkplayer-java-0.8.8.aar new file mode 100644 index 0000000..8224130 Binary files /dev/null and b/CountBoard/app/libs/ijkplayer-java-0.8.8.aar differ diff --git a/CountBoard/app/libs/xixun_card_settings_1.2.4.jar b/CountBoard/app/libs/xixun_card_settings_1.2.4.jar new file mode 100644 index 0000000..0d17c22 Binary files /dev/null and b/CountBoard/app/libs/xixun_card_settings_1.2.4.jar differ diff --git a/CountBoard/app/libs/zip4j-2.10.0.jar b/CountBoard/app/libs/zip4j-2.10.0.jar new file mode 100644 index 0000000..d80d844 Binary files /dev/null and b/CountBoard/app/libs/zip4j-2.10.0.jar differ diff --git a/CountBoard/app/proguard-rules.pro b/CountBoard/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/CountBoard/app/proguard-rules.pro @@ -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 \ No newline at end of file diff --git a/CountBoard/app/src/main/AndroidManifest.xml b/CountBoard/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..47da6ae --- /dev/null +++ b/CountBoard/app/src/main/AndroidManifest.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CountBoard/app/src/main/aidl/com/xixun/util/PlayerInfo.aidl b/CountBoard/app/src/main/aidl/com/xixun/util/PlayerInfo.aidl new file mode 100644 index 0000000..7726d8e --- /dev/null +++ b/CountBoard/app/src/main/aidl/com/xixun/util/PlayerInfo.aidl @@ -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(); +} \ No newline at end of file diff --git a/CountBoard/app/src/main/assets/imgs/W0.png b/CountBoard/app/src/main/assets/imgs/W0.png new file mode 100644 index 0000000..3e37d21 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W0.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W1.png b/CountBoard/app/src/main/assets/imgs/W1.png new file mode 100644 index 0000000..5dee862 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W1.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W10.png b/CountBoard/app/src/main/assets/imgs/W10.png new file mode 100644 index 0000000..7d55efe Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W10.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W13.png b/CountBoard/app/src/main/assets/imgs/W13.png new file mode 100644 index 0000000..8577bdc Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W13.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W14.png b/CountBoard/app/src/main/assets/imgs/W14.png new file mode 100644 index 0000000..2537239 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W14.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W15.png b/CountBoard/app/src/main/assets/imgs/W15.png new file mode 100644 index 0000000..4be21b3 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W15.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W16.png b/CountBoard/app/src/main/assets/imgs/W16.png new file mode 100644 index 0000000..0f2e015 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W16.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W17.png b/CountBoard/app/src/main/assets/imgs/W17.png new file mode 100644 index 0000000..04f83db Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W17.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W18.png b/CountBoard/app/src/main/assets/imgs/W18.png new file mode 100644 index 0000000..a3aec72 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W18.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W19.png b/CountBoard/app/src/main/assets/imgs/W19.png new file mode 100644 index 0000000..32736e2 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W19.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W2.png b/CountBoard/app/src/main/assets/imgs/W2.png new file mode 100644 index 0000000..c27cea2 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W2.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W20.png b/CountBoard/app/src/main/assets/imgs/W20.png new file mode 100644 index 0000000..2b326a8 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W20.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W29.png b/CountBoard/app/src/main/assets/imgs/W29.png new file mode 100644 index 0000000..1178e2e Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W29.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W3.png b/CountBoard/app/src/main/assets/imgs/W3.png new file mode 100644 index 0000000..10e825b Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W3.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W30.png b/CountBoard/app/src/main/assets/imgs/W30.png new file mode 100644 index 0000000..de3615c Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W30.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W31.png b/CountBoard/app/src/main/assets/imgs/W31.png new file mode 100644 index 0000000..b4dd147 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W31.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W32.png b/CountBoard/app/src/main/assets/imgs/W32.png new file mode 100644 index 0000000..581663d Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W32.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W33.png b/CountBoard/app/src/main/assets/imgs/W33.png new file mode 100644 index 0000000..3b51e5a Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W33.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W34.png b/CountBoard/app/src/main/assets/imgs/W34.png new file mode 100644 index 0000000..0bc4e72 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W34.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W35.png b/CountBoard/app/src/main/assets/imgs/W35.png new file mode 100644 index 0000000..cfa67ec Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W35.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W36.png b/CountBoard/app/src/main/assets/imgs/W36.png new file mode 100644 index 0000000..2b326a8 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W36.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W4.png b/CountBoard/app/src/main/assets/imgs/W4.png new file mode 100644 index 0000000..17a05d8 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W4.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W44.png b/CountBoard/app/src/main/assets/imgs/W44.png new file mode 100644 index 0000000..d829389 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W44.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W45.png b/CountBoard/app/src/main/assets/imgs/W45.png new file mode 100644 index 0000000..9129ef8 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W45.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W46.png b/CountBoard/app/src/main/assets/imgs/W46.png new file mode 100644 index 0000000..9129ef8 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W46.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W5.png b/CountBoard/app/src/main/assets/imgs/W5.png new file mode 100644 index 0000000..5f7cbd7 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W5.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W6.png b/CountBoard/app/src/main/assets/imgs/W6.png new file mode 100644 index 0000000..2e1a63c Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W6.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W7.png b/CountBoard/app/src/main/assets/imgs/W7.png new file mode 100644 index 0000000..d37cc41 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W7.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W8.png b/CountBoard/app/src/main/assets/imgs/W8.png new file mode 100644 index 0000000..a3394db Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W8.png differ diff --git a/CountBoard/app/src/main/assets/imgs/W9.png b/CountBoard/app/src/main/assets/imgs/W9.png new file mode 100644 index 0000000..8e98a1c Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/W9.png differ diff --git a/CountBoard/app/src/main/assets/imgs/logo3.png b/CountBoard/app/src/main/assets/imgs/logo3.png new file mode 100644 index 0000000..3b4ea20 Binary files /dev/null and b/CountBoard/app/src/main/assets/imgs/logo3.png differ diff --git a/CountBoard/app/src/main/java/com/xixun/command/reply/ReplyBase.java b/CountBoard/app/src/main/java/com/xixun/command/reply/ReplyBase.java new file mode 100644 index 0000000..d2f446a --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/command/reply/ReplyBase.java @@ -0,0 +1,10 @@ +package com.xixun.command.reply; + +import java.io.Serializable; + + +public abstract class ReplyBase implements Serializable{ + + private static final long serialVersionUID = -3630726876519388513L; + public String commandId; +} diff --git a/CountBoard/app/src/main/java/com/xixun/command/reply/TaskProgressReply.java b/CountBoard/app/src/main/java/com/xixun/command/reply/TaskProgressReply.java new file mode 100644 index 0000000..54b2a64 --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/command/reply/TaskProgressReply.java @@ -0,0 +1,18 @@ +package com.xixun.command.reply; + +public class TaskProgressReply extends ReplyBase { + + private static final long serialVersionUID = 6264049742389542806L; + public int percent; + public String taskItemId; + public int speed; + public int remainingSeconds; + + public TaskProgressReply(String commandId, String taskItemId, int percent, int sp, int rs) { + this.commandId = commandId; + this.taskItemId = taskItemId; + this.percent = percent; + this.speed = sp; + this.remainingSeconds = rs; + } +} \ No newline at end of file diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/AIDLService.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/AIDLService.java new file mode 100644 index 0000000..1682c71 --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/AIDLService.java @@ -0,0 +1,232 @@ +package com.xixun.xixunplayer; + +import android.annotation.SuppressLint; +import android.app.Service; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.IBinder; +import android.os.RemoteException; + +import com.xixun.command.reply.TaskProgressReply; +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.ArrayList; +import java.util.Base64; +import java.util.HashSet; + +import gnph.util.IOs; +import gnph.util.JSList; +import gnph.util.JSMap; +import gnph.util.URLConn; + +public class AIDLService 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 { + Util.println("Server getVersion. <-"+null); + return null; + } + + @Override + public void setScreenWidth(int width) throws RemoteException { + Util.println("Server setScreenWidth. ->"+width); + } + + @Override + public void setScreenHeight(int height) throws RemoteException { + Util.println("Server setScreenHeight. ->"+height); + + } + + @Override + public void taskScreenshot(String cmdId) throws RemoteException { + Util.println("Server taskScreenshot. ->"+cmdId); + } + + @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 { + Util.println("Server getCurProgramId ..."); + return null; + } + + @Override + public void setUSBProgramPwd(String pwd) throws RemoteException { + + } + + @SuppressLint("ResourceType") + @Override + public String executeJosnCommand(String jsonstr) throws RemoteException { + Util.println("AIDL executeJsonCommand ..."+jsonstr);//{"_type":"DeleteTask","id":"652522a0e81d1e000009201a","sendTo":"yzd-player"} + String commandId = null; + try { + var jsonBytes = jsonstr.getBytes(StandardCharsets.UTF_8); + var json = JSMap.from(jsonBytes); + var _type = json.stnn("_type"); + commandId = json.stnn("id"); + if(_type.equals("DeleteTask")) { + return new JSMap( + "_type", "DataCallback", + "result", "received command", + "cardId", Util.getCardId(), + "commandId", commandId + ).toString(); + } else if(_type.equals("SetPlayerBackground")) { + var url = json.str("url"); + if(url==null) new File(Util.backImgFile).delete(); + else { + var fout = new FileOutputStream(Util.backImgFile); + IOs.write(fout, new URLConn(url).in()); + fout.flush(); + fout.getFD().sync(); + fout.close(); + } + MainActivity.ins.runOnUiThread(() -> { + MainActivity.ins.backView.cosImg = url==null ? null : BitmapFactory.decodeFile(Util.backImgFile, Util.noScaled); + MainActivity.ins.backView.invalidate(); + }); + return new JSMap( + "_type", "Success", + "cardId", Util.getCardId(), + "commandId", commandId + ).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", commandId, + "img", img + ).toString(); + } else if(_type.equalsIgnoreCase("getProgramTask")) { + var task = JSMap.fromClose(new FileInputStream(Util.programDir+"/program")).jsmap("task"); + return new JSMap( + "_type", "ProgramTaskCallback", + "cardId", Util.getCardId(), + "commandId", commandId, + "task", task + ).toString(); + } + return new JSMap( + "_type", "Error", + "errorMessage", "Unknown Type: "+_type, + "cardId", Util.getCardId(), + "commandId", commandId + ).toString(); + } catch (Exception e) { + Util.printStackTrace(e); + return new JSMap( + "_type", "Error", + "errorMessage", Util.toStr(e), + "cardId", Util.getCardId(), + "commandId", commandId + ).toString(); + } + } + + @Override + public void pausePlayer(boolean b) throws RemoteException { + + } + + @Override + public boolean isPause() throws RemoteException { + return false; + } + + @Override + public boolean clearTasks() throws RemoteException { + 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 { + try { + return IOs.readStrClose(new FileInputStream(Util.programDir+"/program")); + } catch (Exception e) { + Util.printStackTrace(e); + return Util.toStr(e); + } + } + + @Override + public void setUploadLogUrl(String playLog) throws RemoteException { + + } + + @Override + public String getUploadLogUrl() throws RemoteException { + return null; + } + }; + + static class Src { + String filename; + String url; + + public Src(String filename, String url) { + this.filename = filename; + this.url = url; + } + } + static class NeedDowns { + String prog; + ArrayList srcs = new ArrayList<>(); + } +} \ No newline at end of file diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/AbsLayout.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/AbsLayout.java new file mode 100644 index 0000000..b00610b --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/AbsLayout.java @@ -0,0 +1,107 @@ +package com.xixun.xixunplayer; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +public class AbsLayout extends ViewGroup { + + public AbsLayout(Context context) { + this(context, null); + } + + public AbsLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public AbsLayout(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public AbsLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int count = getChildCount(); + int maxHeight = 0; + int maxWidth = 0; + measureChildren(widthMeasureSpec, heightMeasureSpec); + for(int i = 0; i < count; i++) { + View child = getChildAt(i); + if(child.getVisibility() != GONE) { + int childRight; + int childBottom; + var lp = (LayoutParams) child.getLayoutParams(); + childRight = lp.x + child.getMeasuredWidth(); + childBottom = lp.y + child.getMeasuredHeight(); + maxWidth = Math.max(maxWidth, childRight); + maxHeight = Math.max(maxHeight, childBottom); + } + } + maxWidth += getPaddingLeft() + getPaddingRight(); + maxHeight += getPaddingTop() + getPaddingBottom(); + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, 0), resolveSizeAndState(maxHeight, heightMeasureSpec, 0)); + } + + @Override + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(0, 0, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int count = getChildCount(); + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + if(child.getVisibility() != GONE) { + var lp = (LayoutParams) child.getLayoutParams(); + int childLeft = getPaddingLeft() + lp.x; + int childTop = getPaddingTop() + lp.y; + child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight()); + } + } + } + + @Override + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams; + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return new LayoutParams(p); + } + + @Override + public boolean shouldDelayChildPressedState() { + return false; + } + + public static class LayoutParams extends ViewGroup.LayoutParams { + + public int x; + public int y; + + public LayoutParams(int x, int y, int width, int height) { + super(width, height); + this.x = x; + this.y = y; + } + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + } + public LayoutParams(ViewGroup.LayoutParams source) { + super(source); + } + } +} diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/BackView.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/BackView.java new file mode 100644 index 0000000..2085153 --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/BackView.java @@ -0,0 +1,40 @@ +package com.xixun.xixunplayer; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.text.TextPaint; +import android.view.View; + +public class BackView extends View { + + Bitmap cosImg; + Rect rect = new Rect(); + Paint[] paints = {new TextPaint(), new TextPaint()}; + String[] txts = {"0.00", ""}; + int size2 = Util.screenHeight/2; + + public BackView(Context context) { + super(context); + paints[0].setTextAlign(Paint.Align.RIGHT); + paints[1].setTextAlign(Paint.Align.RIGHT); + for(int i=0; i<2; i++) { + paints[i].setTextSize(size2); + paints[i].setColor(0xffffffff); + } + paints[0].setLinearText(true); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + rect.right = Util.screenWidth; + rect.bottom = Util.screenHeight; + canvas.clipRect(rect); + if(cosImg!=null) canvas.drawBitmap(cosImg, null, rect, null); + canvas.drawText(txts[0], Util.screenWidth-6, -paints[0].ascent(), paints[0]); + canvas.drawText(txts[1], Util.screenWidth-6, (Util.screenHeight+paints[0].getTextSize()-paints[1].ascent()-paints[1].descent())/2, paints[1]); + } +} diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/BootCompletedReceiver.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/BootCompletedReceiver.java new file mode 100644 index 0000000..7433834 --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/BootCompletedReceiver.java @@ -0,0 +1,17 @@ + +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) { + Util.println("==== BootCompletedReceiver onReceive >> "+intent.getAction()); + Util.initDir(context); + if(MainActivity.ins!=null) return; + var inten = new Intent(context, MainActivity.class); + inten.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(inten); + } +} \ No newline at end of file diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/MainActivity.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/MainActivity.java new file mode 100644 index 0000000..66d2404 --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/MainActivity.java @@ -0,0 +1,178 @@ +package com.xixun.xixunplayer; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Bundle; +import android.os.IBinder; +import android.os.StrictMode; +import android.view.Choreographer; + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import com.xixun.joey.aidlset.CardService; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; + +import gnph.util.JSMap; + +public class MainActivity extends Activity implements Choreographer.FrameCallback { + + public static MainActivity ins; + ArrayList services = new ArrayList<>(); + BackView backView; + + @RequiresApi(api = Build.VERSION_CODES.R) + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ins = this; + Util.println("==>> MainActivity onCreate >>>> this "+hashCode()+" Thread: "+Thread.currentThread().getId()); + + StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build()); + setContentView(backView = new BackView(MainActivity.this)); + + if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) init(); + else { + Util.println("---- No permission, Try again ..."); + Util.makeText(this, "No permission, Try again ...").show(); + 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, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if(Util.programDir!=null) return; + if(requestCode==999 && grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED) init(); + else { + Util.println("---- Request Permission Failed"); + Util.makeText(this, "Request Permission Failed").show(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + Util.println("==<< MainActivity onDestroy <<<< this "+hashCode()); + ins = null; + for(var service : services) unbindService(service); + try (var fout = new FileOutputStream(Util.programDir+"/cfg")){ + Util.cfg.write(fout); + fout.flush(); + fout.getFD().sync(); + } catch (Exception ignored) { + } + System.gc(); + } + + @Override + protected void onStart() { + super.onStart(); + Util.println(" ==>> MainActivity onStart >> "+hashCode()); + } + @Override + protected void onStop() { + super.onStop(); + Util.println(" ==<< MainActivity onStop << "+hashCode()); + } + @Override + protected void onRestart() { + super.onRestart(); + Util.println(" ==>> MainActivity onRestart >> "+hashCode()); + } + + @Override + protected void onResume() { + super.onResume(); + Util.println(" ==>> MainActivity onResume >> "+hashCode()); + } + + @Override + protected void onPause() { + super.onPause(); + Util.println(" ==<< MainActivity onPause << "+hashCode()); + } + + CardService serviCard; + Intent intenCard; + ServiceConnection connCard; + @SuppressLint("UnspecifiedRegisterReceiverFlag") + public void init() { + Util.initDir(this); + backView.cosImg = BitmapFactory.decodeFile(Util.backImgFile, Util.noScaled); + backView.invalidate(); + if(MainService.ins==null) startService(new Intent(this, MainService.class)); + + var cfg = new File(Util.programDir+"/cfg"); + if(! cfg.isFile()) Util.cfg = new JSMap(); + else { + try { + Util.cfg = JSMap.fromClose(new FileInputStream(cfg)); + } catch (Exception e) { + Util.cfg = new JSMap(); + Util.makeText(MainActivity.this, Util.toStr(e)).show(); + Util.printStackTrace(e); + } + } + Util.println(Util.cfg.toStr()); + connCard = new ServiceConnection() { + public void onServiceDisconnected(ComponentName name) { + serviCard = null; + Util.println("<-<- AIDL Service cardsystem Disconnected"); + } + + public void onServiceConnected(ComponentName name, IBinder iBinder) { + unbindService(this); + services.remove(this); + Util.println("->-> AIDL Service cardsystem Connected"); + serviCard = CardService.Stub.asInterface(iBinder); + try { + //Util.screenWidth = serviCard.getScreenWidth(); + //Util.screenHeight = serviCard.getScreenHeight(); + Util.println(" screen: "+Util.screenWidth+" x "+Util.screenHeight); + backView.invalidate(); + } catch (Exception e) { + Util.makeText(MainActivity.this, Util.toStr(e)).show(); + Util.printStackTrace(e); + } + } + }; + intenCard = new Intent("com.xixun.joey.aidlset.SettingsService"); + intenCard.setPackage("com.xixun.joey.cardsystem"); + bindService(intenCard, connCard, Context.BIND_AUTO_CREATE); + services.add(connCard); + } + + + Choreographer choreographer = Choreographer.getInstance(); + boolean canAdd = true; + + @Override + public void doFrame(long frameTimeNanos) { + if(backView == null) { + canAdd = true; + return; + } + choreographer.postFrameCallback(this); + canAdd = false; + //var milli = System.currentTimeMillis(); + } +} \ No newline at end of file diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/MainService.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/MainService.java new file mode 100644 index 0000000..ae7b23d --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/MainService.java @@ -0,0 +1,35 @@ +package com.xixun.xixunplayer; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +public class MainService extends Service { + + static MainService ins; + @Override + public void onCreate() { + super.onCreate(); + ins = this; + Util.println("==>> MainService onCreate >>>> "+hashCode()+" Thread: "+Thread.currentThread().getId()); + UDPThread.startSocket(); + TCPThread.startServer(3333); + if(MainActivity.ins==null) { + var intent = new Intent(this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + } + @Override + public void onDestroy() { + super.onDestroy(); + Util.println("==<< MainService onDestroy <<<< this "+hashCode()); + ins = null; + System.gc(); + } + + @Override + public IBinder onBind(Intent intent) { + throw new UnsupportedOperationException("Not yet implemented"); + } +} \ No newline at end of file diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/SrcCopy.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/SrcCopy.java new file mode 100644 index 0000000..2f38af5 --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/SrcCopy.java @@ -0,0 +1,36 @@ +package com.xixun.xixunplayer; + +import android.content.Context; +import android.graphics.Canvas; +import android.view.View; + +import androidx.annotation.NonNull; + +public class SrcCopy extends View { + + View view; + float scaleX = 1, scaleY = 1; + + public SrcCopy(Context context, View view) { + super(context); + this.view = view; + } + + @Override + protected void onDraw(@NonNull Canvas canvas) { + super.onDraw(canvas); + if(view==null) return; + if(scaleX==0) { + if(view.getWidth()!=0&&getWidth()!=0) { + scaleX = getWidth() / (float) view.getWidth(); + scaleY = getHeight() / (float) view.getHeight(); + } else { + invalidate(); + return; + } + } + if(scaleX!=1 || scaleY!=1) canvas.scale(scaleX, scaleY); + view.draw(canvas); + invalidate(); + } +} diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/TCPThread.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/TCPThread.java new file mode 100644 index 0000000..7b04694 --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/TCPThread.java @@ -0,0 +1,204 @@ +package com.xixun.xixunplayer; + +import android.app.ActivityManager; +import android.graphics.BitmapFactory; +import android.os.Environment; +import android.os.StatFs; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.TimeZone; +import java.util.concurrent.CountDownLatch; + +import gnph.util.IOs; +import gnph.util.JSList; +import gnph.util.JSMap; +import gnph.util.NumFmts; +import gnph.util.O; + +public class TCPThread extends Thread { + + public static void startServer(int port) { + new Thread(()->{ + try { + var serverSocket = new ServerSocket(port); + while(true) { + try { + Util.println("\nAccepting ..."); + var socket = serverSocket.accept(); + new TCPThread(MainActivity.ins, socket).start(); + Util.println("\nAccepted"); + } catch (Throwable e) { + var ins = MainActivity.ins; + if(ins!=null) ins.runOnUiThread(() -> Util.makeText(ins, Util.toStr(e)).show()); + Util.printStackTrace(e); + } + } + } catch (Throwable e) { + var msg = e.getMessage(); + if(msg==null || ! msg.contains("in use")) MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.ins, Util.toStr(e)).show()); + Util.printStackTrace(e); + } + }).start(); + } + + MainActivity main; + Socket socket; + InputStream in; + OutputStream out; + SimpleDateFormat fmt = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); + + public TCPThread(MainActivity main, Socket socket) { + this.main = main; + this.socket = socket; + } + public void run() { + try { + socket.setSoTimeout(600000); + Util.socketThreads.add(this); + in = socket.getInputStream(); + out = socket.getOutputStream(); + HashSet existed = null; + ByteArrayOutputStream progJson = null; + while(true) { + var obj = JSMap.from(in); + var _type = obj.stnn("_type"); + Util.println("_type: "+_type); + if("consult".equals(_type)) { + JSList files = obj.jslist("files"); + if(files==null) new JSMap("_type", _type, "idList", obj.jslist("idList")).write(out); + else { + existed = new HashSet<>(); + for(var fil : files) { + var name = fil.stnn("name"); + var file = new File(Util.programDir + "/" + name); + if(file.isFile() && file.length()==fil.intg("size")) existed.add(name); + } + new JSMap("_type", _type, "existed", existed).write(out); + } + } else if("setBackImg".equals(_type) || "imgFileStart".equals(_type)) { + var fout = new FileOutputStream(Util.backImgFile); + IOs.write(fout, in, obj.intg("size")); + fout.flush(); + fout.getFD().sync(); + fout.close(); + var img = BitmapFactory.decodeFile(Util.backImgFile, Util.noScaled); + if(main!=null) main.runOnUiThread(() -> { + main.backView.cosImg = img; + main.backView.invalidate(); + }); + new JSMap("success", true).write(out); + } else if("DelBackImg".equals(_type)) { + MainActivity.ins.runOnUiThread(() -> { + MainActivity.ins.backView.cosImg = null; + MainActivity.ins.backView.invalidate(); + }); + new JSMap("success", new File(Util.backImgFile).delete()).write(out); + } else if("Config".equals(_type)) { + var entrySet = obj.entrySet(); + for(var entry : entrySet) if(! entry.getKey().equals("_type")) Util.cfg.put(entry.getKey(), entry.getValue()); + try (var fOut = new FileOutputStream(Util.programDir + "/cfg")) { + Util.cfg.write(fOut); + fOut.flush(); + fOut.getFD().sync(); + } + new JSMap("success", new File(Util.backImgFile).delete()).write(out); + } else if("GetInfo".equals(_type)) { + var writer = new OutputStreamWriter(out); + var fmt = new SimpleDateFormat("yy-MM-dd HH:mm:ss.SSS"); + writer.append(" Current: ").append(fmt.format(System.currentTimeMillis())).append(" ").append(String.valueOf(TimeZone.getDefault().getRawOffset()/3600000f)).append(" ").append(TimeZone.getDefault().getDisplayName()).append("\n"); + + var statFs = new StatFs(Environment.getExternalStorageDirectory().getPath()); + writer.append(" Disk: ").append(String.valueOf(statFs.getTotalBytes()/1000000)).append(" ").append(String.valueOf(statFs.getAvailableBytes()/1000000)).append(" ").append(String.valueOf(statFs.getFreeBytes()/1000000)).append(" (total avail free)\n"); + if(main!=null) { + var actManager = (ActivityManager) main.getSystemService(MainActivity.ACTIVITY_SERVICE); + var memoryInfo = new ActivityManager.MemoryInfo(); + actManager.getMemoryInfo(memoryInfo); + writer.append(" Memory: ").append(String.valueOf(memoryInfo.totalMem/1000000)).append(" ").append(String.valueOf(memoryInfo.availMem/1000000)).append(" ").append(String.valueOf(memoryInfo.threshold/1000000)).append(" ").append(String.valueOf(memoryInfo.lowMemory)).append(" (total avail threshold low)\n"); + } + var runtime = Runtime.getRuntime(); + writer.append("Runtime: ").append(String.valueOf(runtime.maxMemory()/1000000)).append(" ").append(String.valueOf(runtime.totalMemory()/1000000)).append(" ").append(NumFmts.cfix2().format(runtime.freeMemory()*0.000001)).append(" (max total free)\n"); + writer.append("\nSockets ").append(String.valueOf(Util.socketThreads.size())).append("\n"); + for(var socket : Util.socketThreads) writer.append(" ").append(String.valueOf(socket.socket.getInetAddress())).append(":").append(String.valueOf(socket.socket.getPort())).append(" Buf:").append(String.valueOf(socket.socket.getReceiveBufferSize()/1000)).append("k SoLinger:").append(String.valueOf(socket.socket.getSoLinger())).append("\n"); + + writer.append("\n\n"); + writer.append(Util.cfg.toStr()); + writer.append("\n\n"); + + var latch = new CountDownLatch(1); + try { + latch.await(); + } catch (InterruptedException ignored) {} + writer.flush(); + } else if("ListProgFiles".equals(_type)) { + var files = new File(Util.programDir).listFiles(); + if(files!=null) { + Arrays.sort(files, (f1, f2) -> Long.signum(f2.lastModified() - f1.lastModified())); + var writer = new OutputStreamWriter(out); + for(var file : files) writer.append(fmt.format(new Date(file.lastModified()))).append(' ').append(file.getName()).append(' ').append(String.valueOf(file.length())).append('\n'); + writer.flush(); + } + } else if("GetFile".equals(_type)) { + var name = obj.str("name"); + if(name==null) new JSMap("msg", "name is null").write(out); + else { + var file = new File(Util.programDir+"/"+name); + if(! file.isFile()) new JSMap("msg", "file not exist").write(out); + else { + new JSMap("len", file.length()).write(out); + IOs.writeCloseIn(out, new FileInputStream(file)); + } + } + } else if("GetJsonWithFileInfo".equals(_type)) { + var inse = new File(Util.programDir+"/insert"); + var files = new File(Util.programDir).listFiles(); + if(inse.isFile()) { + var json = IOs.readStrClose(new FileInputStream(inse)); + if(files!=null) for(var file : files) if(! "program".equals(file.getName())) json = json.replace("\""+file.getName()+"\"", "\""+file.getName()+"\"/*"+file.length()+" "+fmt.format(new Date(file.lastModified()))+"*/"); + var writer = new OutputStreamWriter(out); + writer.append("insert:\n"); + writer.append(json); + if(! json.endsWith("\n")) writer.append("\n"); + writer.flush(); + } + var prog = new File(Util.programDir+"/program"); + if(! prog.isFile()) new JSMap("msg", "'program' file not exist").write(out); + else { + var json = IOs.readStrClose(new FileInputStream(prog)); + if(files!=null) for(var file : files) if(! "program".equals(file.getName())) json = json.replace("\""+file.getName()+"\"", "\""+file.getName()+"\"/*"+file.length()+" "+fmt.format(new Date(file.lastModified()))+"*/"); + var writer = new OutputStreamWriter(out); + writer.append("\nprogram:\n"); + writer.append(json); + writer.flush(); + } + } + out.flush(); + Util.println("cmd end"); + } + } catch (Throwable e) { + var emsg = e.getMessage(); + if(e instanceof SocketTimeoutException || "Socket closed".equals(emsg) || (emsg!=null && emsg.endsWith("end-of-input"))) { + Util.println(emsg); + return; + } + if(main!=null) main.runOnUiThread(() -> Util.makeText(main, Util.toStr(e)).show()); + Util.printStackTrace(e); + } finally { + Util.socketThreads.remove(this); + O.close(in, out, socket); + Util.println("conn end\n"); + } + } +} diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/UDPThread.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/UDPThread.java new file mode 100644 index 0000000..a1c1359 --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/UDPThread.java @@ -0,0 +1,116 @@ +package com.xixun.xixunplayer; + +import android.graphics.BitmapFactory; + +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.util.Base64; + +import gnph.util.JSMap; +import gnph.util.NumFmts; +import gnph.util.URLConn; + +public class UDPThread extends Thread { + + public static void startSocket() { + new Thread(()->{ + try (var socket = new DatagramSocket(33331)) { + byte[] buffer = new byte[1024]; + var imgBuf = new ByteArrayOutputStream(10240); + Util.println("\nAccepting"); + while(true) { + try { + var packet = new DatagramPacket(buffer, buffer.length); + socket.receive(packet); + var len = packet.getLength(); + if(buffer[0]!=0x5A || buffer[len-1]!=(byte)0xA5 || buffer[1]<0x0a) continue; + var ins = MainActivity.ins; + if(ins==null) continue; + var view = ins.backView; + if(buffer[1]==0x0a) { + var buf = new StringBuilder(16); + if(buffer[2]!=0) buf.append(buffer[2]&0xff).append(":"); + + if(buf.length()!=0) buf.append(NumFmts.zz().format(buffer[3]&0xff)).append(":"); + else if(buffer[3]!=0) buf.append(buffer[3]&0xff).append(":"); + if(buf.length()!=0) buf.append(NumFmts.zz().format(buffer[4]&0xff)); + else buf.append(buffer[4]&0xff); + + if(buffer[7]>=1) buf.append(".").append(buffer[5]&0xff); + if(buffer[7]>=2) buf.append(buffer[6]&0xff); + var txt = buf.toString(); + ins.runOnUiThread(() -> { + view.txts[0] = txt; + view.invalidate(); + }); + } else if(buffer[1]==0x0d) { + var txt = new String(buffer, 4, packet.getLength()-6); + ins.runOnUiThread(() -> { + view.paints[1].setTextSize(view.size2); + var tlen = view.paints[1].measureText(view.txts[1] = txt); + if(tlen > Util.screenWidth) view.paints[1].setTextSize(Util.screenWidth * view.size2 / tlen); + view.invalidate(); + }); + } else if(buffer[1]==0x0b) { + int size = buffer[3]&0xff; + if(buffer[2]==0) ins.runOnUiThread(() -> { + view.paints[0].setTextSize(size); + if(size + view.paints[1].getTextSize() > Util.screenHeight) view.paints[1].setTextSize(Util.screenHeight-size); + view.invalidate(); + }); + else if(buffer[2]==1) ins.runOnUiThread(() -> { + view.paints[1].setTextSize(view.size2 = size); + var tlen = view.paints[1].measureText(view.txts[1]); + if(tlen > Util.screenWidth) view.paints[1].setTextSize(Util.screenWidth * view.size2 / tlen); + view.invalidate(); + }); + } else if(buffer[1]==0x0f) { + int color = 0xff000000 | (buffer[3]&0xff)<<16 | (buffer[4]&0xff)<<8 | buffer[5]&0xff; + int idx = buffer[2]; + if(idx==0||idx==1) ins.runOnUiThread(() -> { + view.paints[idx].setColor(color); + view.invalidate(); + }); + } else if(buffer[1]==0x0c) { + int val = buffer[2]&0xff; + var json = new JSMap(); + json.put("_id", "SetBrightness"); + json.put("_type", "SetBrightness"); + json.put("brightnessPercentage", val*100/255); + var res = new URLConn("http://localhost:2016/settings").writeJson(json.toStr()).read(); + Util.println(res); + } else if(buffer[1]==0x0e) { + //Util.println(new String(Hex.to(buffer, packet.getLength(), null))); + if(buffer[3]==1) imgBuf.reset(); + imgBuf.write(buffer, 6, packet.getLength()-8); + if(buffer[3]==buffer[2]) { + var data = Base64.getDecoder().decode(imgBuf.toByteArray()); + var fout = new FileOutputStream(Util.backImgFile); + fout.write(data); + fout.flush(); + fout.getFD().sync(); + fout.close(); + imgBuf.reset(); + var img = BitmapFactory.decodeFile(Util.backImgFile, Util.noScaled); + ins.runOnUiThread(() -> { + view.cosImg = img; + view.invalidate(); + }); + } + } + } catch (Throwable e) { + var ins = MainActivity.ins; + if(ins!=null) ins.runOnUiThread(() -> Util.makeText(ins, Util.toStr(e)).show()); + Util.printStackTrace(e); + } + } + } catch (Throwable e) { + var msg = e.getMessage(); + if(msg==null || ! msg.contains("in use")) MainActivity.ins.runOnUiThread(() -> Util.makeText(MainActivity.ins, Util.toStr(e)).show()); + Util.printStackTrace(e); + } + }).start(); + } +} diff --git a/CountBoard/app/src/main/java/com/xixun/xixunplayer/Util.java b/CountBoard/app/src/main/java/com/xixun/xixunplayer/Util.java new file mode 100644 index 0000000..45d8dcd --- /dev/null +++ b/CountBoard/app/src/main/java/com/xixun/xixunplayer/Util.java @@ -0,0 +1,91 @@ +package com.xixun.xixunplayer; + +import android.content.Context; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Environment; +import android.view.Gravity; +import android.widget.Toast; + +import java.io.CharArrayWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Vector; + +import gnph.util.IOs; +import gnph.util.JSMap; + +public class Util { + public static JSMap cfg; + public static int screenWidth = 320, screenHeight = 160; + + public static void initDir(Context ctx) { + var dir = Build.VERSION.SDK_INT < Build.VERSION_CODES.R ? Environment.getExternalStorageDirectory().getAbsolutePath() + "/XixunPlayer" : ctx.getExternalFilesDir(null).getAbsolutePath(); + Util.println("\n---- Init dir "+dir); + Util.programDir = dir + "/program"; + Util.backImgFile = dir + "/background"; + + var program = new File(Util.programDir); + if(program.isFile()) program.delete(); + Util.println(" mkdir: "+program.mkdirs()); + } + + public static final BitmapFactory.Options noScaled = new BitmapFactory.Options(); + static { + noScaled.inScaled = false; + } + public static final Vector socketThreads = new Vector<>(); + + public static StringBuffer buf = new StringBuffer(); + public static SimpleDateFormat dateFmt = new SimpleDateFormat("yy-MM-dd HH:mm:ss.SSS"); + + public static void println(String msg) { + System.out.println(msg); + if(buf.length()>1000000) buf.replace(0, 100000, ""); + buf.append(msg).append("\n"); + } + public static void printStackTrace(Throwable e) { + println(toStackTrace(e)); + } + + public static String toStr(Throwable e) { + var traces = e.getStackTrace(); + var msg = e.toString(); + for(var trace : traces) if(trace.getClassName().startsWith("com.xixun.xixunplayer.")) { + msg += "\n at "+trace.getFileName()+'.'+trace.getMethodName()+':'+trace.getLineNumber(); + } + return msg; + } + public static String toStackTrace(Throwable e) { + var out = new CharArrayWriter(); + var writer = new PrintWriter(out); + e.printStackTrace(writer); + writer.flush(); + return out.toString(); + } + + 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 programDir, backImgFile; + public static String getCardId() { + try { + var bytes = IOs.readBytesClose(new FileInputStream("/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) { + printStackTrace(e); + return ""; + } + } +} diff --git a/CountBoard/app/src/main/java/gnph/android/LinearBox.java b/CountBoard/app/src/main/java/gnph/android/LinearBox.java new file mode 100644 index 0000000..f6606af --- /dev/null +++ b/CountBoard/app/src/main/java/gnph/android/LinearBox.java @@ -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; + } +} diff --git a/CountBoard/app/src/main/res/drawable/back.png b/CountBoard/app/src/main/res/drawable/back.png new file mode 100644 index 0000000..7d65f1e Binary files /dev/null and b/CountBoard/app/src/main/res/drawable/back.png differ diff --git a/CountBoard/app/src/main/res/drawable/ic_launcher_background.xml b/CountBoard/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/CountBoard/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CountBoard/app/src/main/res/drawable/ic_launcher_foreground.xml b/CountBoard/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/CountBoard/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/CountBoard/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/CountBoard/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/CountBoard/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/CountBoard/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/CountBoard/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/CountBoard/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/CountBoard/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/CountBoard/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/CountBoard/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/CountBoard/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/CountBoard/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/CountBoard/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/CountBoard/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/CountBoard/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/CountBoard/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/CountBoard/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/CountBoard/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/CountBoard/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/CountBoard/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/CountBoard/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/CountBoard/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/CountBoard/app/src/main/res/values/colors.xml b/CountBoard/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..c8524cd --- /dev/null +++ b/CountBoard/app/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/CountBoard/app/src/main/res/values/strings.xml b/CountBoard/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..a619236 --- /dev/null +++ b/CountBoard/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + XixunPlayer + \ No newline at end of file diff --git a/CountBoard/build.gradle b/CountBoard/build.gradle new file mode 100644 index 0000000..3daed1d --- /dev/null +++ b/CountBoard/build.gradle @@ -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 +} \ No newline at end of file diff --git a/CountBoard/gradle.properties b/CountBoard/gradle.properties new file mode 100644 index 0000000..3e927b1 --- /dev/null +++ b/CountBoard/gradle.properties @@ -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 \ No newline at end of file diff --git a/CountBoard/gradle/wrapper/gradle-wrapper.jar b/CountBoard/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/CountBoard/gradle/wrapper/gradle-wrapper.jar differ diff --git a/CountBoard/gradle/wrapper/gradle-wrapper.properties b/CountBoard/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..d587198 --- /dev/null +++ b/CountBoard/gradle/wrapper/gradle-wrapper.properties @@ -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 diff --git a/CountBoard/gradlew b/CountBoard/gradlew new file mode 100644 index 0000000..4f906e0 --- /dev/null +++ b/CountBoard/gradlew @@ -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" "$@" diff --git a/CountBoard/gradlew.bat b/CountBoard/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/CountBoard/gradlew.bat @@ -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 diff --git a/CountBoard/settings.gradle b/CountBoard/settings.gradle new file mode 100644 index 0000000..366ef33 --- /dev/null +++ b/CountBoard/settings.gradle @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + jcenter() + } +} + +rootProject.name = "XixunPlayer" +include ':app'