Browse Source

删除设备

chenzubin 3 months ago
parent
commit
1bb0991c51

+ 1 - 0
android/app/build.gradle

@@ -79,4 +79,5 @@ dependencies {
79 79
     implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
80 80
     implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
81 81
     implementation 'org.apache.commons:commons-lang3:3.12.0'
82
+
82 83
 }

+ 2 - 4
android/app/src/main/java/com/gnhz/clinic/eitc_erm_app/MainActivity.java

@@ -7,8 +7,6 @@ import android.util.Log;
7 7
 
8 8
 import androidx.annotation.NonNull;
9 9
 
10
-import com.gnhz.clinic.eitc_erm_app.sightGlass.VideoSDK;
11
-
12 10
 import java.util.HashMap;
13 11
 import java.util.Map;
14 12
 
@@ -69,9 +67,9 @@ public class MainActivity extends FlutterActivity {
69 67
 
70 68
     @SuppressLint("LongLogTag") // 用于告诉编译器忽略指定代码段的特定警告或lint检查
71 69
     private void launchApp() {
72
-        Intent intent = new Intent();
70
+       /* Intent intent = new Intent();
73 71
         intent.setClass(this, VideoSDK.class);
74
-        startActivity(intent);
72
+        startActivity(intent);*/
75 73
         System.out.println("--------------1访问成功--------------------");
76 74
 
77 75
         Log.d(CHANNEL, "The value of number is:是否 ");

+ 0 - 107
android/app/src/main/java/com/gnhz/clinic/eitc_erm_app/sightGlass/BaseActivity.java

@@ -1,107 +0,0 @@
1
-package com.example.eitc_erm_app.sightGlass;
2
-
3
-import android.app.Activity;
4
-import android.content.SharedPreferences;
5
-import android.content.res.Configuration;
6
-import android.content.res.Resources;
7
-import android.os.Bundle;
8
-import android.util.DisplayMetrics;
9
-import android.view.Window;
10
-import android.view.WindowManager;
11
-
12
-import androidx.appcompat.app.AppCompatActivity;
13
-
14
-import com.gnhz.clinic.eitc_erm_app.R;
15
-
16
-import java.util.Locale;
17
-
18
-public class BaseActivity extends Activity {
19
-    public static final String TAG = "czb";
20
-
21
-    @Override
22
-    protected void onCreate(Bundle savedInstanceState) {
23
-        super.onCreate(savedInstanceState);
24
-        //设置全面屏
25
-        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
26
-        requestWindowFeature(Window.FEATURE_NO_TITLE);
27
-        setLanguage();
28
-        setContentView(R.layout.activity_base);
29
-    }
30
-
31
-    int ReadLanguageConfig() {
32
-        SharedPreferences sharedata = getSharedPreferences("tcflanguageconfig", 0);
33
-        return sharedata.getInt("language", 1);
34
-    }
35
-
36
-    void SaveLanguageConfig(int mlg_Language) {
37
-        SharedPreferences.Editor sharepre = getSharedPreferences("tcflanguageconfig", 0).edit();
38
-        sharepre.putInt("language", mlg_Language);
39
-        sharepre.apply();
40
-    }
41
-
42
-    void setLanguage() {
43
-        Resources resources = getResources();
44
-        final Configuration configuration = resources.getConfiguration();
45
-        DisplayMetrics displayMetrics = resources.getDisplayMetrics();
46
-        switch (ReadLanguageConfig()) {
47
-            case 0:
48
-                configuration.setLocale(Locale.ENGLISH);
49
-                break;
50
-            case 1:
51
-                configuration.setLocale(Locale.SIMPLIFIED_CHINESE);
52
-                break;
53
-            case 2:
54
-                configuration.setLocale(Locale.TRADITIONAL_CHINESE);
55
-                break;
56
-            case 3:
57
-                configuration.setLocale(Locale.JAPANESE);
58
-                break;
59
-            case 4:
60
-                configuration.setLocale(Locale.FRENCH);
61
-                break;
62
-            default:
63
-                configuration.setLocale(Locale.getDefault());
64
-                break;
65
-        }
66
-        resources.updateConfiguration(configuration, displayMetrics);
67
-    }
68
-
69
-
70
-    public String[] getSSIDPWD() {
71
-        String[] strings = new String[2];
72
-        SharedPreferences sharedPreferences = getSharedPreferences("WIFISDK", MODE_PRIVATE);
73
-        strings[0] = sharedPreferences.getString("SSID", "TP-LINK_1B55");
74
-        strings[1] = sharedPreferences.getString("PWD", "aa123456");
75
-        return strings;
76
-    }
77
-
78
-    public void saveSSIDPWD(String ssid, String pwd) {
79
-        SharedPreferences.Editor sharedPreferences = getSharedPreferences("WIFISDK", MODE_PRIVATE).edit();
80
-        sharedPreferences.putString("SSID", ssid);
81
-        sharedPreferences.putString("PWD", pwd);
82
-        sharedPreferences.apply();
83
-    }
84
-    public String getString(String value) {
85
-        SharedPreferences sharedPreferences = getSharedPreferences("WIFISDK", MODE_PRIVATE);
86
-        return sharedPreferences.getString(value, "");
87
-    }
88
-
89
-    public int getInt(String value) {
90
-        SharedPreferences sharedPreferences = getSharedPreferences("WIFISDK", MODE_PRIVATE);
91
-        return sharedPreferences.getInt(value, 0);
92
-    }
93
-
94
-
95
-
96
-    public void saveInt(String key, int value) {
97
-        SharedPreferences.Editor shared = getSharedPreferences("WIFISDK", MODE_PRIVATE).edit();
98
-        shared.putInt(key, value);
99
-        shared.apply();
100
-    }
101
-
102
-    public void saveString(String key, String value) {
103
-        SharedPreferences.Editor sharedPreferences = getSharedPreferences("WIFISDK", MODE_PRIVATE).edit();
104
-        sharedPreferences.putString(key, value);
105
-        sharedPreferences.apply();
106
-    }
107
-}

+ 0 - 190
android/app/src/main/java/com/gnhz/clinic/eitc_erm_app/sightGlass/DecodeUtil.java

@@ -1,190 +0,0 @@
1
-package com.gnhz.clinic.eitc_erm_app.sightGlass;
2
-
3
-import android.media.MediaCodec;
4
-import android.media.MediaCodecInfo;
5
-import android.media.MediaFormat;
6
-import android.media.MediaMuxer;
7
-import android.util.Log;
8
-import android.view.Surface;
9
-
10
-import androidx.annotation.NonNull;
11
-
12
-import java.io.IOException;
13
-import java.nio.ByteBuffer;
14
-import java.util.concurrent.ArrayBlockingQueue;
15
-
16
-public class DecodeUtil {
17
-    private static final String TAG = "czb";
18
-    private MediaCodec mediaCodec;
19
-    public Surface mSurfaceView;
20
-    private MediaMuxer mMuxer;
21
-    private int mVideoTrackIndex, mAudioTrackIndex;
22
-    public static boolean recordMp4Flag = false;
23
-    public static ArrayBlockingQueue<byte[]> arrayBlockingQueue = new ArrayBlockingQueue<>(30);
24
-
25
-    public DecodeUtil(Surface mSurfaceView) {
26
-        this.mSurfaceView = mSurfaceView;
27
-    }
28
-
29
-    public void StartCodec() {
30
-        //===========================================
31
-        String MIME_TYPE = "video/avc";
32
-        try {
33
-            mediaCodec = MediaCodec.createDecoderByType(MIME_TYPE);
34
-        } catch (IOException e) {
35
-            e.printStackTrace();
36
-        }
37
-        MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, 1280, 720);
38
-        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
39
-        mediaCodec.setCallback(mCallBack);
40
-        mediaCodec.configure(mediaFormat, mSurfaceView, null, 0);
41
-        mediaCodec.start();
42
-        Log.e(TAG, "StartCodec: **************************************************");
43
-    }
44
-
45
-
46
-    /**
47
-     * @param filePath 需要保存的路径 record path
48
-     * @param width    视频宽度    video width
49
-     * @param height   视频高度   video height
50
-     */
51
-    public void initRecordMp4(String filePath, int width, int height) {
52
-        try {
53
-            mMuxer = new MediaMuxer(filePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
54
-        } catch (IOException e) {
55
-            e.printStackTrace();
56
-        }
57
-        MediaFormat videoMediaformat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height);
58
-
59
-        byte[] header_SPS_1080 = {0, 0, 0, 1, 103, 77, 0, 42, -99, -88, 30, 0, -119, -7, 102, -32, 32, 32, 32, 64};
60
-        byte[] header_PPS_1080 = {0, 0, 0, 1, 104, -18, 60, -128};
61
-
62
-        byte[] header_SPS_720 = {0, 0, 0, 1, 103, 66, 0, 31, -99, -88, 20, 1, 110, -101, -128, -128, -128, -127};
63
-        byte[] header_PPS_720 = {0, 0, 0, 1, 104, -50, 60, -128};
64
-
65
-        byte[] header_SPS_360 = {0, 0, 0, 1, 103, 77, 0, 30, -99, -88, 40, 11, -2, 89, -72, 8, 8, 8, 16};
66
-        byte[] header_PPS_360 = {0, 0, 0, 1, 104, -18, 60, -128};
67
-
68
-        if (width == 640 && height == 360) {
69
-            videoMediaformat.setByteBuffer("csd-0", ByteBuffer.wrap(header_SPS_360));
70
-            videoMediaformat.setByteBuffer("csd-1", ByteBuffer.wrap(header_PPS_360));//H264格式的视频需要添加
71
-            videoMediaformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);//视频数据格式
72
-            videoMediaformat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 640 * 360);//缓冲区最大值
73
-            videoMediaformat.setInteger(MediaFormat.KEY_CAPTURE_RATE, 20);//帧率
74
-        } else if (width == 1280 && height == 720) {
75
-            videoMediaformat.setByteBuffer("csd-0", ByteBuffer.wrap(header_SPS_720));
76
-            videoMediaformat.setByteBuffer("csd-1", ByteBuffer.wrap(header_PPS_720));
77
-            videoMediaformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
78
-            videoMediaformat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1280 * 720);
79
-            videoMediaformat.setInteger(MediaFormat.KEY_CAPTURE_RATE, 20);
80
-        } else {
81
-            videoMediaformat.setByteBuffer("csd-0", ByteBuffer.wrap(header_SPS_1080));
82
-            videoMediaformat.setByteBuffer("csd-1", ByteBuffer.wrap(header_PPS_1080));
83
-            videoMediaformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
84
-            videoMediaformat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080);
85
-            videoMediaformat.setInteger(MediaFormat.KEY_CAPTURE_RATE, 20);
86
-        }
87
-        videoMediaformat.setInteger(MediaFormat.KEY_BIT_RATE, width * height * 3);
88
-        mVideoTrackIndex = mMuxer.addTrack(videoMediaformat);
89
-        mMuxer.start();//开启合成器
90
-        recordMp4Flag = true;
91
-    }
92
-
93
-
94
-    public void stopRecordMp4() {
95
-        recordMp4Flag = false;
96
-        try {
97
-            mMuxer.stop();
98
-        } catch (Exception e) {
99
-            e.printStackTrace();
100
-        }
101
-        try {
102
-            mMuxer.release();
103
-        } catch (Exception e) {
104
-            e.printStackTrace();
105
-        }
106
-    }
107
-
108
-    protected long getPTSUs() {
109
-      /*  long result = System.nanoTime() / 1000L;
110
-        if (result < 0) {
111
-            result = (-result) + result;
112
-        }*/
113
-        return System.nanoTime() / 1000L;
114
-    }
115
-
116
-    long timerCount = 0;
117
-    MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
118
-    private final MediaCodec.Callback mCallBack = new MediaCodec.Callback() {
119
-        @Override
120
-        public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
121
-            byte[] bytes = arrayBlockingQueue.poll();
122
-            if (bytes != null) {
123
-                //  codec.getInputBuffer(index).put(bytes);
124
-                ByteBuffer byteBuffer = codec.getInputBuffer(index);
125
-                byteBuffer.put(bytes, 0, bytes.length);
126
-                if (recordMp4Flag && (bytes.length > 0)) {
127
-                    //  if (isFirstFrame) {
128
-                    // Log.e(TAG, "onInputBufferAvailable: " + bytes[4]);
129
-                    bufferInfo.offset = 0;
130
-                    bufferInfo.size = bytes.length;  ///*naluIndex*/视频流数据的大小;
131
-                    if ((bytes[4] & 0x1f) == 5) {
132
-                        bufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;//I帧
133
-                    } else if ((bytes[4] & 0x1f) == 7 || (bytes[4] & 0x1f) == 8 || (bytes[4] & 0x1f) == 6) {
134
-                        bufferInfo.flags = MediaCodec.BUFFER_FLAG_CODEC_CONFIG;//B,P帧
135
-                    } else {
136
-                        bufferInfo.flags = 0;//SEI
137
-                    }
138
-                    bufferInfo.presentationTimeUs = getPTSUs();
139
-                    mMuxer.writeSampleData(mVideoTrackIndex, byteBuffer, bufferInfo);
140
-                    // }
141
-                }
142
-                codec.queueInputBuffer(index, 0, bytes.length, timerCount++, 0);
143
-
144
-
145
-            } else {
146
-                codec.queueInputBuffer(index, 0, 0, timerCount++, 0);
147
-            }
148
-        }
149
-
150
-        @Override
151
-        public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {
152
-            codec.releaseOutputBuffer(index, true);
153
-        }
154
-
155
-        @Override
156
-        public void onError(@NonNull MediaCodec codec, @NonNull MediaCodec.CodecException e) {
157
-
158
-        }
159
-
160
-        @Override
161
-        public void onOutputFormatChanged(@NonNull MediaCodec codec, @NonNull MediaFormat format) {
162
-
163
-        }
164
-    };
165
-
166
-
167
-    public void StopCodec() {
168
-        //硬解码是调用c,需要释放掉内存
169
-
170
-        //  mediaCodec.setCallback(null);
171
-        try {
172
-            if (mediaCodec != null) {
173
-                mediaCodec.stop();
174
-                Log.e(TAG, "stopShotCodec: stop");
175
-            }
176
-        } catch (Exception e) {
177
-            e.printStackTrace();
178
-            Log.e(TAG, "StopCodec: 失败了!");
179
-        }
180
-        try {
181
-            if (mediaCodec != null) {
182
-                mediaCodec.release();
183
-                Log.e(TAG, "stopShotCodec: release");
184
-            }
185
-        } catch (Exception e) {
186
-            e.printStackTrace();
187
-        }
188
-        mediaCodec = null;
189
-    }
190
-}

