Compare View
Commits (5)
Showing
36 changed files
Show diff stats
.idea/inspectionProfiles/Project_Default.xml
... | ... | @@ -6,5 +6,10 @@ |
6 | 6 | <option name="m_reportAllNonLibraryCalls" value="false" /> |
7 | 7 | <option name="callCheckString" value="java.io.File,.*,java.io.InputStream,read|skip|available|markSupported,java.io.Reader,read|skip|ready|markSupported,java.lang.AbstractStringBuilder,capacity|codePointAt|codePointBefore|codePointCount|indexOf|lastIndexOf|offsetByCodePoints|substring|subSequence,java.lang.Boolean,.*,java.lang.Byte,.*,java.lang.Character,.*,java.lang.Double,.*,java.lang.Float,.*,java.lang.Integer,.*,java.lang.Long,.*,java.lang.Math,.*,java.lang.Object,equals|hashCode|toString,java.lang.Short,.*,java.lang.StrictMath,.*,java.lang.String,.*,java.lang.Thread,interrupted,java.math.BigDecimal,.*,java.math.BigInteger,.*,java.net.InetAddress,.*,java.net.URI,.*,java.nio.channels.AsynchronousChannelGroup,.*,java.nio.channels.Channel,isOpen,java.nio.channels.FileChannel,open|map|lock|tryLock|write,java.nio.channels.ScatteringByteChannel,read,java.nio.channels.SocketChannel,open|socket|isConnected|isConnectionPending,java.util.Arrays,.*,java.util.Collections,(?!addAll).*,java.util.List,of,java.util.Map,of|ofEntries|entry,java.util.Set,of,java.util.UUID,.*,java.util.concurrent.BlockingQueue,offer|remove,java.util.concurrent.CountDownLatch,await|getCount,java.util.concurrent.ExecutorService,awaitTermination|isShutdown|isTerminated,java.util.concurrent.ForkJoinPool,awaitQuiescence,java.util.concurrent.Semaphore,tryAcquire|availablePermits|isFair|hasQueuedThreads|getQueueLength|getQueuedThreads,java.util.concurrent.locks.Condition,await|awaitNanos|awaitUntil,java.util.concurrent.locks.Lock,tryLock|newCondition,java.util.regex.Matcher,pattern|toMatchResult|start|end|group|groupCount|matches|find|lookingAt|quoteReplacement|replaceAll|replaceFirst|regionStart|regionEnd|hasTransparentBounds|hasAnchoringBounds|hitEnd|requireEnd,java.util.regex.Pattern,.*,java.util.stream.BaseStream,.*,java.util.stream.DoubleStream,.*,java.util.stream.IntStream,.*,java.util.stream.LongStream,.*,java.util.stream.Stream,.*" /> |
8 | 8 | </inspection_tool> |
9 | + <inspection_tool class="SameReturnValue" enabled="false" level="WARNING" enabled_by_default="false" /> | |
10 | + <inspection_tool class="UnnecessaryLocalVariable" enabled="false" level="WARNING" enabled_by_default="false"> | |
11 | + <option name="m_ignoreImmediatelyReturnedVariables" value="false" /> | |
12 | + <option name="m_ignoreAnnotatedVariables" value="false" /> | |
13 | + </inspection_tool> | |
9 | 14 | </profile> |
10 | 15 | </component> |
11 | 16 | \ No newline at end of file | ... | ... |
app/build.gradle
... | ... | @@ -97,4 +97,9 @@ dependencies { |
97 | 97 | |
98 | 98 | implementation 'com.jakewharton:butterknife:10.2.3' |
99 | 99 | annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' |
100 | + | |
101 | + | |
102 | + /** 鲁班压缩 */ | |
103 | + implementation 'top.zibin:Luban:1.1.8' | |
104 | + | |
100 | 105 | } |
101 | 106 | \ No newline at end of file | ... | ... |
app/src/main/AndroidManifest.xml
app/src/main/java/com/hjx/parent/ImageActivity.java
... | ... | @@ -24,11 +24,13 @@ import com.google.gson.Gson; |
24 | 24 | import com.google.gson.JsonObject; |
25 | 25 | import com.hjx.parent.adapter.ImageAdapter; |
26 | 26 | import com.hjx.parent.databinding.ActivityImageBinding; |
27 | +import com.hjx.parent.databinding.ItemImageBinding; | |
27 | 28 | import com.hjx.parent.dialog.AddHomeworkDialog; |
28 | 29 | import com.hjx.parent.dialog.ErrorInputDialog; |
29 | 30 | import com.hjx.parent.dialog.PhotoViewDialog; |
30 | 31 | import com.hjx.parent.dialog.TipDialog; |
31 | 32 | import com.hjx.parent.rx.BaseRxActivity; |
33 | +import com.hjx.parent.utils.CutUtil; | |
32 | 34 | import com.prws.common.bean.CutPicBean; |
33 | 35 | import com.prws.common.bean.ImageBean; |
34 | 36 | import com.prws.common.bean.TopicBean; |
... | ... | @@ -40,16 +42,15 @@ import com.xiasuhuei321.loadingdialog.view.LoadingDialog; |
40 | 42 | import java.io.File; |
41 | 43 | import java.util.ArrayList; |
42 | 44 | import java.util.List; |
45 | +import java.util.stream.Collectors; | |
43 | 46 | |
44 | 47 | import io.reactivex.Observer; |
48 | +import io.reactivex.Single; | |
45 | 49 | import io.reactivex.disposables.Disposable; |
46 | -import retrofit2.Call; | |
47 | -import retrofit2.Callback; | |
48 | -import retrofit2.Response; | |
49 | 50 | |
50 | 51 | public class ImageActivity extends BaseRxActivity<ActivityImageBinding> implements View.OnClickListener { |
51 | 52 | |
52 | - private List<String> images = new ArrayList<>(); | |
53 | + private final List<String> images = new ArrayList<>(); | |
53 | 54 | private ImageAdapter imageAdapter; |
54 | 55 | private List<ImageBean> list = new ArrayList<>(); |
55 | 56 | private String filePath; |
... | ... | @@ -57,12 +58,30 @@ public class ImageActivity extends BaseRxActivity<ActivityImageBinding> implemen |
57 | 58 | private int type = 0; |
58 | 59 | private AddHomeworkDialog addHomeworkDialog; |
59 | 60 | |
61 | + @SuppressLint("CheckResult") | |
60 | 62 | @Override |
61 | 63 | public void initView(Bundle savedInstanceState) { |
62 | 64 | type = getIntent().getIntExtra("type", 0); |
63 | 65 | binding.tvSave.setText(type == 0 ? "保存错题" : "录入题目"); |
64 | 66 | |
65 | - images = getIntent().getStringArrayListExtra("images"); | |
67 | + List<String> originList = getIntent().getStringArrayListExtra("images"); | |
68 | + List<String> originListFinal = originList == null ? new ArrayList<>() : originList; | |
69 | + Single.fromCallable(() -> CutUtil.compressAllSync(this, originListFinal, 200)) | |
70 | + .map(it -> it.stream().map(File::getAbsolutePath).collect(Collectors.toList())) | |
71 | + .compose(transformSingle()) | |
72 | + .subscribe((it, throwable) -> { | |
73 | + if (throwable != null) Log.e(getClass().getName(), "", throwable); | |
74 | + images.clear(); | |
75 | + if (it == null) { | |
76 | + images.addAll(originListFinal); | |
77 | + } else { | |
78 | + images.addAll(it); | |
79 | + } | |
80 | + start(); | |
81 | + }); | |
82 | + } | |
83 | + | |
84 | + private void start() { | |
66 | 85 | if (images == null || images.size() <= 1) { |
67 | 86 | binding.rlPrevious.setVisibility(View.GONE); |
68 | 87 | binding.rlNext.setVisibility(View.GONE); |
... | ... | @@ -82,24 +101,18 @@ public class ImageActivity extends BaseRxActivity<ActivityImageBinding> implemen |
82 | 101 | @Override |
83 | 102 | public void onPageSelected(int position) { |
84 | 103 | if (list.get(position).getCuts() == null) { |
85 | -// binding.ivPrevious.setEnabled(false); | |
86 | -// binding.ivNext.setEnabled(false); | |
87 | 104 | clearText(); |
88 | 105 | } |
89 | 106 | binding.tvTitle.setText((binding.viewPager.getCurrentItem() + 1) + "/" + list.size()); |
90 | 107 | if (position == 0) { |
91 | 108 | binding.ivPrevious.setImageResource(R.mipmap.ic_previous_gray); |
92 | -// binding.ivPrevious.setEnabled(true); | |
93 | 109 | } else { |
94 | 110 | binding.ivPrevious.setImageResource(R.mipmap.ic_previous); |
95 | -// binding.ivPrevious.setEnabled(false); | |
96 | 111 | } |
97 | 112 | if (position == list.size() - 1) { |
98 | 113 | binding.ivNext.setImageResource(R.mipmap.ic_next_gray); |
99 | -// binding.ivNext.setEnabled(true); | |
100 | 114 | } else { |
101 | 115 | binding.ivNext.setImageResource(R.mipmap.ic_next); |
102 | -// binding.ivNext.setEnabled(false); | |
103 | 116 | } |
104 | 117 | super.onPageSelected(position); |
105 | 118 | } |
... | ... | @@ -116,6 +129,62 @@ public class ImageActivity extends BaseRxActivity<ActivityImageBinding> implemen |
116 | 129 | ImageBean data = list.get(binding.viewPager.getCurrentItem()); |
117 | 130 | new PhotoViewDialog(this).show(data.source); |
118 | 131 | }); |
132 | + | |
133 | + binding.btnJudge.setVisibility(type == 0 ? View.VISIBLE : View.GONE); | |
134 | + binding.btnJudge.setOnClickListener(v -> { | |
135 | + goJudge(); | |
136 | + }); | |
137 | + } | |
138 | + | |
139 | + private void goJudge() { | |
140 | + if (list.isEmpty()) return; | |
141 | + int position = binding.viewPager.getCurrentItem(); | |
142 | + ImageBean imageBean = list.get(position); | |
143 | + Bitmap bitmap = BitmapFactory.decodeFile(imageBean.getPath()); | |
144 | + if (bitmap == null || imageBean.getCuts() == null) { | |
145 | + showToast("请先框选题目"); | |
146 | + return; | |
147 | + } | |
148 | + ItemImageBinding ib = imageAdapter.viewArray.get(position); | |
149 | + if (ib == null) { | |
150 | + showToast("出错"); | |
151 | + return; | |
152 | + } | |
153 | + View view = ib.ivPic; | |
154 | + float[] size = CutUtil.measureBitmap(view, bitmap); | |
155 | + | |
156 | + ArrayList<Rect> rects = new ArrayList<>(); | |
157 | + for (ImageBean.Cut cut: imageBean.getCuts()) { | |
158 | + if (cut.getRect1() == null) continue; | |
159 | + Rect rectV = cut.getRect1(); | |
160 | + rects.add(getRectB(rectV, bitmap, size)); | |
161 | + } | |
162 | + if (list.isEmpty()) { | |
163 | + showToast("请先框选题目"); | |
164 | + return; | |
165 | + } | |
166 | + | |
167 | + Intent intent = new Intent(this, JudgeActivity.class); | |
168 | + intent.putExtra("path", imageBean.getPath()); | |
169 | + intent.putParcelableArrayListExtra("rects", rects); | |
170 | + | |
171 | + startActivity(intent); | |
172 | + } | |
173 | + | |
174 | + private Rect getRectB(Rect rectV, Bitmap bitmap, float[] measuredSize) { | |
175 | + float realW = measuredSize[0]; | |
176 | + float realH = measuredSize[1]; | |
177 | + float offsetX = measuredSize[2]; | |
178 | + float offsetY = measuredSize[3]; | |
179 | + float percentX = bitmap.getWidth() / realW; | |
180 | + float percentY = bitmap.getHeight() / realH; | |
181 | + | |
182 | + float left = (rectV.left - offsetX) * percentX; | |
183 | + float right = (rectV.right - offsetX) * percentX; | |
184 | + float top = (rectV.top - offsetY) * percentY; | |
185 | + float bottom = (rectV.bottom - offsetY) * percentY; | |
186 | + Rect rectB = new Rect((int) left, (int) top, (int) right, (int) bottom); | |
187 | + return rectB; | |
119 | 188 | } |
120 | 189 | |
121 | 190 | public void clearText() { |
... | ... | @@ -128,8 +197,8 @@ public class ImageActivity extends BaseRxActivity<ActivityImageBinding> implemen |
128 | 197 | } |
129 | 198 | }); |
130 | 199 | Log.i("clearText", list.get(index).getPath()); |
131 | - String base64 = BitmapUtils.imageToBase64(list.get(index).getPath()); | |
132 | - NetWorks.removeWriting(base64, new Observer<JsonObject>() { | |
200 | + String base64 = BitmapUtils.imageToBase64(list.get(index).getPath(), false); | |
201 | + NetWorks.baiduEnhance(base64, new Observer<JsonObject>() { | |
133 | 202 | @Override |
134 | 203 | public void onSubscribe(Disposable d) { |
135 | 204 | |
... | ... | @@ -170,7 +239,7 @@ public class ImageActivity extends BaseRxActivity<ActivityImageBinding> implemen |
170 | 239 | } |
171 | 240 | |
172 | 241 | public void cut(String path) { |
173 | - String base64 = BitmapUtils.imageToBase64(path); | |
242 | + String base64 = BitmapUtils.imageToBase64WithUrlEncode(path); | |
174 | 243 | Log.i("figLoaction", path); |
175 | 244 | NetWorks.cut(base64, new Observer<CutPicBean>() { |
176 | 245 | @Override | ... | ... |
app/src/main/java/com/hjx/parent/JudgeActivity.java
... | ... | @@ -0,0 +1,173 @@ |
1 | +package com.hjx.parent; | |
2 | + | |
3 | +import android.annotation.SuppressLint; | |
4 | +import android.graphics.Bitmap; | |
5 | +import android.graphics.Rect; | |
6 | +import android.os.Bundle; | |
7 | +import android.util.Log; | |
8 | + | |
9 | +import com.bumptech.glide.Glide; | |
10 | +import com.hjx.parent.api.JudgeRepository; | |
11 | +import com.hjx.parent.databinding.ActivityJudgeBinding; | |
12 | +import com.hjx.parent.databinding.LayoutJudgeRectBinding; | |
13 | +import com.hjx.parent.rx.BaseRxActivity; | |
14 | +import com.hjx.parent.utils.CutUtil; | |
15 | + | |
16 | +import java.io.File; | |
17 | +import java.util.ArrayList; | |
18 | +import java.util.List; | |
19 | + | |
20 | +import io.reactivex.Observable; | |
21 | +import io.reactivex.Single; | |
22 | +import top.zibin.luban.Luban; | |
23 | + | |
24 | +public class JudgeActivity extends BaseRxActivity<ActivityJudgeBinding> { | |
25 | + | |
26 | + private Bitmap bitmap; | |
27 | + | |
28 | + private final List<JudgeCut> mList = new ArrayList<>(); | |
29 | + | |
30 | + @SuppressLint("CheckResult") | |
31 | + @Override | |
32 | + public void initView(Bundle savedInstanceState) { | |
33 | + binding.ivBack.setOnClickListener(v -> { | |
34 | + onBackPressed(); | |
35 | + }); | |
36 | + String path = getIntent().getStringExtra("path"); | |
37 | + if (path == null) return; | |
38 | + final ArrayList<Rect> rects = getIntent().getParcelableArrayListExtra("rects"); | |
39 | + if (rects == null) return; | |
40 | + | |
41 | + Single.just(path) | |
42 | + .map(origin -> Luban.with(this).load(origin).ignoreBy(300).get().get(0)) | |
43 | + .map(file -> Glide.with(this).asBitmap().load(file).submit().get()) | |
44 | + .compose(transformSingle()) | |
45 | + .subscribe((bitmap, th) -> { | |
46 | + if (th != null) th.printStackTrace(); | |
47 | + if (bitmap == null) return; | |
48 | + this.bitmap = bitmap; | |
49 | + | |
50 | + binding.ivPic.setImageBitmap(bitmap); | |
51 | + CutUtil.onLayoutReady(binding.ivPic, v -> { | |
52 | + prepareRects(rects); | |
53 | + }); | |
54 | + }); | |
55 | + binding.btnSelectAll.setOnClickListener(v -> { | |
56 | + if (mList.isEmpty()) return; | |
57 | + mList.forEach(it -> it.vb.getRoot().setSelected(true)); | |
58 | + checkCount(); | |
59 | + }); | |
60 | + } | |
61 | + | |
62 | + private void prepareRects(List<Rect> rects) { | |
63 | + mList.clear(); | |
64 | + binding.flRects.removeAllViews(); | |
65 | + float[] measuredSize = CutUtil.measureBitmap(binding.ivPic, bitmap); | |
66 | + for (int i = 0; i < rects.size(); i++) { | |
67 | + Rect it = rects.get(i); | |
68 | + Bitmap bitmap = CutUtil.cut(this.bitmap, it.left, it.top, it.width(), it.height(), this); | |
69 | + Rect rect = measureRect(it, measuredSize); | |
70 | + LayoutJudgeRectBinding vb = showRect(rect); | |
71 | + mList.add(new JudgeCut(i, bitmap, rect, vb)); | |
72 | + } | |
73 | + | |
74 | + judge(); | |
75 | + } | |
76 | + | |
77 | + @SuppressLint("CheckResult") | |
78 | + private void judge() { | |
79 | + showLoadingDialog(""); | |
80 | + Observable.fromIterable(mList) | |
81 | + .map(it -> { | |
82 | + if (it.url != null && !it.url.isEmpty()) return it; | |
83 | + String base64 = CutUtil.bitmapToBase64(it.bitmap, true); | |
84 | + it.url = base64; | |
85 | + return it; | |
86 | + }) | |
87 | + .flatMap(it -> JudgeRepository.singleJudge(it.url) | |
88 | + .map(result -> { | |
89 | + it.correctResult = result; | |
90 | + return it; | |
91 | + }) | |
92 | + .toObservable() | |
93 | + ) | |
94 | + .compose(transform()) | |
95 | + .subscribe(it -> { | |
96 | + if (it.correctResult == 1) { | |
97 | + it.vb.ivResult.setImageResource(R.drawable.png_ic_judge_correct); | |
98 | + } else if (it.correctResult == 2) { | |
99 | + it.vb.ivResult.setImageResource(R.drawable.png_ic_judge_wrong); | |
100 | + } | |
101 | + it.vb.getRoot().setSelected(it.correctResult != 1); | |
102 | + checkCount(); | |
103 | + }, th -> { | |
104 | + cancelLoadingDialog(); | |
105 | + Log.e(getClass().getName(), "", th); | |
106 | + }, this::cancelLoadingDialog) | |
107 | + ; | |
108 | + } | |
109 | + | |
110 | + private LayoutJudgeRectBinding showRect(Rect rect) { | |
111 | + LayoutJudgeRectBinding vb = LayoutJudgeRectBinding.inflate(getLayoutInflater(), binding.flRects, false); | |
112 | + | |
113 | + vb.getRoot().setMinimumWidth(rect.width()); | |
114 | + vb.getRoot().setMinimumHeight(rect.height()); | |
115 | + vb.getRoot().setTranslationX((float) rect.left); | |
116 | + vb.getRoot().setTranslationY((float) rect.top); | |
117 | + vb.getRoot().setOnClickListener(v -> { | |
118 | + v.setSelected(!v.isSelected()); | |
119 | + checkCount(); | |
120 | + }); | |
121 | + binding.flRects.addView(vb.getRoot()); | |
122 | + | |
123 | + return vb; | |
124 | + } | |
125 | + | |
126 | + @SuppressLint("SetTextI18n") | |
127 | + private void checkCount() { | |
128 | + int count = (int) mList.stream().filter(it -> it.vb.getRoot().isSelected()).count(); | |
129 | + if (count == 0) binding.btnAdd.setText("加入错题"); | |
130 | + else binding.btnAdd.setText("加入错题(" + count + ")"); | |
131 | + binding.btnAdd.setEnabled(count > 0); | |
132 | + } | |
133 | + | |
134 | + /** bitmapRect 转换为 viewRect */ | |
135 | + private Rect measureRect(Rect rect, float[] measuredSize) { | |
136 | + float realW = measuredSize[0]; | |
137 | + float realH = measuredSize[1]; | |
138 | + float offsetX = measuredSize[2]; | |
139 | + float offsetY = measuredSize[3]; | |
140 | + float percentX = realW / bitmap.getWidth(); | |
141 | + float percentY = realH / bitmap.getHeight(); | |
142 | + | |
143 | + float left = rect.left * percentX + offsetX; | |
144 | + float right = rect.right * percentX + offsetX; | |
145 | + float top = rect.top * percentY + offsetY; | |
146 | + float bottom = rect.bottom * percentY + offsetY; | |
147 | + return new Rect((int) left, (int) top, (int) right, (int) bottom); | |
148 | + } | |
149 | + | |
150 | + @Override | |
151 | + protected ActivityJudgeBinding getViewBinding() { | |
152 | + return ActivityJudgeBinding.inflate(getLayoutInflater()); | |
153 | + } | |
154 | + | |
155 | + static class JudgeCut { | |
156 | + final int index; | |
157 | + final Bitmap bitmap; | |
158 | + final Rect rect; | |
159 | + final LayoutJudgeRectBinding vb; | |
160 | + | |
161 | + String url; | |
162 | + | |
163 | + /** 0:未批改;1:正确;2:错误;3:未作答 */ | |
164 | + int correctResult = 0; | |
165 | + | |
166 | + public JudgeCut(int index, Bitmap bitmap, Rect rect, LayoutJudgeRectBinding vb) { | |
167 | + this.index = index; | |
168 | + this.bitmap = bitmap; | |
169 | + this.rect = rect; | |
170 | + this.vb = vb; | |
171 | + } | |
172 | + } | |
173 | +} | ... | ... |
app/src/main/java/com/hjx/parent/adapter/ImageAdapter.java
... | ... | @@ -7,6 +7,7 @@ import android.graphics.BitmapFactory; |
7 | 7 | import android.graphics.Rect; |
8 | 8 | import android.graphics.RectF; |
9 | 9 | import android.util.Log; |
10 | +import android.util.SparseArray; | |
10 | 11 | import android.view.LayoutInflater; |
11 | 12 | import android.view.View; |
12 | 13 | import android.view.ViewGroup; |
... | ... | @@ -27,9 +28,12 @@ import com.prws.common.utils.CommonUtil; |
27 | 28 | import java.util.List; |
28 | 29 | |
29 | 30 | public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageHolder> { |
31 | + public SparseArray<ItemImageBinding> viewArray = new SparseArray<>(); | |
32 | + | |
30 | 33 | private List<ImageBean> list; |
31 | 34 | private ImageActivity context; |
32 | 35 | |
36 | + | |
33 | 37 | public ImageAdapter(ImageActivity context, List<ImageBean> list) { |
34 | 38 | this.context = context; |
35 | 39 | this.list = list; |
... | ... | @@ -44,6 +48,8 @@ public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageHolder> |
44 | 48 | |
45 | 49 | @Override |
46 | 50 | public void onBindViewHolder(@NonNull ImageHolder holder, int position) { |
51 | + viewArray.put(position, holder.binding); | |
52 | + | |
47 | 53 | ImageBean imageBean = list.get(position); |
48 | 54 | Bitmap bitmap = BitmapFactory.decodeFile(imageBean.getPath()); |
49 | 55 | float imageHeight = bitmap.getHeight(); | ... | ... |
app/src/main/java/com/hjx/parent/api/ChatApi.java
... | ... | @@ -0,0 +1,17 @@ |
1 | +package com.hjx.parent.api; | |
2 | + | |
3 | +import io.reactivex.Single; | |
4 | +import retrofit2.http.Body; | |
5 | +import retrofit2.http.Header; | |
6 | +import retrofit2.http.POST; | |
7 | +import retrofit2.http.Url; | |
8 | + | |
9 | +public interface ChatApi { | |
10 | + @POST | |
11 | + Single<ChatResponse> aiChat( | |
12 | + @Url String url, | |
13 | + @Header("Authorization") String token, | |
14 | + @Body ChatRequest body | |
15 | + ); | |
16 | + | |
17 | +} | ... | ... |
app/src/main/java/com/hjx/parent/api/ChatChoices.java
... | ... | @@ -0,0 +1,13 @@ |
1 | +package com.hjx.parent.api; | |
2 | + | |
3 | +import com.google.gson.annotations.SerializedName; | |
4 | + | |
5 | +public class ChatChoices { | |
6 | + | |
7 | + public ChatMessage message; | |
8 | + public int index; | |
9 | + @SerializedName("finish_reason") | |
10 | + public String finishReason; | |
11 | + public String logprobs; | |
12 | + | |
13 | +} | ... | ... |
app/src/main/java/com/hjx/parent/api/ChatError.java
app/src/main/java/com/hjx/parent/api/ChatMessage.java
... | ... | @@ -0,0 +1,45 @@ |
1 | +package com.hjx.parent.api; | |
2 | + | |
3 | +import java.util.ArrayList; | |
4 | +import java.util.List; | |
5 | +import java.util.Objects; | |
6 | + | |
7 | +public class ChatMessage { | |
8 | + public ChatMessage() { | |
9 | + } | |
10 | + public ChatMessage(String role, Object content) { | |
11 | + this.role = role; | |
12 | + this.content = content; | |
13 | + } | |
14 | + | |
15 | + public String role; | |
16 | + public Object content; | |
17 | + | |
18 | + public static ChatMessage fromImage(String role, String text, String... urls) { | |
19 | + List<ContentItem> items = new ArrayList<>(); | |
20 | + if (text != null && !text.isEmpty()) { | |
21 | + items.add(new ContentItem(ContentItem.TYPE_TEXT, text)); | |
22 | + } | |
23 | + for (String it: urls) { | |
24 | + ContentItem.ContentImage image = new ContentItem.ContentImage(it); | |
25 | + items.add(new ContentItem(ContentItem.TYPE_IMAGE, image)); | |
26 | + } | |
27 | + return new ChatMessage(role, items); | |
28 | + } | |
29 | + | |
30 | + public String getTextContent() { | |
31 | + if (content == null) return null; | |
32 | + if (content instanceof String) return (String) content; | |
33 | + ContentItem item = firstText(); | |
34 | + return item == null ? null : item.text; | |
35 | + } | |
36 | + | |
37 | + private ContentItem firstText() { | |
38 | + if (!(content instanceof List<?>)) return null; | |
39 | + List<?> anyList = (List<?>) content; | |
40 | + return anyList.stream() | |
41 | + .map(ContentItem::reSerialize) | |
42 | + .filter(Objects::nonNull) | |
43 | + .findFirst().orElse(null); | |
44 | + } | |
45 | +} | ... | ... |
app/src/main/java/com/hjx/parent/api/ChatRequest.java
... | ... | @@ -0,0 +1,15 @@ |
1 | +package com.hjx.parent.api; | |
2 | + | |
3 | +import java.util.List; | |
4 | + | |
5 | +public class ChatRequest { | |
6 | + public String model; | |
7 | + public List<ChatMessage> messages; | |
8 | + public boolean stream; | |
9 | + | |
10 | + public ChatRequest(String model, List<ChatMessage> messages) { | |
11 | + this.model = model; | |
12 | + this.messages = messages; | |
13 | + this.stream = false; | |
14 | + } | |
15 | +} | ... | ... |
app/src/main/java/com/hjx/parent/api/ChatResponse.java
... | ... | @@ -0,0 +1,19 @@ |
1 | +package com.hjx.parent.api; | |
2 | + | |
3 | +import com.google.gson.annotations.SerializedName; | |
4 | + | |
5 | +import java.util.List; | |
6 | + | |
7 | +public class ChatResponse { | |
8 | + public List<ChatChoices> choices; | |
9 | + public String created; | |
10 | + public String id; | |
11 | + public String model; | |
12 | + @SerializedName("service_tier") | |
13 | + public String serviceTier; | |
14 | + @SerializedName("object") | |
15 | + public String obj; | |
16 | + public ChatUsage usage; | |
17 | + | |
18 | + public ChatError error; | |
19 | +} | ... | ... |
app/src/main/java/com/hjx/parent/api/ChatUsage.java
... | ... | @@ -0,0 +1,16 @@ |
1 | +package com.hjx.parent.api; | |
2 | + | |
3 | +import com.google.gson.annotations.SerializedName; | |
4 | + | |
5 | +public class ChatUsage { | |
6 | + @SerializedName("completion_tokens") | |
7 | + public int completionTokens; | |
8 | + @SerializedName("prompt_tokens") | |
9 | + public int promptTokens; | |
10 | + @SerializedName("total_tokens") | |
11 | + public int totalTokens; | |
12 | + @SerializedName("prompt_tokens_details") | |
13 | + public PromptTokensDetails promptTokensDetails; | |
14 | + @SerializedName("completion_tokens_details") | |
15 | + public CompletionTokensDetails completionTokensDetails; | |
16 | +} | ... | ... |
app/src/main/java/com/hjx/parent/api/CompletionTokensDetails.java
app/src/main/java/com/hjx/parent/api/ContentItem.java
... | ... | @@ -0,0 +1,48 @@ |
1 | +package com.hjx.parent.api; | |
2 | + | |
3 | +import com.google.gson.Gson; | |
4 | +import com.google.gson.annotations.SerializedName; | |
5 | + | |
6 | +public class ContentItem { | |
7 | + public static final String TYPE_TEXT = "text"; | |
8 | + public static final String TYPE_IMAGE = "image_url"; | |
9 | + | |
10 | + | |
11 | + public ContentItem() { | |
12 | + } | |
13 | + public ContentItem(String type, String text) { | |
14 | + this.type = type; | |
15 | + this.text = text; | |
16 | + } | |
17 | + public ContentItem(String type, ContentImage imageUrl) { | |
18 | + this.type = type; | |
19 | + this.imageUrl = imageUrl; | |
20 | + } | |
21 | + | |
22 | + public String type; | |
23 | + public String text; | |
24 | + @SerializedName("image_url") | |
25 | + public ContentImage imageUrl; | |
26 | + | |
27 | + public static class ContentImage { | |
28 | + public ContentImage(String url) { | |
29 | + this.url = url; | |
30 | + } | |
31 | + | |
32 | + public String url; | |
33 | + } | |
34 | + | |
35 | + | |
36 | + private static final Gson gson = new Gson(); | |
37 | + static ContentItem reSerialize(Object any) { | |
38 | + if (any == null) return null; | |
39 | + try { | |
40 | + String json = gson.toJson(any); | |
41 | + ContentItem it = gson.fromJson(json, ContentItem.class); | |
42 | + return it; | |
43 | + } catch (Throwable t) { | |
44 | + t.printStackTrace(); | |
45 | + } | |
46 | + return null; | |
47 | + } | |
48 | +} | ... | ... |
app/src/main/java/com/hjx/parent/api/JudgeRepository.java
... | ... | @@ -0,0 +1,55 @@ |
1 | +package com.hjx.parent.api; | |
2 | + | |
3 | +import android.annotation.SuppressLint; | |
4 | + | |
5 | +import com.google.gson.Gson; | |
6 | +import com.prws.common.net.NetWorks; | |
7 | + | |
8 | +import java.util.ArrayList; | |
9 | +import java.util.List; | |
10 | + | |
11 | +import io.reactivex.Single; | |
12 | +import retrofit2.Retrofit; | |
13 | + | |
14 | +public class JudgeRepository { | |
15 | + private static final Gson gson = new Gson(); | |
16 | + private static final ChatApi api; | |
17 | + static { | |
18 | + Retrofit retrofit = NetWorks.retrofit; | |
19 | + api = retrofit.create(ChatApi.class); | |
20 | + } | |
21 | + | |
22 | + | |
23 | + public static Single<Integer> singleJudge(String url) { | |
24 | + List<ChatMessage> messages = new ArrayList<>(); | |
25 | + messages.add(ChatMessage.fromImage("system", setting, url)); | |
26 | + | |
27 | + return api.aiChat(JudgeRepository.url, token, new ChatRequest(model, messages)) | |
28 | + .map(response -> { | |
29 | + if (response.choices == null) return null; | |
30 | + return response.choices.stream().findFirst() | |
31 | + .map(it -> it.message) | |
32 | + .map(ChatMessage::getTextContent) | |
33 | + .orElse(null); | |
34 | + }) | |
35 | + .map(json -> { | |
36 | + JudgeResult result = gson.fromJson(json, JudgeResult.class); | |
37 | + return result.result; | |
38 | + }) | |
39 | + ; | |
40 | + } | |
41 | + | |
42 | + | |
43 | + private static final String model = "doubao-1-5-thinking-vision-pro-250428"; | |
44 | + private static final String url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"; | |
45 | + private static final String token = "Bearer a877087e-bb74-471b-8f2a-01e6b2220699"; | |
46 | + private static final String setting = | |
47 | + "批改图片中的题目, 判断作答是否正确,并以Json格式返回结果,需要包含以下字段: \n" + | |
48 | + "result(批改结果, 枚举 0:不确定; 1:正确; 2:错误; 3:未作答).\n" + | |
49 | + "Json示例(供参考,无需复制): {\"result\": 1}\n" + | |
50 | + "一个图片中一般只会有一个题目, 返回一个结果即可."; | |
51 | + | |
52 | + private static class JudgeResult { | |
53 | + public int result; | |
54 | + } | |
55 | +} | ... | ... |
app/src/main/java/com/hjx/parent/api/PromptTokensDetails.java
app/src/main/java/com/hjx/parent/utils/CutUtil.java
... | ... | @@ -0,0 +1,102 @@ |
1 | +package com.hjx.parent.utils; | |
2 | + | |
3 | +import android.content.Context; | |
4 | +import android.graphics.Bitmap; | |
5 | +import android.graphics.Canvas; | |
6 | +import android.graphics.Color; | |
7 | +import android.graphics.Paint; | |
8 | +import android.util.Base64; | |
9 | +import android.view.View; | |
10 | +import android.view.ViewTreeObserver; | |
11 | + | |
12 | +import com.bumptech.glide.Glide; | |
13 | +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; | |
14 | +import com.hjx.parent.function.Function1; | |
15 | + | |
16 | +import java.io.ByteArrayOutputStream; | |
17 | +import java.io.File; | |
18 | +import java.io.IOException; | |
19 | +import java.util.List; | |
20 | + | |
21 | +import top.zibin.luban.Luban; | |
22 | + | |
23 | +public class CutUtil { | |
24 | + | |
25 | + public static float[] measureBitmap(View view, Bitmap bitmap) { | |
26 | + float realW; | |
27 | + float realH; | |
28 | + float offsetX; | |
29 | + float offsetY; | |
30 | + | |
31 | + float vp = 1f * view.getWidth() / view.getHeight(); | |
32 | + float bp = 1f * bitmap.getWidth() / bitmap.getHeight(); | |
33 | + | |
34 | + if (vp > bp) { | |
35 | + realW = view.getHeight() * bp; | |
36 | + realH = (float) view.getHeight(); | |
37 | + offsetY = 0f; | |
38 | + offsetX = (view.getWidth() - realW) * 0.5f; | |
39 | + } else if (vp < bp) { | |
40 | + realW = (float) view.getWidth(); | |
41 | + realH = view.getWidth() * (1f / bp); | |
42 | + offsetX = 0f; | |
43 | + offsetY = (view.getHeight() - realH) * 0.5f; | |
44 | + } else { | |
45 | + realW = (float) view.getWidth(); | |
46 | + realH = (float) view.getHeight(); | |
47 | + offsetX = 0f; | |
48 | + offsetY = 0f; | |
49 | + } | |
50 | + | |
51 | + return new float[]{realW, realH, offsetX, offsetY}; | |
52 | + } | |
53 | + | |
54 | + public static Bitmap cut(Bitmap source, float x, float y, int w, int h, Context context) { | |
55 | + // 获取 Glide 的 BitmapPool | |
56 | + BitmapPool bitmapPool = Glide.get(context).getBitmapPool(); | |
57 | + | |
58 | + // 从 BitmapPool 中获取可复用的 Bitmap | |
59 | + Bitmap result = bitmapPool.get(w, h, source.getConfig() != null ? source.getConfig() : Bitmap.Config.ARGB_8888); | |
60 | + | |
61 | + // 填充白色背景 | |
62 | + result.eraseColor(Color.WHITE); | |
63 | + | |
64 | + // 创建画布并绘制 | |
65 | + Canvas canvas = new Canvas(result); | |
66 | + Paint paint = new Paint(); | |
67 | + canvas.drawBitmap(source, -x, -y, paint); | |
68 | + | |
69 | + return result; | |
70 | + } | |
71 | + | |
72 | + public static void onLayoutReady(final View view, final Function1<View> action) { | |
73 | + view.getViewTreeObserver().addOnGlobalLayoutListener( | |
74 | + new ViewTreeObserver.OnGlobalLayoutListener() { | |
75 | + @Override | |
76 | + public void onGlobalLayout() { | |
77 | + view.getViewTreeObserver().removeOnGlobalLayoutListener(this); | |
78 | + action.invoke(view); | |
79 | + } | |
80 | + } | |
81 | + ); | |
82 | + } | |
83 | + | |
84 | + public static byte[] bitmapToByteArray(Bitmap bitmap) { | |
85 | + ByteArrayOutputStream output = new ByteArrayOutputStream(); | |
86 | + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output); | |
87 | + return output.toByteArray(); | |
88 | + } | |
89 | + | |
90 | + public static String bitmapToBase64(Bitmap bitmap, Boolean usePrefix) { | |
91 | + String base64 = Base64.encodeToString(bitmapToByteArray(bitmap), Base64.NO_WRAP); | |
92 | + if (usePrefix) return "data:image/jpeg;base64," + base64; | |
93 | + else return base64; | |
94 | + } | |
95 | + | |
96 | + public static List<File> compressAllSync(Context context, List<String> originList, int ignore) throws IOException { | |
97 | + return Luban.with(context).ignoreBy(ignore) | |
98 | + .setTargetDir(context.getExternalCacheDir().getAbsolutePath()) | |
99 | + .load(originList) | |
100 | + .get(); | |
101 | + } | |
102 | +} | ... | ... |
app/src/main/res/drawable/bg_judge_cut.xml
... | ... | @@ -0,0 +1,15 @@ |
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |
3 | + <item android:state_selected="true"> | |
4 | + <shape> | |
5 | + <solid android:color="#1A1C90F3"/> | |
6 | + <stroke android:color="#1C90F3" android:width="1px"/> | |
7 | + </shape> | |
8 | + </item> | |
9 | + <item> | |
10 | + <shape> | |
11 | + <solid android:color="#33000000"/> | |
12 | + <stroke android:color="#666666" android:width="1px"/> | |
13 | + </shape> | |
14 | + </item> | |
15 | +</selector> | |
0 | 16 | \ No newline at end of file | ... | ... |
app/src/main/res/drawable/check_circle_12.xml
... | ... | @@ -0,0 +1,15 @@ |
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | |
3 | + <item android:width="12dp" android:height="12dp"> | |
4 | + <selector> | |
5 | + <item android:state_checked="true" | |
6 | + android:drawable="@drawable/png_ic_check_circle"/> | |
7 | + <item> | |
8 | + <shape> | |
9 | + <corners android:radius="20dp"/> | |
10 | + <stroke android:width="1.5dp" android:color="#333"/> | |
11 | + </shape> | |
12 | + </item> | |
13 | + </selector> | |
14 | + </item> | |
15 | +</layer-list> | |
0 | 16 | \ No newline at end of file | ... | ... |
app/src/main/res/drawable/ic_add.png
1.12 KB
app/src/main/res/drawable/ic_judge_rect_select.xml
... | ... | @@ -0,0 +1,5 @@ |
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<selector xmlns:android="http://schemas.android.com/apk/res/android"> | |
3 | + <item android:drawable="@drawable/png_rect_selected" android:state_selected="true"/> | |
4 | + <item android:drawable="@drawable/png_rect_add"/> | |
5 | +</selector> | |
0 | 6 | \ No newline at end of file | ... | ... |
app/src/main/res/drawable/ic_rect_20.xml
app/src/main/res/drawable/png_ic_check_circle.png
1.05 KB
app/src/main/res/drawable/png_ic_judge_correct.png
1.09 KB
app/src/main/res/drawable/png_ic_judge_wrong.png
1.12 KB
app/src/main/res/drawable/png_ic_rect.png
1.72 KB
app/src/main/res/drawable/png_rect_add.png
1.12 KB
app/src/main/res/drawable/png_rect_selected.png
902 Bytes
app/src/main/res/layout/activity_image.xml
1 | 1 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
2 | + xmlns:tools="http://schemas.android.com/tools" | |
2 | 3 | android:layout_width="match_parent" |
3 | 4 | android:layout_height="match_parent" |
4 | - android:orientation="vertical"> | |
5 | + xmlns:app="http://schemas.android.com/apk/res-auto" | |
6 | + android:orientation="vertical" | |
7 | + tools:ignore="HardcodedText"> | |
5 | 8 | |
6 | 9 | <RelativeLayout |
7 | 10 | android:layout_width="match_parent" |
... | ... | @@ -102,8 +105,10 @@ |
102 | 105 | android:src="@mipmap/ic_next_gray" /> |
103 | 106 | </RelativeLayout> |
104 | 107 | |
105 | - <RelativeLayout | |
108 | + <LinearLayout | |
106 | 109 | android:id="@+id/rl_bottom" |
110 | + android:orientation="horizontal" | |
111 | + android:gravity="center_vertical" | |
107 | 112 | android:layout_width="match_parent" |
108 | 113 | android:layout_height="70dp" |
109 | 114 | android:layout_alignParentBottom="true" |
... | ... | @@ -113,13 +118,12 @@ |
113 | 118 | android:id="@+id/ll_edit" |
114 | 119 | android:layout_width="wrap_content" |
115 | 120 | android:layout_height="wrap_content" |
116 | - android:layout_centerVertical="true" | |
117 | - android:layout_marginLeft="15dp" | |
121 | + android:layout_marginStart="15dp" | |
118 | 122 | android:orientation="vertical"> |
119 | 123 | |
120 | 124 | <ImageView |
121 | - android:layout_width="25dp" | |
122 | - android:layout_height="25dp" | |
125 | + android:layout_width="20dp" | |
126 | + android:layout_height="20dp" | |
123 | 127 | android:layout_gravity="center_horizontal" |
124 | 128 | android:src="@mipmap/ic_pic_edit" /> |
125 | 129 | |
... | ... | @@ -128,35 +132,45 @@ |
128 | 132 | android:layout_height="wrap_content" |
129 | 133 | android:layout_marginTop="5dp" |
130 | 134 | android:text="图片编辑" |
135 | + android:textColor="#333" | |
131 | 136 | android:textSize="11sp" /> |
132 | 137 | </LinearLayout> |
133 | 138 | |
134 | - <TextView | |
139 | + <androidx.appcompat.widget.AppCompatTextView | |
135 | 140 | android:id="@+id/tv_add" |
136 | - android:layout_width="140dp" | |
137 | - android:layout_height="40dp" | |
138 | - android:layout_centerVertical="true" | |
139 | - android:layout_marginRight="15dp" | |
140 | - android:layout_toLeftOf="@+id/tv_save" | |
141 | + android:text="手动框选" | |
142 | + android:textSize="11sp" | |
143 | + android:textColor="#333" | |
144 | + android:gravity="center_horizontal" | |
145 | + android:drawableTop="@drawable/ic_rect_20" | |
146 | + android:drawablePadding="5dp" | |
147 | + android:layout_marginStart="12dp" | |
148 | + android:layout_width="wrap_content" | |
149 | + android:layout_height="wrap_content" /> | |
150 | + | |
151 | + <Space style="@style/empty_space"/> | |
152 | + | |
153 | + <TextView | |
154 | + android:id="@+id/btnJudge" | |
155 | + android:layout_width="112dp" | |
156 | + android:layout_height="36dp" | |
141 | 157 | android:background="@drawable/bg_soild_orange_5" |
142 | 158 | android:gravity="center" |
143 | - android:text="手动框选" | |
159 | + android:text="去批改" | |
144 | 160 | android:textColor="@color/white" |
145 | - android:textSize="18sp" /> | |
161 | + android:textSize="16sp" /> | |
146 | 162 | |
147 | 163 | <TextView |
148 | 164 | android:id="@+id/tv_save" |
149 | - android:layout_width="140dp" | |
150 | - android:layout_height="40dp" | |
151 | - android:layout_alignParentRight="true" | |
152 | - android:layout_centerVertical="true" | |
153 | - android:layout_marginRight="15dp" | |
165 | + android:layout_width="112dp" | |
166 | + android:layout_height="36dp" | |
167 | + android:layout_marginHorizontal="15dp" | |
154 | 168 | android:background="@drawable/bg_soild_blue_light_5" |
155 | 169 | android:enabled="false" |
156 | 170 | android:gravity="center" |
157 | 171 | android:text="保存错题" |
158 | 172 | android:textColor="@color/white" |
159 | - android:textSize="18sp" /> | |
160 | - </RelativeLayout> | |
173 | + android:textSize="16sp" /> | |
174 | + </LinearLayout> | |
161 | 175 | </RelativeLayout> |
162 | 176 | </LinearLayout> |
163 | 177 | \ No newline at end of file | ... | ... |
app/src/main/res/layout/activity_judge.xml
... | ... | @@ -0,0 +1,73 @@ |
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
3 | + xmlns:app="http://schemas.android.com/apk/res-auto" | |
4 | + xmlns:tools="http://schemas.android.com/tools" | |
5 | + android:orientation="vertical" | |
6 | + android:layout_width="match_parent" | |
7 | + android:layout_height="match_parent" | |
8 | + tools:ignore="UseCompoundDrawables,HardcodedText,SmallSp,ContentDescription"> | |
9 | + | |
10 | + <androidx.appcompat.widget.Toolbar | |
11 | + android:background="@color/white" | |
12 | + app:contentInsetStart="0dp" | |
13 | + android:layout_width="match_parent" | |
14 | + android:layout_height="40dp"> | |
15 | + <ImageView | |
16 | + android:id="@+id/ivBack" | |
17 | + android:layout_width="30dp" | |
18 | + android:layout_height="36dp" | |
19 | + android:layout_centerVertical="true" | |
20 | + android:layout_marginStart="5dp" | |
21 | + android:padding="10dp" | |
22 | + android:src="@mipmap/icon_back" /> | |
23 | + </androidx.appcompat.widget.Toolbar> | |
24 | + | |
25 | + <FrameLayout | |
26 | + android:background="@color/white" | |
27 | + android:padding="8dp" | |
28 | + android:layout_margin="16dp" | |
29 | + android:layout_width="match_parent" | |
30 | + android:layout_height="0px" | |
31 | + android:layout_weight="1"> | |
32 | + <ImageView | |
33 | + android:id="@+id/ivPic" | |
34 | + android:layout_width="match_parent" | |
35 | + android:layout_height="match_parent"/> | |
36 | + <FrameLayout | |
37 | + android:id="@+id/flRects" | |
38 | + android:layout_width="match_parent" | |
39 | + android:layout_height="match_parent" /> | |
40 | + </FrameLayout> | |
41 | + | |
42 | + <LinearLayout | |
43 | + android:orientation="horizontal" | |
44 | + android:gravity="center_vertical" | |
45 | + android:paddingHorizontal="16dp" | |
46 | + android:background="@color/white" | |
47 | + android:layout_width="match_parent" | |
48 | + android:layout_height="64dp"> | |
49 | + <androidx.appcompat.widget.AppCompatTextView | |
50 | + android:id="@+id/btnSelectAll" | |
51 | + android:text="全选" | |
52 | + android:textSize="16sp" | |
53 | + android:textColor="#333" | |
54 | + android:gravity="center_vertical" | |
55 | + android:paddingHorizontal="8dp" | |
56 | + android:paddingVertical="4dp" | |
57 | + android:layout_width="wrap_content" | |
58 | + android:layout_height="wrap_content"/> | |
59 | + | |
60 | + <Space style="@style/empty_space"/> | |
61 | + <TextView | |
62 | + android:id="@+id/btnAdd" | |
63 | + android:text="加入错题" | |
64 | + android:textSize="16sp" | |
65 | + android:textColor="@color/white" | |
66 | + android:gravity="center" | |
67 | + android:background="@drawable/shape_radius_5" | |
68 | + android:backgroundTint="#1C90F3" | |
69 | + android:layout_width="112dp" | |
70 | + android:layout_height="36dp"/> | |
71 | + </LinearLayout> | |
72 | + | |
73 | +</LinearLayout> | |
0 | 74 | \ No newline at end of file | ... | ... |
app/src/main/res/layout/layout_judge_rect.xml
... | ... | @@ -0,0 +1,27 @@ |
1 | +<?xml version="1.0" encoding="utf-8"?> | |
2 | +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
3 | + xmlns:app="http://schemas.android.com/apk/res-auto" | |
4 | + xmlns:tools="http://schemas.android.com/tools" | |
5 | + android:orientation="vertical" | |
6 | + android:background="@drawable/bg_judge_cut" | |
7 | + android:minWidth="160dp" | |
8 | + android:minHeight="48dp" | |
9 | + android:layout_width="wrap_content" | |
10 | + android:layout_height="wrap_content" | |
11 | + tools:ignore="UseCompoundDrawables,HardcodedText,SmallSp,ContentDescription"> | |
12 | + | |
13 | + <ImageView | |
14 | + android:id="@+id/ivResult" | |
15 | + tools:src="@drawable/png_ic_judge_correct" | |
16 | + android:layout_gravity="end" | |
17 | + android:layout_margin="8dp" | |
18 | + android:layout_width="12dp" | |
19 | + android:layout_height="12dp"/> | |
20 | + | |
21 | + <ImageView | |
22 | + android:src="@drawable/ic_judge_rect_select" | |
23 | + android:layout_gravity="center" | |
24 | + android:layout_width="12dp" | |
25 | + android:layout_height="12dp"/> | |
26 | + | |
27 | +</FrameLayout> | |
0 | 28 | \ No newline at end of file | ... | ... |
libs/common/build.gradle
... | ... | @@ -18,23 +18,21 @@ android { |
18 | 18 | |
19 | 19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" |
20 | 20 | |
21 | - buildConfigField("String", "APIKey1", "\"eCa3YzEjTBBiNjlXcNnjnldP\"") | |
22 | - buildConfigField("String", "SecretKey1", "\"KnZPmjF0ZzmxWV964mzmm6yuDljnETLt\"") | |
21 | + buildConfigField("String", "APIKey", "\"oj9XT8AOeTeLkdqaEX7RJA0N\"") | |
22 | + buildConfigField("String", "SecretKey", "\"AfUFmACkfbd0RMuk11qbw1TW5LtxtJHK\"") | |
23 | + buildConfigField("String", "APIKey1", "\"oj9XT8AOeTeLkdqaEX7RJA0N\"") | |
24 | + buildConfigField("String", "SecretKey1", "\"AfUFmACkfbd0RMuk11qbw1TW5LtxtJHK\"") | |
23 | 25 | } |
24 | 26 | |
25 | 27 | buildTypes { |
26 | 28 | debug { |
27 | 29 | minifyEnabled false |
28 | 30 | buildConfigField("String", "SERVER_URL", "\"${url.server_url}\"") |
29 | - buildConfigField("String", "APIKey", "\"OmmSqorNFXjVHXlZWhHAyGyQ\"") | |
30 | - buildConfigField("String", "SecretKey", "\"Uwjz4XGi89RN4Mvl5mievKpjqpGgUy6D\"") | |
31 | 31 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
32 | 32 | } |
33 | 33 | release { |
34 | 34 | minifyEnabled false |
35 | 35 | buildConfigField("String", "SERVER_URL", "\"${url.server_url_online}\"") |
36 | - buildConfigField("String", "APIKey", "\"OmmSqorNFXjVHXlZWhHAyGyQ\"") | |
37 | - buildConfigField("String", "SecretKey", "\"Uwjz4XGi89RN4Mvl5mievKpjqpGgUy6D\"") | |
38 | 36 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
39 | 37 | } |
40 | 38 | } | ... | ... |
libs/common/src/main/java/com/prws/common/net/NetWorks.java
... | ... | @@ -24,6 +24,7 @@ import com.prws.common.utils.SharedPreferencesUtil; |
24 | 24 | |
25 | 25 | import java.io.File; |
26 | 26 | import java.util.HashMap; |
27 | +import java.util.LinkedHashMap; | |
27 | 28 | import java.util.List; |
28 | 29 | import java.util.Map; |
29 | 30 | |
... | ... | @@ -38,6 +39,7 @@ import okhttp3.RequestBody; |
38 | 39 | import okhttp3.ResponseBody; |
39 | 40 | import retrofit2.Call; |
40 | 41 | import retrofit2.Callback; |
42 | +import retrofit2.Retrofit; | |
41 | 43 | import retrofit2.http.Body; |
42 | 44 | import retrofit2.http.GET; |
43 | 45 | import retrofit2.http.Header; |
... | ... | @@ -58,7 +60,8 @@ import retrofit2.http.Url; |
58 | 60 | */ |
59 | 61 | public class NetWorks extends RetrofitUtils { |
60 | 62 | //服务器路径 |
61 | - public static final NetService service_url = getMachineRetrofit(BuildConfig.SERVER_URL).create(NetService.class); | |
63 | + public static final Retrofit retrofit = getMachineRetrofit(BuildConfig.SERVER_URL); | |
64 | + public static final NetService service_url = retrofit.create(NetService.class); | |
62 | 65 | |
63 | 66 | //设缓存有效期为1天 |
64 | 67 | protected static final long CACHE_STALE_SEC = 60 * 60 * 24 * 1; |
... | ... | @@ -152,6 +155,12 @@ public class NetWorks extends RetrofitUtils { |
152 | 155 | @POST |
153 | 156 | Observable<JsonObject> removeWriting(@Url String url, @Body RequestBody body); |
154 | 157 | |
158 | + @POST("https://aip.baidubce.com/rest/2.0/ocr/v1/doc_crop_enhance") | |
159 | + Observable<JsonObject> baiduEnhance( | |
160 | + @Query("access_token") String token, | |
161 | + @Body Object any | |
162 | + ); | |
163 | + | |
155 | 164 | @POST |
156 | 165 | Observable<CutPicBean> cut(@Url String url, @Body RequestBody body); |
157 | 166 | |
... | ... | @@ -336,6 +345,14 @@ public class NetWorks extends RetrofitUtils { |
336 | 345 | setSubscribe(service_url.removeWriting(("https://aip.baidubce.com/rest/2.0/ocr/v1/remove_handwriting?access_token=" + getBaiduToken()), body), observer); |
337 | 346 | } |
338 | 347 | |
348 | + public static void baiduEnhance(String base64, Observer<JsonObject> observer) { | |
349 | + Map<String, Object> body = new LinkedHashMap<>(); | |
350 | + body.put("image", base64); | |
351 | + body.put("scan_type", 3); | |
352 | + body.put("enhance_type", 3); | |
353 | + setSubscribe(service_url.baiduEnhance(getBaiduToken(), body), observer); | |
354 | + } | |
355 | + | |
339 | 356 | public static void searchTeacher(String phone, Observer<ResponseResult<Teacher>> observer) { |
340 | 357 | setSubscribe(service_url.searchTeacher(getHeader(), phone), observer); |
341 | 358 | } | ... | ... |
libs/common/src/main/java/com/prws/common/net/SignInterceptor.java
1 | 1 | package com.prws.common.net; |
2 | 2 | |
3 | +import androidx.annotation.NonNull; | |
4 | + | |
5 | +import com.prws.common.BuildConfig; | |
3 | 6 | import com.prws.common.utils.SharedPreferencesUtil; |
4 | 7 | |
5 | 8 | import org.apache.commons.codec.binary.Hex; |
... | ... | @@ -14,23 +17,20 @@ import okhttp3.Request; |
14 | 17 | import okhttp3.Response; |
15 | 18 | |
16 | 19 | public class SignInterceptor implements Interceptor { |
20 | + @NonNull | |
17 | 21 | @Override |
18 | 22 | public Response intercept(Chain chain) throws IOException { |
19 | -// String appId = "1"; | |
20 | -// String APP_SECRET = "a839c40e04477d43705a64ba9db23b0dba969df360c3e428add85a6f5b8d0622"; | |
21 | -// String timestamp = String.valueOf(new Date().getTime()); | |
22 | -// String nonce = String.valueOf(new Random().nextInt(10000)); | |
23 | -// String sign = DigestUtils.md5Hex(appId + APP_SECRET + timestamp + nonce); // yidao板子报错 采用如下代码 | |
24 | -// byte[] signBytes = DigestUtils.md5(appId + APP_SECRET + timestamp + nonce); | |
25 | -// String sign = new String(Hex.encodeHex(signBytes)); | |
23 | + String host = BuildConfig.SERVER_URL; | |
24 | + if (!chain.request().url().toString().startsWith(host)) { | |
25 | + return chain.proceed(chain.request()); | |
26 | + } | |
27 | + | |
26 | 28 | String token = (String) SharedPreferencesUtil.getData("token",""); |
27 | 29 | Request.Builder requestBuilder = chain.request().newBuilder(); |
28 | 30 | if (token != null && token.length() > 0) { |
29 | 31 | requestBuilder = chain.request().newBuilder() |
30 | 32 | .header("Authorization", token); |
31 | 33 | } |
32 | -// .header("Content-Type","application/json"); | |
33 | - | |
34 | 34 | return chain.proceed(requestBuilder.build()); |
35 | 35 | } |
36 | 36 | } | ... | ... |
libs/common/src/main/java/com/prws/common/utils/BitmapUtils.java
... | ... | @@ -166,7 +166,12 @@ public class BitmapUtils { |
166 | 166 | /** |
167 | 167 | * 将图片转换成Base64编码的字符串 |
168 | 168 | */ |
169 | - public static String imageToBase64(String path) { | |
169 | + public static String imageToBase64WithUrlEncode(String path) { | |
170 | + return imageToBase64(path, true); | |
171 | + } | |
172 | + | |
173 | + public static String imageToBase64(String path, boolean urlEncode) { | |
174 | + | |
170 | 175 | if (TextUtils.isEmpty(path)) { |
171 | 176 | return null; |
172 | 177 | } |
... | ... | @@ -193,7 +198,8 @@ public class BitmapUtils { |
193 | 198 | } |
194 | 199 | |
195 | 200 | } |
196 | - return toURLEncoded(result); | |
201 | + if (urlEncode) return toURLEncoded(result); | |
202 | + else return result; | |
197 | 203 | } |
198 | 204 | |
199 | 205 | ... | ... |