+ 0 - 418
android/app/src/main/java/com/gnhz/clinic/eitc_erm_app/sightGlass/MyXUtil.java

@@ -1,418 +0,0 @@
1
-package com.gnhz.clinic.eitc_erm_app.sightGlass;
2
-
3
-import android.Manifest;
4
-import android.app.Activity;
5
-import android.content.Context;
6
-import android.content.pm.PackageManager;
7
-import android.graphics.ImageFormat;
8
-import android.graphics.Rect;
9
-import android.graphics.YuvImage;
10
-import android.media.Image;
11
-import android.os.Environment;
12
-import android.util.DisplayMetrics;
13
-import android.util.Log;
14
-import android.view.Display;
15
-import android.view.WindowManager;
16
-import android.view.inputmethod.InputMethodManager;
17
-
18
-import androidx.core.app.ActivityCompat;
19
-
20
-import java.io.File;
21
-import java.io.FileOutputStream;
22
-import java.io.IOException;
23
-import java.net.DatagramPacket;
24
-import java.net.DatagramSocket;
25
-import java.net.InetAddress;
26
-import java.net.SocketException;
27
-import java.net.UnknownHostException;
28
-import java.nio.ByteBuffer;
29
-import java.util.ArrayList;
30
-import java.util.Arrays;
31
-import java.util.List;
32
-
33
-public class MyXUtil {
34
-
35
-    public static final boolean DEBUGMODE = false;
36
-    private static final String TAG = "czb";
37
-    public static String devIP = "192.168.1.1";
38
-    public static String nowIP = "192.168.1.1";
39
-    public static ArrayList<Integer> portList = new ArrayList<Integer>(Arrays.asList(40003, 40031, 40121, 40101));
40
-    //public static ArrayList<Integer> portList = new ArrayList<Integer>(Arrays.asList(40031, 40121, 40101, 40003));
41
-    public static int nowPort = 40003;
42
-    public static boolean h264PlayFlag = false;
43
-    public static boolean ketThreadFlag = false;
44
-
45
-    public static void setDevIP(String devIP) {
46
-        MyXUtil.devIP = devIP;
47
-    }
48
-
49
-    public static String getDevIP() {
50
-        return getDeviceIP();
51
-    }
52
-
53
-    //发送查找信号
54
-    public static void sendSearchIPOrder() {
55
-        Log.e(TAG, "MyXUtil.sendSearchIPOrder");
56
-        com.gnhz.clinic.eitc_erm_app.sightGlass.ThreadPoolHelper.executeTask(new Runnable() {
57
-            @Override
58
-            public void run() {
59
-                DatagramSocket socket = null;
60
-                try {
61
-                    socket = new DatagramSocket();
62
-                } catch (SocketException e) {
63
-                    e.printStackTrace();
64
-                    return;
65
-                }
66
-                byte[] buf = new byte[20];
67
-                buf[0] = 0x3f;
68
-                buf[1] = 0x2f;
69
-                //将数据打包
70
-                DatagramPacket packet = null;
71
-                try {
72
-                    packet = new DatagramPacket(buf, buf.length, InetAddress.getByName("255.255.255.255"), 40011);
73
-                } catch (UnknownHostException e) {
74
-                    e.printStackTrace();
75
-                    socket.close();
76
-                    return;
77
-                }
78
-                try {
79
-                    socket.send(packet);
80
-                } catch (IOException e) {
81
-                    e.printStackTrace();
82
-                    socket.close();
83
-                    return;
84
-                }
85
-                socket.close();
86
-                Log.e(TAG, "run: udp发送已经关闭******************");
87
-            }
88
-        });
89
-    }
90
-
91
-    private static String getDeviceIP() {
92
-        Log.e(TAG, "MyXUtil.getDeviceIP");
93
-        DatagramSocket recvClient = null;
94
-        byte[] buffer = new byte[20];
95
-        int port = 40012;
96
-        String deviceIP = null;
97
-        try {
98
-            recvClient = new DatagramSocket(port);
99
-        } catch (IOException e) {
100
-            e.printStackTrace();
101
-            return null;
102
-        }
103
-        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
104
-        sendSearchIPOrder();
105
-        try {
106
-            recvClient.setSoTimeout(3000);
107
-        } catch (SocketException e) {
108
-            e.printStackTrace();
109
-        }
110
-        try {
111
-            recvClient.receive(packet);
112
-        } catch (IOException e) {
113
-            e.printStackTrace();
114
-            recvClient.close();
115
-            Log.e(TAG, "getDeviceIP: 接收超时--");
116
-            return null;
117
-        }
118
-        deviceIP = packet.getAddress().toString().substring(1);
119
-        recvClient.close();
120
-        Log.e(TAG, "run: udp接收已经关闭******************");
121
-
122
-        if (!recvClient.isClosed()) {
123
-            recvClient.close();
124
-            Log.e(TAG, "finally run: udp接收已经关闭******************");
125
-        }
126
-        return deviceIP;
127
-    }
128
-
129
-    /**
130
-     * 判断当前设备是手机还是平板,代码来自 Google I/O App for Android
131
-     *
132
-     * @param context
133
-     * @param context 上下文
134
-     * @return 平板返回 True,手机返回 False
135
-     * <p>
136
-     * public static boolean isPad(Context context) {
137
-     * return isPad_normal(context) && isPad_size(context);
138
-     * }
139
-     * <p>
140
-     * private static boolean isPad_normal(Context context) {
141
-     * return (context.getResources().getConfiguration().screenLayout
142
-     * & Configuration.SCREENLAYOUT_SIZE_MASK)
143
-     * >= Configuration.SCREENLAYOUT_SIZE_LARGE;
144
-     * }
145
-     * <p>
146
-     * /**
147
-     * 大小判断是否是平板
148
-     * @return 是平板则返回true,反之返回false
149
-     */
150
-    private static boolean isPad_size(Context context) {
151
-        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
152
-        Display display = wm.getDefaultDisplay();
153
-        DisplayMetrics dm = new DisplayMetrics();
154
-        display.getMetrics(dm);
155
-        double x = Math.pow(dm.widthPixels / dm.xdpi, 2);
156
-        double y = Math.pow(dm.heightPixels / dm.ydpi, 2);
157
-        double screenInches = Math.sqrt(x + y); // 屏幕尺寸
158
-        return screenInches >= 7.3;   //华为mate20x的尺寸时7.2,应该是最大的了吧。。。
159
-    }
160
-
161
-    public static void compressToJpeg2(String fileName, Image image) {
162
-        FileOutputStream outStream;
163
-        try {
164
-            outStream = new FileOutputStream(fileName);
165
-        } catch (IOException ioe) {
166
-            throw new RuntimeException("Unable to create output file " + fileName, ioe);
167
-        }
168
-        Rect rect = image.getCropRect();
169
-        YuvImage yuvImage = toYuvImage(image);
170
-        yuvImage.compressToJpeg(rect, 100, outStream);
171
-        try {
172
-            outStream.close();
173
-        } catch (IOException e) {
174
-            e.printStackTrace();
175
-        }
176
-    }
177
-
178
-
179
-    private static YuvImage toYuvImage(Image image) {
180
-        if (image.getFormat() != ImageFormat.YUV_420_888) {
181
-            throw new IllegalArgumentException("Invalid image format");
182
-        }
183
-
184
-        int width = image.getWidth();
185
-        int height = image.getHeight();
186
-
187
-        // Order of U/V channel guaranteed, read more:
188
-        // https://developer.android.com/reference/android/graphics/ImageFormat#YUV_420_888
189
-        Image.Plane yPlane = image.getPlanes()[0];
190
-        Image.Plane uPlane = image.getPlanes()[1];
191
-        Image.Plane vPlane = image.getPlanes()[2];
192
-
193
-        ByteBuffer yBuffer = yPlane.getBuffer();
194
-        ByteBuffer uBuffer = uPlane.getBuffer();
195
-        ByteBuffer vBuffer = vPlane.getBuffer();
196
-
197
-        // Full size Y channel and quarter size U+V channels.
198
-        int numPixels = (int) (width * height * 1.5f);
199
-        byte[] nv21 = new byte[numPixels];
200
-        int index = 0;
201
-
202
-        // Copy Y channel.
203
-        int yRowStride = yPlane.getRowStride();
204
-        int yPixelStride = yPlane.getPixelStride();
205
-        for (int y = 0; y < height; ++y) {
206
-            for (int x = 0; x < width; ++x) {
207
-                nv21[index++] = yBuffer.get(y * yRowStride + x * yPixelStride);
208
-            }
209
-        }
210
-
211
-        // Copy VU data; NV21 format is expected to have YYYYVU packaging.
212
-        // The U/V planes are guaranteed to have the same row stride and pixel stride.
213
-        int uvRowStride = uPlane.getRowStride();
214
-        int uvPixelStride = uPlane.getPixelStride();
215
-        int uvWidth = width / 2;
216
-        int uvHeight = height / 2;
217
-
218
-        for (int y = 0; y < uvHeight; ++y) {
219
-            for (int x = 0; x < uvWidth; ++x) {
220
-                int bufferIndex = (y * uvRowStride) + (x * uvPixelStride);
221
-                // V channel.
222
-                nv21[index++] = vBuffer.get(bufferIndex);
223
-                // U channel.
224
-                nv21[index++] = uBuffer.get(bufferIndex);
225
-            }
226
-        }
227
-        return new YuvImage(nv21, ImageFormat.NV21, width, height, /* strides= */ null);
228
-    }
229
-
230
-
231
-    private static final int COLOR_FormatI420 = 1;
232
-    private static final int COLOR_FormatNV21 = 2;
233
-
234
-    private static boolean isImageFormatSupported(Image image) {
235
-        int format = image.getFormat();
236
-        switch (format) {
237
-            case ImageFormat.YUV_420_888:
238
-            case ImageFormat.NV21:
239
-            case ImageFormat.YV12:
240
-                return true;
241
-        }
242
-        return false;
243
-    }
244
-
245
-    private static byte[] getDataFromImage(Image image, int colorFormat) {
246
-        if (colorFormat != COLOR_FormatI420 && colorFormat != COLOR_FormatNV21) {
247
-            throw new IllegalArgumentException("only support COLOR_FormatI420 " + "and COLOR_FormatNV21");
248
-        }
249
-        if (!isImageFormatSupported(image)) {
250
-            throw new RuntimeException("can't convert Image to byte array, format " + image.getFormat());
251
-        }
252
-        Rect crop = image.getCropRect();
253
-        int format = image.getFormat();
254
-        int width = crop.width();
255
-        int height = crop.height();
256
-        Image.Plane[] planes = image.getPlanes();
257
-        byte[] data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
258
-        byte[] rowData = new byte[planes[0].getRowStride()];
259
-        int channelOffset = 0;
260
-        int outputStride = 1;
261
-        for (int i = 0; i < planes.length; i++) {
262
-            switch (i) {
263
-                case 0:
264
-                    channelOffset = 0;
265
-                    outputStride = 1;
266
-                    break;
267
-                case 1:
268
-                    if (colorFormat == COLOR_FormatI420) {
269
-                        channelOffset = width * height;
270
-                        outputStride = 1;
271
-                    } else if (colorFormat == COLOR_FormatNV21) {
272
-                        channelOffset = width * height + 1;
273
-                        outputStride = 2;
274
-                    }
275
-                    break;
276
-                case 2:
277
-                    if (colorFormat == COLOR_FormatI420) {
278
-                        channelOffset = (int) (width * height * 1.25);
279
-                        outputStride = 1;
280
-                    } else if (colorFormat == COLOR_FormatNV21) {
281
-                        channelOffset = width * height;
282
-                        outputStride = 2;
283
-                    }
284
-                    break;
285
-            }
286
-            ByteBuffer buffer = planes[i].getBuffer();
287
-            int rowStride = planes[i].getRowStride();
288
-            int pixelStride = planes[i].getPixelStride();
289
-            int shift = (i == 0) ? 0 : 1;
290
-            int w = width >> shift;
291
-            int h = height >> shift;
292
-            buffer.position(rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift));
293
-            for (int row = 0; row < h; row++) {
294
-                int length;
295
-                if (pixelStride == 1 && outputStride == 1) {
296
-                    length = w;
297
-                    buffer.get(data, channelOffset, length);
298
-                    channelOffset += length;
299
-                } else {
300
-                    length = (w - 1) * pixelStride + 1;
301
-                    buffer.get(rowData, 0, length);
302
-                    for (int col = 0; col < w; col++) {
303
-                        data[channelOffset] = rowData[col * pixelStride];
304
-                        channelOffset += outputStride;
305
-                    }
306
-                }
307
-                if (row < h - 1) {
308
-                    buffer.position(buffer.position() + rowStride - length);
309
-                }
310
-            }
311
-        }
312
-        return data;
313
-    }
314
-
315
-    public static void compressToJpeg(String fileName, Image image) {
316
-        FileOutputStream outStream;
317
-        try {
318
-            outStream = new FileOutputStream(fileName);
319
-        } catch (IOException ioe) {
320
-            Log.e(TAG, "compressToJpeg: 创建fileoutputstream失败");
321
-            throw new RuntimeException("Unable to create output file " + fileName, ioe);
322
-        }
323
-        Rect rect = image.getCropRect();
324
-        Log.e(TAG, "compressToJpeg: yuvimag之前");
325
-        YuvImage yuvImage = new YuvImage(getDataFromImage(image, COLOR_FormatNV21), ImageFormat.NV21, rect.width(), rect.height(), null);
326
-        Log.e(TAG, "compressToJpeg: yuvimag之后");
327
-        yuvImage.compressToJpeg(rect, 100, outStream);
328
-        try {
329
-            outStream.close();
330
-        } catch (IOException e) {
331
-            e.printStackTrace();
332
-        }
333
-    }
334
-
335
-
336
-    // 隐藏键盘
337
-    public static void hideKeyBoard(Activity activity) {
338
-        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
339
-        if (imm != null) {
340
-            imm.hideSoftInputFromWindow(activity.getWindow().getDecorView().getWindowToken(), 0);
341
-        }
342
-    }
343
-
344
-/*    public static void showDevGrop(DevGroup devGroup) {
345
-        Log.e(TAG, "showDevGrop: " + devGroup.devid0 + "------" + devGroup.devid0ip);
346
-        Log.e(TAG, "showDevGrop: " + devGroup.devid1 + "------" + devGroup.devid1ip);
347
-        Log.e(TAG, "showDevGrop: " + devGroup.devid2 + "------" + devGroup.devid2ip);
348
-        Log.e(TAG, "showDevGrop: " + devGroup.devid3 + "------" + devGroup.devid3ip);
349
-        Log.e(TAG, "showDevGrop: " + devGroup.devid4 + "------" + devGroup.devid4ip);
350
-    }*/
351
-
352
-    public static String getSdPath(Context context) {
353
-        boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
354
-        //  int version = android.os.Build.VERSION.SDK_INT;
355
-        if (sdCardExist) {
356
-            File externalStorageDirectory = Environment.getExternalStorageDirectory();
357
-            return externalStorageDirectory.toString() + "/Download/WIFISDK/";
358
-        }
359
-        return null;
360
-    }
361
-
362
-    public static String getSdPath() {
363
-        boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
364
-        //  int version = android.os.Build.VERSION.SDK_INT;
365
-        if (sdCardExist) {
366
-            File externalStorageDirectory = Environment.getExternalStorageDirectory();
367
-            return externalStorageDirectory.toString() + "/Download/WIFISDK/";
368
-        }
369
-        return null;
370
-    }
371
-
372
-    public static List<String> getFilesAllName(String path) {
373
-        //传入指定文件夹的路径
374
-        Log.e("debug", "getFilesAllName: " + path);
375
-        File file = new File(path);
376
-        File[] files = file.listFiles();
377
-        if (files != null) {
378
-            List<String> imagePaths = new ArrayList<>();
379
-            for (File value : files) {
380
-                if (checkIsImageFile(value.getPath())) {
381
-                    imagePaths.add(value.getPath());
382
-                }
383
-            }
384
-            return imagePaths;
385
-        } else {
386
-            Log.e(TAG, "getFilesAllName: ++++++++++++里面啥都没有!!");
387
-        }
388
-        return null;
389
-    }
390
-
391
-    /**
392
-     * 判断是否是照片
393
-     */
394
-    public static boolean checkIsImageFile(String fName) {
395
-        //获取拓展名
396
-        String fileEnd = fName.substring(fName.lastIndexOf(".") + 1).toLowerCase();
397
-        return "jpg".equals(fileEnd) || "png".equals(fileEnd) || "jpeg".equals(fileEnd) || "bmp".equals(fileEnd);
398
-    }
399
-
400
-    private static final int REQUEST_EXTERNAL_STORAGE = 1;
401
-    private static String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
402
-
403
-    /**
404
-     * Checks if the app has permission to write to device storage
405
-     * If the app does not has permission then the user will be prompted to grant permissions
406
-     */
407
-
408
-    public static void verifyStoragePermissions(Activity activity) {
409
-        // Check if we have write permission
410
-        int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
411
-        if (permission != PackageManager.PERMISSION_GRANTED) {
412
-            // We don't have permission so prompt the user
413
-            ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
414
-        }
415
-    }
416
-
417
-
418
-}

+ 0 - 18
android/app/src/main/java/com/gnhz/clinic/eitc_erm_app/sightGlass/ServerSocketUtil.java

@@ -1,18 +0,0 @@
1
-package com.gnhz.clinic.eitc_erm_app.sightGlass;
2
-
3
-import java.io.IOException;
4
-import java.net.ServerSocket;
5
-
6
-public class ServerSocketUtil {
7
-    public static ServerSocket serverSocket;
8
-
9
-    public static void closeServerSocket() {
10
-        if (serverSocket != null && !serverSocket.isClosed()) {
11
-            try {
12
-                serverSocket.close();
13
-            } catch (IOException e) {
14
-                e.printStackTrace();
15
-            }
16
-        }
17
-    }
18
-}

+ 0 - 68
android/app/src/main/java/com/gnhz/clinic/eitc_erm_app/sightGlass/ThreadPoolHelper.java

@@ -1,68 +0,0 @@
1
-package com.gnhz.clinic.eitc_erm_app.sightGlass;
2
-
3
-import android.util.Log;
4
-
5
-import org.apache.commons.lang3.concurrent.BasicThreadFactory;
6
-
7
-import java.util.concurrent.ScheduledThreadPoolExecutor;
8
-import java.util.concurrent.ThreadPoolExecutor;
9
-import java.util.concurrent.TimeUnit;
10
-
11
-public class ThreadPoolHelper {
12
-    /*线程池大小*/
13
-    private static final int POOL_SIZE = 10;
14
-    private static final String TAG = "czb";
15
-
16
-    //订单任务线程池
17
-
18
-    private static ThreadPoolExecutor comitTaskPool = (ThreadPoolExecutor) new ScheduledThreadPoolExecutor(POOL_SIZE,
19
-            new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
20
-
21
-
22
-    /**
23
-     * 执行订单任务
24
-     *
25
-     * @param comitTask
26
-     */
27
-    public static void executeTask(Runnable comitTask) {
28
-        comitTaskPool.execute(comitTask);
29
-        Log.e("debug", "【线程池任务】线程池中线程数:" + comitTaskPool.getPoolSize());
30
-        Log.e("debug", "【线程池任务】队列中等待执行的任务数:" + comitTaskPool.getQueue().size());
31
-        // Log.e("debug","【线程池任务】已执行完任务数:" + comitTaskPool.getCompletedTaskCount());
32
-    }
33
-
34
-
35
-    /**
36
-     * 关闭线程池
37
-     */
38
-    public static void shutdown() {
39
-        Log.e(TAG, "shutdown comitTaskPool...");
40
-        comitTaskPool.shutdown();
41
-        try {
42
-            if (!comitTaskPool.isTerminated()) {
43
-                Log.e(TAG, "shutdown: 直接关闭失败[" + comitTaskPool.toString() + "]");
44
-
45
-                comitTaskPool.awaitTermination(3, TimeUnit.SECONDS);
46
-                if (comitTaskPool.isTerminated()) {
47
-                    Log.e(TAG, "shutdown: 成功关闭[" + comitTaskPool.toString() + "]");
48
-
49
-                } else {
50
-                    Log.e(TAG, "[" + comitTaskPool.toString() + "]关闭失败,执行shutdownNow...");
51
-                    if (comitTaskPool.shutdownNow().size() > 0) {
52
-                        Log.e(TAG, "[" + comitTaskPool.toString() + "]没有关闭成功");
53
-                    } else {
54
-                        Log.e(TAG, "shutdown: shutdownNow执行完毕,成功关闭[" + comitTaskPool.toString() + "]");
55
-
56
-                    }
57
-                }
58
-            } else {
59
-                Log.e(TAG, "shutdown: 成功关闭[" + comitTaskPool.toString() + "]");
60
-
61
-            }
62
-        } catch (InterruptedException e) {
63
-            Log.e(TAG, "shutdown: 接收到中断请" + comitTaskPool.toString() + "停止操作");
64
-
65
-        }
66
-    }
67
-
68
-}

+ 0 - 303
android/app/src/main/java/com/gnhz/clinic/eitc_erm_app/sightGlass/Video.java

@@ -1,303 +0,0 @@
1
-package com.gnhz.clinic.eitc_erm_app.sightGlass;
2
-
3
-import android.os.Bundle;
4
-import android.os.Handler;
5
-import android.os.Message;
6
-import android.util.Log;
7
-
8
-import java.io.BufferedInputStream;
9
-import java.io.IOException;
10
-import java.io.OutputStream;
11
-import java.net.InetSocketAddress;
12
-import java.net.ServerSocket;
13
-import java.net.Socket;
14
-import java.net.SocketAddress;
15
-
16
-public class Video {
17
-    private static final String TAG = "czb";
18
-    private static final int READ_MAX_LEN = 8192 * 2;
19
-    /*一般H264帧大小不超过200k,如果解码失败可以尝试增大这个值*/
20
-    private static int FRAME_MAX_LEN = 500 * 1024;
21
-    private boolean DecodeModeUser = true;
22
-    //解码后显示的surface及其宽高
23
-    private Socket sock;
24
-    private BufferedInputStream is;
25
-    private OutputStream os;
26
-
27
-    private int mTrans = 0x0F0F0F0F;
28
-    private Handler handler;
29
-    private DecodeUtil decodeUtil;
30
-
31
-
32
-    public Video(Handler handler, DecodeUtil decodeUtil) {
33
-        this.handler = handler;
34
-        this.decodeUtil = decodeUtil;
35
-    }
36
-
37
-    /**
38
-     * 连接验证
39
-     *
40
-     * @param os
41
-     */
42
-    private void sendHandleMes(OutputStream os) {
43
-        byte[] SockBuf = new byte[12];
44
-        SockBuf[0] = 0x5f;
45
-        SockBuf[1] = 0x6f;
46
-        SockBuf[10] = (byte) 11;
47
-        SockBuf[11] = (byte) 0;
48
-        try {
49
-            os.write(SockBuf, 0, 12);
50
-        } catch (IOException e) {
51
-            e.printStackTrace();
52
-        }
53
-    }
54
-
55
-    int tempI;
56
-    byte Temp;
57
-
58
-    int MergeBuffer(byte[] NalBuf, int NalBufUsed, byte[] SockBuf, int SockBufUsed, int SockRemain) {
59
-
60
-        for (tempI = 0; tempI < SockRemain; tempI++) {
61
-            Temp = SockBuf[tempI + SockBufUsed];
62
-            NalBuf[tempI + NalBufUsed] = Temp;
63
-            mTrans <<= 8;
64
-            mTrans |= Temp;
65
-            if (mTrans == 1) {
66
-                tempI++;
67
-                break;
68
-            }
69
-        }
70
-        return tempI;
71
-    }
72
-
73
-    private void checkSocket(Socket socket) {
74
-        if (socket != null && !socket.isClosed()) {
75
-            try {
76
-                socket.close();
77
-                Log.e(TAG, "checkSocket: closed!");
78
-            } catch (IOException e) {
79
-                e.printStackTrace();
80
-            }
81
-        }
82
-    }
83
-
84
-    private boolean connectSocketIsOK(String ip, int port) {
85
-        // checkSocket(sock);
86
-        SocketAddress socketAddress = new InetSocketAddress(ip, port);
87
-        try {
88
-            sock = null;
89
-            sock = new Socket();
90
-            sock.connect(socketAddress, 2000);
91
-            com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag = true;
92
-            /// sock = socket;
93
-            Log.e(TAG, "socketH264Player: connect success!");
94
-        } catch (IOException e) {
95
-            e.printStackTrace();
96
-            Log.e(TAG, "socketH264Player: connect failed!");
97
-            com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag = false;
98
-        }
99
-        return com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag;
100
-    }
101
-
102
-    public void startVideoDecode() {
103
-        int i = 0;
104
-        for (i = 0; i < com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.size(); i++) {
105
-            if (connectSocketIsOK("192.168.1.1", com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.get(i))) {
106
-                com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.nowPort = com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.get(i);
107
-                Log.e(TAG, "MyXUtil.nowPort " + com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.nowPort);
108
-                break;
109
-            }
110
-        }
111
-        if (!com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag) {
112
-            String devIP = com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.getDevIP();
113
-            if (devIP == null) {
114
-                handler.sendEmptyMessage(3);
115
-                return;
116
-            }
117
-            for (i = 0; i < com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.size(); i++) {
118
-                if (connectSocketIsOK(devIP, com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.get(i))) {
119
-                    com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.nowIP = devIP;
120
-                    com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.nowPort = com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.portList.get(i);
121
-                    break;
122
-                }
123
-            }
124
-        }
125
-        if (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag) {
126
-            Log.e(TAG, "startVideoDecode: sockt已经连接成功了!");
127
-            int nalLen;
128
-            int SockBufUsed;
129
-            int bytesRead = 0;
130
-            int NalBufUsed = 0;
131
-            byte[] frame = new byte[FRAME_MAX_LEN];
132
-            byte[] SockBuf = new byte[READ_MAX_LEN];
133
-            try {
134
-                is = new BufferedInputStream(sock.getInputStream());
135
-            } catch (IOException e) {
136
-                e.printStackTrace();
137
-            }
138
-            try {
139
-                os = sock.getOutputStream();
140
-            } catch (IOException e) {
141
-                e.printStackTrace();
142
-            }
143
-            sendHandleMes(os);
144
-            handler.sendEmptyMessage(3);
145
-            //循环读取数据
146
-            while (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag) {
147
-                try {
148
-                    assert is != null;
149
-                    bytesRead = is.read(SockBuf, 0, READ_MAX_LEN);
150
-                } catch (IOException | AssertionError e) {
151
-                    e.printStackTrace();
152
-                    Log.d(TAG, "run: 40003端口读取超时或者出错********************");
153
-                    handler.sendEmptyMessage(7);
154
-                }
155
-                SockBufUsed = 0;
156
-                while (bytesRead - SockBufUsed > 0) {
157
-                    nalLen = MergeBuffer(frame, NalBufUsed, SockBuf, SockBufUsed, bytesRead - SockBufUsed);
158
-                    NalBufUsed += nalLen;
159
-                    SockBufUsed += nalLen;
160
-                    //找到了就执行下面的解码,没有找到就继续循环读取数据,直到找到帧头
161
-                    if (mTrans == 1) {
162
-                        mTrans = 0x0F0F0F0F;
163
-                        if (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag && decodeUtil != null) {
164
-                            // decodeUtil.DecodeFrame(frame, 0, NalBufUsed - 4);
165
-                            byte[] bytes = new byte[NalBufUsed - 4];
166
-                            System.arraycopy(frame, 0, bytes, 0, NalBufUsed - 4);
167
-                            try {
168
-                                DecodeUtil.arrayBlockingQueue.put(bytes);
169
-                            } catch (InterruptedException e) {
170
-                                e.printStackTrace();
171
-                            }
172
-                        }
173
-                        frame[0] = 0;
174
-                        frame[1] = 0;
175
-                        frame[2] = 0;
176
-                        frame[3] = 1;
177
-                        NalBufUsed = 4;
178
-                    }
179
-                }
180
-            }
181
-
182
-        } else {
183
-            handler.sendEmptyMessage(3);
184
-            Log.e(TAG, "stratVideoDecode: socket连接失败----");
185
-        }
186
-        Log.e(TAG, "stratVideoDecode: 结束解码,已经结束咧!*******************");
187
-    }
188
-
189
-
190
-    private void showCapJpg(String filename) {
191
-        Message msg = Message.obtain();
192
-        msg.what = 4;
193
-        Bundle bundle = new Bundle();
194
-        bundle.putString("filename", filename);
195
-        msg.setData(bundle);
196
-        handler.sendMessage(msg);
197
-    }
198
-
199
-
200
-    public void StartKeyScanThread() {
201
-        try {
202
-            com.gnhz.clinic.eitc_erm_app.sightGlass.ServerSocketUtil.serverSocket = new ServerSocket(40004);
203
-            com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag = true;
204
-        } catch (IOException e) {
205
-            e.printStackTrace();
206
-            com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag = false;
207
-        }
208
-        if (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag) {
209
-            byte[] SockBuf = new byte[22];
210
-            int bytesRead = 0;
211
-            Socket client = null;
212
-            while (com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag) {
213
-                try {
214
-                    client = com.gnhz.clinic.eitc_erm_app.sightGlass.ServerSocketUtil.serverSocket.accept();
215
-                } catch (IOException e) {
216
-                    e.printStackTrace();
217
-                    com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.ketThreadFlag = false;
218
-                    continue;
219
-                }
220
-                try {
221
-                    bytesRead = client.getInputStream().read(SockBuf, 0, SockBuf.length);
222
-                } catch (IOException | AssertionError e) {
223
-                    e.printStackTrace();
224
-                }
225
-                if ((bytesRead == 10) && (SockBuf[8] == 0)) {
226
-                    handler.sendEmptyMessage(4);
227
-                    Log.e(TAG, "run: button-0");
228
-                } else if ((bytesRead == 10) && (SockBuf[8] == 1)) {
229
-                    handler.sendEmptyMessage(4);
230
-                    Log.e(TAG, "run: button-1");
231
-                } else if ((bytesRead == 10) && (SockBuf[8] == 20)) {
232
-                    handler.sendEmptyMessage(20);
233
-                    Log.e(TAG, "StartKeyScanThread: 20");
234
-                } else if ((bytesRead == 10) && (SockBuf[8] == 21)) {
235
-                    handler.sendEmptyMessage(21);
236
-                    Log.e(TAG, "StartKeyScanThread: 21");
237
-                } else if ((bytesRead == 10) && (SockBuf[8] == 22)) {
238
-                    handler.sendEmptyMessage(22);
239
-                    Log.e(TAG, "StartKeyScanThread: 22");
240
-                } else if ((bytesRead == 10) && (SockBuf[8] == 23)) {
241
-                    handler.sendEmptyMessage(23);
242
-                    Log.e(TAG, "StartKeyScanThread: 23");
243
-                }
244
-                if (!client.isClosed()) {
245
-                    if (!client.isInputShutdown()) {
246
-                        try {
247
-                            client.shutdownInput();
248
-                        } catch (IOException e) {
249
-                            e.printStackTrace();
250
-                        }
251
-                    }
252
-                    try {
253
-                        client.close();
254
-                    } catch (IOException e) {
255
-                        e.printStackTrace();
256
-                    }
257
-                    client = null;
258
-                }
259
-            }
260
-            Log.e(TAG, "SatrtKeyScanThread: 服务器已经结束咧------");
261
-        }
262
-    }
263
-
264
-    public void closeSocket() {
265
-        com.gnhz.clinic.eitc_erm_app.sightGlass.MyXUtil.h264PlayFlag = false;
266
-        if (sock != null && !sock.isClosed()) {
267
-
268
-            if (!sock.isInputShutdown()) {
269
-                try {
270
-                    sock.shutdownInput();
271
-                } catch (IOException e) {
272
-                    e.printStackTrace();
273
-                }
274
-            }
275
-            if (!sock.isOutputShutdown()) {
276
-                try {
277
-                    sock.shutdownOutput();
278
-                } catch (IOException e) {
279
-                    e.printStackTrace();
280
-                }
281
-            }
282
-            if (!sock.isClosed()) {
283
-                try {
284
-                    sock.close();
285
-                } catch (IOException e) {
286
-                    e.printStackTrace();
287
-                }
288
-            }
289
-            sock = null;
290
-            Log.e(TAG, "closeSocket: socket已经关闭咧!");
291
-        }
292
-    }
293
-
294
-    public void showsdjpg(String filename, boolean newfile) {
295
-        Message msg = new Message();
296
-        msg.what = 6;
297
-        Bundle bundle = new Bundle();
298
-        bundle.putString("filename", filename);
299
-        bundle.putBoolean("newfile", newfile);
300
-        msg.setData(bundle);
301
-        handler.sendMessage(msg);
302
-    }
303
-}

+ 0 - 511
android/app/src/main/java/com/gnhz/clinic/eitc_erm_app/sightGlass/VideoSDK.java

@@ -1,511 +0,0 @@
1
-package com.gnhz.clinic.eitc_erm_app.sightGlass;
2
-
3
-import android.Manifest;
4
-import android.annotation.SuppressLint;
5
-import android.content.Intent;
6
-import android.content.pm.PackageManager;
7
-import android.content.res.Configuration;
8
-import android.graphics.Bitmap;
9
-import android.os.Build;
10
-import android.os.Bundle;
11
-import android.os.Handler;
12
-import android.os.Message;
13
-import android.util.Log;
14
-import android.view.KeyEvent;
15
-import android.view.PixelCopy;
16
-import android.view.SurfaceHolder;
17
-import android.view.SurfaceView;
18
-import android.view.View;
19
-import android.view.WindowManager;
20
-import android.widget.Button;
21
-import android.widget.ImageButton;
22
-import android.widget.ImageView;
23
-import android.widget.ProgressBar;
24
-import android.widget.TextView;
25
-import android.widget.Toast;
26
-
27
-import androidx.annotation.NonNull;
28
-import androidx.appcompat.content.res.AppCompatResources;
29
-
30
-import com.github.chrisbanes.photoview.PhotoView;
31
-import com.gnhz.clinic.eitc_erm_app.BuildConfig;
32
-import com.gnhz.clinic.eitc_erm_app.MainActivity;
33
-import com.gnhz.clinic.eitc_erm_app.R;
34
-
35
-import java.util.Timer;
36
-import java.util.TimerTask;
37
-
38
-public class VideoSDK extends com.example.eitc_erm_app.sightGlass.BaseActivity {
39
-    public Video videoDecoder;
40
-    public SurfaceView mSurfaceView;
41
-    private ProgressBar progressBar;
42
-    private PhotoView clickView;
43
-    private ImageView getImage;
44
-    public Button deleteChecked;
45
-    public Button checkAll;
46
-    public Button cancelAll;
47
-    private TextView textView;
48
-    private ImageView restart;
49
-    private Button recordButton;
50
-
51
-    private DecodeUtil decodeUtil;
52
-    private TextView sdkversion;
53
-    private TextView devversion;
54
-    private Button videobuttonStop;
55
-    public static int fpsCount = 0;
56
-    private Timer t = null;
57
-    private final Handler handler = new Handler(new Handler.Callback() {
58
-        @Override
59
-        public boolean handleMessage(@NonNull Message msg) {
60
-            if (msg.what == 1) {
61
-                showButton();
62
-            }
63
-            if (msg.what == 2) {
64
-                hideButton();
65
-            }
66
-            if (msg.what == 3) {
67
-                hideProgress();
68
-                if (videoDecoder != null && MyXUtil.h264PlayFlag) {
69
-                    hideRestart();
70
-//                    PopTip.show("打开视频成功!").iconSuccess();
71
-                    Toast.makeText(VideoSDK.this, "打开视频成功!", Toast.LENGTH_SHORT).show();
72
-                  /*  camera temp = camera.getInstance();
73
-                    byte[] ver = new byte[32];
74
-                    if (temp.getDevVersion(ver) == 0) {
75
-                        //获取成功,例如:20200923_V10.8_sh999
76
-                        devversion.setText(new String(ver).trim());
77
-                    } else {
78
-                        Log.e(TAG, "handleMessage: wtf,获取版本号失败!");
79
-                    }
80
-                    textView.setText("::" + MyXUtil.nowPort);*/
81
-                    if (!MyXUtil.ketThreadFlag) {
82
-                        ThreadPoolHelper.executeTask(() -> videoDecoder.StartKeyScanThread());
83
-                    }
84
-                    videobuttonStop.setText("停止");
85
-                    // videobuttonStop.setCompoundDrawables(ResourcesCompat.getDrawable(Resources.getSystem(), R.drawable.stop, null), null, null, null);
86
-                    videobuttonStop.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(VideoSDK.this, R.drawable.stop), null, null, null);
87
-
88
-                } else {
89
-                    showRestart();
90
-                    closeAllSocket();
91
-                    // TastyToast.makeText(videoSdkTemp, "当前网络没有找到设备", TastyToast.LENGTH_SHORT, TastyToast.ERROR);
92
-//                    PopTip.show("当前网路没有找到设备!").iconError();
93
-                    Toast.makeText(VideoSDK.this, "当前网路没有找到设备!", Toast.LENGTH_SHORT).show();
94
-                }
95
-            }
96
-            if (msg.what == 4) {
97
-                screenshot(mSurfaceView, 1920, 1080);
98
-                Log.e("iMVR", "============msg.what==4=================");
99
-            }
100
-            if (msg.what == 5) {
101
-                hideRestart();
102
-                showProgress();
103
-                ThreadPoolHelper.executeTask(() -> {
104
-                    Log.e(TAG, "onCreate: 开始视频。。。。。");
105
-                    videoDecoder.startVideoDecode();
106
-                });
107
-            }
108
-            if (msg.what == 6) {
109
-//                PopTip.show("已经存在视屏流!").iconError();
110
-                Toast.makeText(VideoSDK.this, "已经存在视屏流!", Toast.LENGTH_SHORT).show();
111
-            }
112
-            if (msg.what == 7) {
113
-                //发送心跳包失败
114
-                startOrStopVideo();
115
-            }
116
-            if (msg.what == 8) {
117
-                //wtf?
118
-            }
119
-            if (msg.what == 9) {
120
-                // TastyToast.makeText(videoSdkTemp, "socket连接失败!", TastyToast.LENGTH_SHORT, TastyToast.ERROR);
121
-//                PopTip.show("当前网络查找视频失败!").iconError();
122
-                Toast.makeText(VideoSDK.this, "当前网络查找视频失败!", Toast.LENGTH_SHORT).show();
123
-            }
124
-            if (msg.what == 20) {
125
-//                PopTip.show("←👈👈👈按键左").iconSuccess();
126
-                Toast.makeText(VideoSDK.this, "按键左!", Toast.LENGTH_SHORT).show();
127
-            }
128
-            if (msg.what == 21) {
129
-//                PopTip.show("按键右👉👉👉→").iconSuccess();
130
-                Toast.makeText(VideoSDK.this, "按键右!", Toast.LENGTH_SHORT).show();
131
-            }
132
-            if (msg.what == 22) {
133
-//                PopTip.show("按键下👇👇👇↓").iconSuccess();
134
-                Toast.makeText(VideoSDK.this, "按键下!", Toast.LENGTH_SHORT).show();
135
-            }
136
-            if (msg.what == 23) {
137
-//                PopTip.show("重置为AP模式,并自动关机!(*Φ皿Φ*)").iconSuccess();
138
-                Toast.makeText(VideoSDK.this, "重置为AP模式,并自动关机!", Toast.LENGTH_SHORT).show();
139
-            }
140
-            if (msg.what == 24) {
141
-                //  sdkversion.setText("Ver::" + BuildConfig.VERSION_NAME + BuildConfig.VERSION_CODE);
142
-                sdkversion.setText("FPS : " + fpsCount);
143
-                fpsCount = 0;
144
-            }
145
-            return false;
146
-        }
147
-    });
148
-
149
-
150
-    @SuppressLint("SetTextI18n")
151
-    @Override
152
-    public void onCreate(Bundle savedInstanceState) {
153
-        super.onCreate(savedInstanceState);
154
-        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
155
-        setContentView(R.layout.videosdk_activity);
156
-        initFindID();
157
-        hideButton();
158
-        initSurface();
159
-        showProgress();
160
-        sdkversion.setText("Ver::" + BuildConfig.VERSION_NAME + BuildConfig.VERSION_CODE);
161
-//        TcpSender.SetDeviceType(0);
162
-        calcuteFPS();
163
-    }
164
-
165
-    private void calcuteFPS() {
166
-        if (t == null) {
167
-            t = new Timer();
168
-        }
169
-        t.scheduleAtFixedRate(new TimerTask() {
170
-            @Override
171
-            public void run() {
172
-                // System.out.println("hello world");
173
-                // Log.e(TAG, "run: " + fpsCount);
174
-                if (MyXUtil.h264PlayFlag) {
175
-                    handler.sendEmptyMessage(24);
176
-                }
177
-            }
178
-        }, 100, 1000);
179
-    }
180
-
181
-
182
-    Bitmap mScreenBitmap = null;
183
-
184
-    public void screenshot(SurfaceView view, int outWidth, int outHeight) {
185
-        mScreenBitmap = Bitmap.createBitmap(outWidth, outHeight, Bitmap.Config.ARGB_8888);
186
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
187
-            PixelCopy.request(view, mScreenBitmap, new PixelCopy.OnPixelCopyFinishedListener() {
188
-                @Override
189
-                public void onPixelCopyFinished(int copyResult) {
190
-                    if (PixelCopy.SUCCESS == copyResult) {
191
-                        //获取成功
192
-                        getImage.setImageBitmap(mScreenBitmap);
193
-                    } else {
194
-//                        PopTip.show("copy error,抓拍失败!").iconError();
195
-                        Toast.makeText(VideoSDK.this, "copy error,抓拍失败!", Toast.LENGTH_SHORT).show();
196
-                    }
197
-                }
198
-            }, handler);
199
-        } else {
200
-//            PopTip.show("安卓版本太低,抓拍失败!").iconWarning();
201
-            Toast.makeText(VideoSDK.this, "安卓版本太低,抓拍失败!", Toast.LENGTH_SHORT).show();
202
-        }
203
-    }
204
-
205
-
206
-    class MyClickListenner implements View.OnClickListener {
207
-        @Override
208
-        public void onClick(View v) {
209
-            if (v.getId() == R.id.checkAll) {
210
-
211
-            }
212
-            if (v.getId() == R.id.cancelAll) {
213
-
214
-            }
215
-            if (v.getId() == R.id.deleteChecked) {
216
-
217
-            }
218
-            if (v.getId() == R.id.face_recordbtn) {
219
-                //record
220
-                if (decodeUtil != null) {
221
-                    if (!DecodeUtil.recordMp4Flag) {
222
-                        decodeUtil.initRecordMp4(MyXUtil.getSdPath() + "test.mp4", 1920, 1080);
223
-                        runOnUiThread(new Runnable() {
224
-                            @Override
225
-                            public void run() {
226
-                                recordButton.setText("recording.....");
227
-                            }
228
-                        });
229
-                    } else {
230
-                        decodeUtil.stopRecordMp4();
231
-                        runOnUiThread(new Runnable() {
232
-                            @Override
233
-                            public void run() {
234
-                                recordButton.setText("record");
235
-                            }
236
-                        });
237
-                    }
238
-                }
239
-            }
240
-
241
-            if (v.getId() == R.id.toMain) {
242
-                closeAllSocket();
243
-                startActivity(new Intent(VideoSDK.this, MainActivity.class));
244
-                finish();
245
-            }
246
-            if (v.getId() == R.id.clickView) {
247
-                clickView.setImageDrawable(null);
248
-                clickView.setVisibility(View.GONE);
249
-            }
250
-
251
-            if (v.getId() == R.id.restart) {
252
-                if (videoDecoder == null) {
253
-                    if (decodeUtil == null) {
254
-                        decodeUtil = new DecodeUtil(mSurfaceView.getHolder().getSurface());
255
-                        decodeUtil.StartCodec();
256
-                    }
257
-                    videoDecoder = new Video(handler, decodeUtil);
258
-                    handler.sendEmptyMessage(5);
259
-                } else {
260
-                    handler.sendEmptyMessage(5);
261
-                }
262
-            }
263
-
264
-            if (v.getId() == R.id.face_stopbtn) {
265
-                startOrStopVideo();
266
-            }
267
-            if (v.getId() == R.id.face_capturebtn) {
268
-                //手动抓图
269
-                // Video.captureStill = true;
270
-                handler.sendEmptyMessage(4);
271
-            }
272
-            if (v.getId() == R.id.getImage) {
273
-                runOnUiThread(new Runnable() {
274
-                    @Override
275
-                    public void run() {
276
-                        if (clickView.getVisibility() != View.VISIBLE) {
277
-                            clickView.setVisibility(View.VISIBLE);
278
-                            clickView.setImageDrawable(getImage.getDrawable());
279
-                        } else {
280
-                            clickView.setImageDrawable(null);
281
-                            clickView.setVisibility(View.GONE);
282
-                        }
283
-                    }
284
-                });
285
-            }
286
-        }
287
-    }
288
-
289
-    private void startOrStopVideo() {
290
-        if (MyXUtil.h264PlayFlag) {
291
-            MyXUtil.h264PlayFlag = false;
292
-            if (videoDecoder != null) {
293
-                closeAllSocket();
294
-                showRestart();
295
-                Log.e(TAG, "onCreate: 停止解码");
296
-            }
297
-        } else {
298
-            if (videoDecoder == null) {
299
-                if (decodeUtil == null) {
300
-                    decodeUtil = new DecodeUtil(mSurfaceView.getHolder().getSurface());
301
-                    decodeUtil.StartCodec();
302
-                }
303
-                videoDecoder = new Video(handler, decodeUtil);
304
-                handler.sendEmptyMessage(5);
305
-            } else {
306
-                handler.sendEmptyMessage(5);
307
-            }
308
-        }
309
-    }
310
-
311
-
312
-    private void closeAllSocket() {
313
-        MyXUtil.h264PlayFlag = false;
314
-        if (videoDecoder != null) {
315
-            videoDecoder.closeSocket();
316
-        }
317
-    }
318
-
319
-    //初始化播放相关
320
-    private void initSurface() {
321
-        mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback2() {
322
-            @Override
323
-            public void surfaceRedrawNeeded(@NonNull SurfaceHolder holder) {
324
-
325
-            }
326
-
327
-            @Override
328
-            public void surfaceCreated(@NonNull SurfaceHolder holder) {
329
-                if (decodeUtil == null) {
330
-                    decodeUtil = new DecodeUtil(holder.getSurface());
331
-                }
332
-                if (videoDecoder == null) {
333
-                    videoDecoder = new Video(handler, decodeUtil);
334
-                }
335
-                decodeUtil.StartCodec();
336
-                handler.sendEmptyMessage(5);
337
-            }
338
-
339
-            @Override
340
-            public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
341
-
342
-            }
343
-
344
-            @Override
345
-            public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
346
-                MyXUtil.h264PlayFlag = false;
347
-                if (videoDecoder != null) {
348
-                    closeAllSocket();
349
-                    runOnUiThread(new Runnable() {
350
-                        @Override
351
-                        public void run() {
352
-                            showRestart();
353
-                        }
354
-                    });
355
-                    Log.e(TAG, "onCreate: 停止解码");
356
-                }
357
-                if (decodeUtil != null) {
358
-                    decodeUtil.StopCodec();
359
-                }
360
-            }
361
-        });
362
-    }
363
-
364
-
365
-    private void initFindID() {
366
-        MyClickListenner myClickListenner = new MyClickListenner();
367
-        mSurfaceView = findViewById(R.id.surfaceView1);
368
-        mSurfaceView.setFocusable(true);
369
-        mSurfaceView.setFocusableInTouchMode(true);
370
-        Button videobuttonCapture = findViewById(R.id.face_capturebtn);
371
-        videobuttonCapture.setOnClickListener(myClickListenner);
372
-        ImageButton toMain = findViewById(R.id.toMain);
373
-        toMain.setOnClickListener(myClickListenner);
374
-        videobuttonStop = findViewById(R.id.face_stopbtn);
375
-        videobuttonStop.setOnClickListener(myClickListenner);
376
-        textView = findViewById(R.id.showByteArr);
377
-        clickView = findViewById(R.id.clickView);
378
-        clickView.setOnClickListener(myClickListenner);
379
-        progressBar = findViewById(R.id.progressStartVideo);
380
-        deleteChecked = findViewById(R.id.deleteChecked);
381
-        deleteChecked.setOnClickListener(myClickListenner);
382
-        checkAll = findViewById(R.id.checkAll);
383
-        checkAll.setOnClickListener(myClickListenner);
384
-        cancelAll = findViewById(R.id.cancelAll);
385
-        cancelAll.setOnClickListener(myClickListenner);
386
-        restart = findViewById(R.id.restart);
387
-        restart.setOnClickListener(myClickListenner);
388
-        getImage = findViewById(R.id.getImage);
389
-        getImage.setOnClickListener(myClickListenner);
390
-        recordButton = findViewById(R.id.face_recordbtn);
391
-        recordButton.setOnClickListener(myClickListenner);
392
-        sdkversion = findViewById(R.id.sdkversion);
393
-        devversion = findViewById(R.id.devversion);
394
-        hideRestart();
395
-    }
396
-
397
-    private void showRestart() {
398
-        restart.setVisibility(View.VISIBLE);
399
-        videobuttonStop.setText("开启");
400
-        videobuttonStop.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(this, R.drawable.start_video), null, null, null);
401
-    }
402
-
403
-    private void hideRestart() {
404
-        restart.setVisibility(View.INVISIBLE);
405
-    }
406
-
407
-    private void showProgress() {
408
-        progressBar.setVisibility(View.VISIBLE);
409
-    }
410
-
411
-    private void hideProgress() {
412
-        progressBar.setVisibility(View.INVISIBLE);
413
-    }
414
-
415
-    private void showButton() {
416
-        cancelAll.setVisibility(View.VISIBLE);
417
-        checkAll.setVisibility(View.VISIBLE);
418
-        deleteChecked.setVisibility(View.VISIBLE);
419
-    }
420
-
421
-    private void hideButton() {
422
-        cancelAll.setVisibility(View.INVISIBLE);
423
-        checkAll.setVisibility(View.INVISIBLE);
424
-        deleteChecked.setVisibility(View.INVISIBLE);
425
-    }
426
-
427
-    //在大于23的android版本中,文件读写需要动态申请权限
428
-    private void verifyStoragePermissions() {
429
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
430
-            if ((this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) || (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
431
-                this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
432
-            } else {
433
-                Log.d(TAG, "已有权限,不需要再申请");
434
-                // mHandler.sendEmptyMessage(MyHandler.PERMISSION_ALLOW);
435
-            }
436
-        } else {
437
-            //  mHandler.sendEmptyMessage(MyHandler.PERMISSION_ALLOW);
438
-        }
439
-    }
440
-
441
-    @Override
442
-    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
443
-        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
444
-        switch (requestCode) {
445
-            case 0x01:  //动态申请的读写权限
446
-                if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
447
-                    //  mHandler.sendEmptyMessage(PERMISSION_ALLOW);
448
-                } else {
449
-                    //  Toast.makeText(this, "用户没有同意文件读取权限!", Toast.LENGTH_LONG).show();
450
-//                    PopTip.show("用户没有同意文件读取权限").iconError();
451
-                    Toast.makeText(VideoSDK.this, "用户没有同意文件读取权限!", Toast.LENGTH_SHORT).show();
452
-                }
453
-                break;
454
-            default:
455
-                break;
456
-        }
457
-    }
458
-
459
-    @Override
460
-    protected void onUserLeaveHint() {
461
-        //运用放到了后台
462
-        super.onUserLeaveHint();
463
-    }
464
-
465
-    @Override
466
-    public void onConfigurationChanged(Configuration newConfig) {
467
-        super.onConfigurationChanged(newConfig);
468
-    }
469
-
470
-    @Override
471
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
472
-        if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME) {
473
-            closeAllSocket();
474
-            Intent intent = new Intent();
475
-            intent.setClass(VideoSDK.this, MainActivity.class);
476
-            startActivity(intent);
477
-            finish();
478
-        }
479
-        return super.onKeyDown(keyCode, event);
480
-    }
481
-
482
-    @Override
483
-    protected void onResume() {
484
-        Log.e(TAG, "onResume: ------");
485
-        super.onResume();
486
-     /*   if (restart.getVisibility() == View.VISIBLE) {
487
-            if (!MyXUtil.h264PlayFlag) {
488
-                Log.e(TAG, "onResume: 重新回到界面,尝试重新开启视频********");
489
-                handler.sendEmptyMessage(5);
490
-            }
491
-        }*/
492
-    }
493
-
494
-    @Override
495
-    protected void onDestroy() {
496
-        closeAllSocket();
497
-        if (videoDecoder != null) {
498
-            videoDecoder = null;
499
-        }
500
-        if (decodeUtil != null) {
501
-            decodeUtil.StopCodec();
502
-            decodeUtil = null;
503
-        }
504
-        MyXUtil.ketThreadFlag = false;
505
-        ServerSocketUtil.closeServerSocket();
506
-        if (t != null) {
507
-            t.cancel();
508
-        }
509
-        super.onDestroy();
510
-    }
511
-}

+ 1 - 0
android/build.gradle

@@ -1,5 +1,6 @@
1 1
 allprojects {
2 2
     repositories {
3
+        maven { url 'https://maven.aliyun.com/repository/public/' }
3 4
         google()
4 5
         mavenCentral()
5 6
         maven { url "https://www.jitpack.io" }