Commit 8494f382 authored by bixing's avatar bixing

update

parent d3446114
......@@ -22,14 +22,38 @@ android {
buildTypes {
release {
minifyEnabled false
debuggable false
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'app-proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
signingConfigs {
toolsTest {
storeFile file("../test.jks")
storePassword '123456'
keyAlias 'key0'
keyPassword '123456'
}
}
flavorDimensions "versionName"
productFlavors {
transalte {
applicationId "com.ads.cal.picturetranslate"
versionName "1.0.0.0"
signingConfig signingConfigs.toolsTest
}
}
}
dependencies {
......@@ -69,5 +93,6 @@ dependencies {
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.27'
implementation("org.greenrobot:eventbus:3.3.1")
}
\ No newline at end of file
......@@ -11,6 +11,8 @@
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature
......@@ -31,11 +33,12 @@
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="ocr" />
android:value="ocr,ocr_chinese,ocr_devanagari,ocr_japanese,ocr_korean" />
<activity
android:name=".activity.PictureTranslateStartActivity"
android:exported="true"
android:theme="@style/Theme.PictureTranslate"
android:screenOrientation="portrait">
<intent-filter>
......@@ -75,6 +78,11 @@
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait"
android:exported="true" />
<activity
android:name=".activity.PrivacyPolicyActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait"
android:exported="true" />
</application>
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>Privacy Policy</title>
</head>
<body>
<h1>Privacy Policy</h1>
<p>Thank you for using our Android Image Text Extraction app. We highly value your privacy, and as such, we have formulated the following privacy policy to help you understand how we collect, use, and protect your personal information. Please read the following carefully.</p>
<h2>Collected Information</h2>
<p>Our app uses the following third-party frameworks and permissions to provide its functionality and may collect the following information:</p>
<h3>1. Glide</h3>
<p>We use Glide to load and display images. Glide may collect information about your device and image loading to enhance performance and user experience.</p>
<h3>2. Android-Gif-Drawable</h3>
<p>Android-Gif-Drawable is used to support the display of GIF images. It may collect information about GIF images for proper decoding and display.</p>
<h3>3. EventBus</h3>
<p>EventBus is used for event handling and communication. It may log information related to event handling but does not directly collect personally identifiable information.</p>
<h3>4. AndroidX.Camera</h3>
<p>We use AndroidX.Camera to access the camera device for image text extraction. The app will require the following permissions:</p>
<ul>
<li><code>android.permission.CAMERA</code></li>
<li><code>android.hardware.camera.any</code></li>
<li><code>android.hardware.camera</code> (optional, if available)</li>
</ul>
<h3>5. Google ML Kit</h3>
<p>We use Google ML Kit for image text extraction. This framework may involve processing of image data but does not store or transmit images or extracted text data.</p>
<h3>6. Other Permissions</h3>
<p>The app may also require the following permissions:</p>
<ul>
<li><code>android.permission.RECORD_AUDIO</code></li>
<li><code>android.permission.WRITE_EXTERNAL_STORAGE</code> (only for Android versions 28 and below)</li>
<li><code>android.permission.READ_MEDIA_IMAGES</code></li>
</ul>
<h2>Use of Information</h2>
<p>The information we collect will be used for the following purposes:</p>
<ul>
<li>Providing the core functionality of the app, such as image text extraction.</li>
<li>Improving app performance and user experience.</li>
<li>Complying with legal regulations and requirements.</li>
</ul>
<h2>Protection of Information</h2>
<p>We have implemented appropriate security measures to protect your personal information from unauthorized access, disclosure, or misuse. We retain your information only for the duration necessary to fulfill the collection purposes.</p>
<h2>Contact Us</h2>
<p>If you have any questions or concerns regarding our privacy policy or data processing, please feel free to contact us through the following means:</p>
<p>Email: contact@example.com</p>
<p>This privacy policy may be updated periodically, and we recommend checking it regularly for the latest information.</p>
<p>Last Updated: September 27, 2023</p>
<hr>
</body>
</html>
\ No newline at end of file
package com.ads.cal.picturetranslate;
public class MessageEvent {
public static final int UPDATE_HOME_DATA = 1;
public static final int FINISH_ACTIVITY = 2;
public MessageEvent(int type, Object o) {
this.type = type;
this.object = o;
}
public Object object;
public int type;
}
......@@ -9,6 +9,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.camera.core.ExperimentalGetImage;
import com.ads.cal.picturetranslate.R;
import com.ads.cal.picturetranslate.base.BaseActivity;
......@@ -20,7 +21,7 @@ import pl.droidsonroids.gif.GifDrawable;
import pl.droidsonroids.gif.GifImageView;
import pl.droidsonroids.gif.InputSource;
public class AboutActivity extends BaseActivity {
@ExperimentalGetImage public class AboutActivity extends BaseActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
......@@ -41,7 +42,7 @@ public class AboutActivity extends BaseActivity {
TextView versionCode = findViewById(R.id.versioncode);
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
versionCode.setText(String.valueOf(packageInfo.versionCode));
versionCode.setText(String.valueOf(packageInfo.versionName));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
......
......@@ -14,6 +14,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ExperimentalGetImage;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
......@@ -34,7 +35,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import java.io.File;
public class CameraActivity extends BaseActivity implements ImageAnalysis.Analyzer {
@ExperimentalGetImage public class CameraActivity extends BaseActivity implements ImageAnalysis.Analyzer {
private static final int SELECT_TAKE_PHONE = 1;
private ImageCapture imageCapture;
......
......@@ -16,6 +16,7 @@ import androidx.annotation.Nullable;
import androidx.camera.core.ExperimentalGetImage;
import com.ads.cal.picturetranslate.LogUtils;
import com.ads.cal.picturetranslate.MessageEvent;
import com.ads.cal.picturetranslate.PictureApplication;
import com.ads.cal.picturetranslate.PictureTranslateUtils;
import com.ads.cal.picturetranslate.R;
......@@ -26,6 +27,8 @@ import com.ads.cal.picturetranslate.fragment.LoadingFragment;
import com.edmodo.cropper.CropImageView;
import com.google.mlkit.vision.common.InputImage;
import org.greenrobot.eventbus.EventBus;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
......@@ -77,6 +80,7 @@ public class PictureTranslateCutOutPhotoActivity extends BaseActivity {
bean.setTitle(text.getText());
bean.setTime(System.currentTimeMillis());
PictureTranslateResultActivity.startPictureTranslateResultActivity(PictureTranslateCutOutPhotoActivity.this, bean);
EventBus.getDefault().post(new MessageEvent(MessageEvent.FINISH_ACTIVITY, null));
finish();
if (bitmap.isRecycled()) {
return;
......
......@@ -29,6 +29,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.ads.cal.picturetranslate.LogUtils;
import com.ads.cal.picturetranslate.MessageEvent;
import com.ads.cal.picturetranslate.PermissionUtil;
import com.ads.cal.picturetranslate.PictureApplication;
import com.ads.cal.picturetranslate.R;
......@@ -37,8 +38,13 @@ import com.ads.cal.picturetranslate.ThreadUtils;
import com.ads.cal.picturetranslate.adapter.PictureTranslateListAdapter;
import com.ads.cal.picturetranslate.base.BaseActivity;
import com.ads.cal.picturetranslate.bean.PictureTranslateBean;
import com.ads.cal.picturetranslate.fragment.DeleteFragment;
import com.ads.cal.picturetranslate.fragment.SettingFragment;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
......@@ -59,6 +65,7 @@ public class PictureTranslateListMainActivity extends BaseActivity implements Ac
private FrameLayout settingContent;
private TextView title, hintAnimText;
private AnimatorSet animatorSet;
private ImageView setting, home, delete, selectImg;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
......@@ -67,6 +74,32 @@ public class PictureTranslateListMainActivity extends BaseActivity implements Ac
initView();
initData();
requestData();
EventBus.getDefault().register(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
if (event != null && event.type == MessageEvent.UPDATE_HOME_DATA) {
if (adapter != null && event.object instanceof PictureTranslateBean) {
adapter.updateData((PictureTranslateBean) event.object);
}
}
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Override
......@@ -103,7 +136,7 @@ public class PictureTranslateListMainActivity extends BaseActivity implements Ac
private void initView() {
ImageView take_photo = findViewById(R.id.take_photo);
take_photo.setOnClickListener(v -> checkSelfPermission());
ImageView selectImg = findViewById(R.id.select_);
selectImg = findViewById(R.id.select_);
selectImg.setOnClickListener(v -> {
PermissionUtil.checkSelfIMAGEPermission(PictureTranslateListMainActivity.this, PICK_IMAGE_REQUEST);
});
......@@ -114,11 +147,14 @@ public class PictureTranslateListMainActivity extends BaseActivity implements Ac
recyclerView.setAdapter(adapter);
notData = findViewById(R.id.not_data_layout);
settingContent = findViewById(R.id.setting_content);
ImageView setting = findViewById(R.id.setting);
setting = findViewById(R.id.setting);
setting.setOnClickListener(v -> {
showFragment(settingFragment, R.id.setting_content);
settingContent.setVisibility(View.VISIBLE);
title.setText(getString(R.string.app_setting));
setHomeAndSettingStatue(1);
});
home = findViewById(R.id.home);
home.setSelected(true);
home.setOnClickListener(v -> {
setHomeAndSettingStatue(0);
});
title = findViewById(R.id.title);
title.setText(getString(R.string.app_recent));
......@@ -129,9 +165,9 @@ public class PictureTranslateListMainActivity extends BaseActivity implements Ac
} else {
startAnimation(hintAnimText);
}
ImageView delete = findViewById(R.id.delete);
delete = findViewById(R.id.delete);
delete.setOnClickListener(v -> {
PictureApplication.getDataBaseManager().deleteData();
showFragment(new DeleteFragment(), android.R.id.content);
});
}
......@@ -148,7 +184,7 @@ public class PictureTranslateListMainActivity extends BaseActivity implements Ac
}
}
private void requestData() {
public void requestData() {
ThreadUtils.startRunnable(() -> {
List<PictureTranslateBean> arrayList = PictureApplication.getDataBaseManager().queryData();
Collections.reverse(arrayList);
......@@ -198,8 +234,41 @@ public class PictureTranslateListMainActivity extends BaseActivity implements Ac
if (settingContent.getVisibility() == View.GONE) {
super.onBackPressed();
} else {
settingContent.setVisibility(View.GONE);
title.setText(getString(R.string.app_recent));
setHomeAndSettingStatue(0);
}
}
private void setHomeAndSettingStatue(int index) {
switch (index) {
case 0:
if (settingContent.getVisibility() != View.GONE) {
settingContent.setVisibility(View.GONE);
}
title.setText(getString(R.string.app_recent));
setting.setSelected(false);
home.setSelected(true);
if (delete.getVisibility() != View.VISIBLE) {
delete.setVisibility(View.VISIBLE);
}
if (selectImg.getVisibility() != View.VISIBLE) {
selectImg.setVisibility(View.VISIBLE);
}
break;
case 1:
setting.setSelected(true);
home.setSelected(false);
showFragment(settingFragment, R.id.setting_content);
if (settingContent.getVisibility() != View.VISIBLE) {
settingContent.setVisibility(View.VISIBLE);
}
if (delete.getVisibility() != View.GONE) {
delete.setVisibility(View.GONE);
}
if (selectImg.getVisibility() != View.GONE) {
selectImg.setVisibility(View.GONE);
}
title.setText(getString(R.string.app_setting));
break;
}
}
......
......@@ -27,6 +27,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
......@@ -35,9 +36,11 @@ import androidx.annotation.Nullable;
import androidx.camera.core.ExperimentalGetImage;
import com.ads.cal.picturetranslate.LogUtils;
import com.ads.cal.picturetranslate.MessageEvent;
import com.ads.cal.picturetranslate.PictureApplication;
import com.ads.cal.picturetranslate.PictureTranslateUtils;
import com.ads.cal.picturetranslate.R;
import com.ads.cal.picturetranslate.ThreadUtils;
import com.ads.cal.picturetranslate.Util;
import com.ads.cal.picturetranslate.base.BaseActivity;
import com.ads.cal.picturetranslate.bean.PictureTranslateBean;
......@@ -48,6 +51,8 @@ import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.text.Text;
import com.google.mlkit.vision.text.TextRecognizer;
import org.greenrobot.eventbus.EventBus;
@ExperimentalGetImage
public class PictureTranslateResultActivity extends BaseActivity {
......@@ -72,12 +77,15 @@ public class PictureTranslateResultActivity extends BaseActivity {
LinearLayout back = findViewById(R.id.back);
back.setOnClickListener(v -> {
if (pictureTranslateBean != null && !TextUtils.isEmpty(pictureTranslateBean.getTitle())) {
PictureApplication.getDataBaseManager().insertData(path, pictureTranslateBean.getTitle(), System.currentTimeMillis());
long time = System.currentTimeMillis();
pictureTranslateBean.setNewTime(time);
Toast.makeText(this, getString(R.string.app_save_automatically), Toast.LENGTH_SHORT).show();
updateAndInsertData();
}
finish();
});
result_txt = findViewById(R.id.result_txt);
result_txt.setMaxHeight(Util.getScreenHeight(this) - 200);
result_txt.setMaxHeight((int) (Util.getScreenHeight(this) - (getResources().getDisplayMetrics().density * 300 + 0.5f)));
TextView more_translate = findViewById(R.id.more);
String text = getString(R.string.app_more_select);
SpannableString spannableString = new SpannableString(text);
......@@ -223,10 +231,24 @@ public class PictureTranslateResultActivity extends BaseActivity {
public void onBackPressed() {
super.onBackPressed();
if (pictureTranslateBean != null && !TextUtils.isEmpty(pictureTranslateBean.getTitle())) {
PictureApplication.getDataBaseManager().insertData(path, pictureTranslateBean.getTitle(), System.currentTimeMillis());
long time = System.currentTimeMillis();
pictureTranslateBean.setNewTime(time);
Toast.makeText(this, getString(R.string.app_save_automatically), Toast.LENGTH_SHORT).show();
updateAndInsertData();
}
}
private void updateAndInsertData() {
ThreadUtils.startRunnable(() -> {
if (pictureTranslateBean.getTime() != 0) {
PictureApplication.getDataBaseManager().deleteData(pictureTranslateBean.getTime());
}
PictureApplication.getDataBaseManager().insertData(path, pictureTranslateBean.getTitle(), pictureTranslateBean.getNewTime());
runOnUiThread(() -> EventBus.getDefault().post(new MessageEvent(MessageEvent.UPDATE_HOME_DATA, pictureTranslateBean)));
});//1695871418961
}
public static void startPictureTranslateResultActivity(Context context, PictureTranslateBean bean) {
Intent intent = new Intent(context, PictureTranslateResultActivity.class);
......@@ -241,10 +263,6 @@ public class PictureTranslateResultActivity extends BaseActivity {
LogUtils.e("AAAAAA", text.getText());
result_txt.setText(text.getText());
pictureTranslateBean.setTitle(text.getText());
PictureTranslateBean bean = new PictureTranslateBean();
bean.setImageUrl(path);
bean.setTitle(text.getText());
bean.setTime(System.currentTimeMillis());
hideLoadingFragment();
}
......
......@@ -20,22 +20,29 @@ import androidx.annotation.Nullable;
import androidx.camera.core.ExperimentalGetImage;
import com.ads.cal.picturetranslate.LogUtils;
import com.ads.cal.picturetranslate.MessageEvent;
import com.ads.cal.picturetranslate.PictureApplication;
import com.ads.cal.picturetranslate.PictureTranslateUtils;
import com.ads.cal.picturetranslate.R;
import com.ads.cal.picturetranslate.Util;
import com.ads.cal.picturetranslate.base.BaseActivity;
import com.ads.cal.picturetranslate.bean.PictureTranslateBean;
import com.ads.cal.picturetranslate.fragment.AgainFragment;
import com.ads.cal.picturetranslate.fragment.LoadingFragment;
import com.google.mlkit.vision.common.InputImage;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@ExperimentalGetImage public class PictureTranslateShowPhotoActivity extends BaseActivity {
@ExperimentalGetImage
public class PictureTranslateShowPhotoActivity extends BaseActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
......@@ -57,51 +64,64 @@ import java.io.OutputStream;
setContentView(R.layout.activity_show_photon);
initView();
initData();
EventBus.getDefault().register(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
if (event != null && event.type == MessageEvent.FINISH_ACTIVITY) {
finish();
}
}
private ImageView imageView;
private LinearLayout crop, extract;
private void initView() {
ImageView close = findViewById(R.id.close);
close.setOnClickListener(v -> finish());
LinearLayout crop = findViewById(R.id.crop);
crop = findViewById(R.id.crop);
crop.setOnClickListener(v -> PictureTranslateCutOutPhotoActivity.startCutOutPhotoActivity(this, uri));
LinearLayout extract = findViewById(R.id.extract);
extract = findViewById(R.id.extract);
extract.setOnClickListener(v -> {
if (path == null) {
return;
}
showLoadingFragment(new LoadingFragment());
Bitmap bitmap = BitmapFactory.decodeFile(path);
ExifInterface exif = null;
try {
exif = new ExifInterface(path);
} catch (IOException e) {
e.printStackTrace();
}
if (bitmap == null) {
hideLoadingFragment();
return;
}
Bitmap rotatedBitmap = rotateBitmapIfNecessary(bitmap, exif);
extractFunction();
});
imageView = findViewById(R.id.bg);
}
// 保存旋转后的图片
String resultPath = saveRotatedImage(rotatedBitmap);
public void extractFunction() {
if (path == null) {
return;
}
showLoadingFragment(new LoadingFragment());
Bitmap bitmap = BitmapFactory.decodeFile(path);
ExifInterface exif = null;
try {
exif = new ExifInterface(path);
} catch (IOException e) {
e.printStackTrace();
}
if (bitmap == null) {
hideLoadingFragment();
return;
}
Bitmap rotatedBitmap = rotateBitmapIfNecessary(bitmap, exif);
if (!resultPath.isEmpty()) {
translate(rotatedBitmap, resultPath);
} else {
Toast.makeText(this, getString(R.string.app_toast_unable_to_save_picture), Toast.LENGTH_SHORT).show();
}
// 保存旋转后的图片
String resultPath = saveRotatedImage(rotatedBitmap);
// 释放位图资源
bitmap.recycle();
});
imageView = findViewById(R.id.bg);
if (!resultPath.isEmpty()) {
translate(rotatedBitmap, resultPath, bitmap);
crop.setVisibility(View.GONE);
extract.setVisibility(View.GONE);
} else {
Toast.makeText(this, getString(R.string.app_toast_unable_to_save_picture), Toast.LENGTH_SHORT).show();
}
}
private void translate(Bitmap bitmap, String path) {
private void translate(Bitmap bitmap, String path, Bitmap sBitmap) {
if (bitmap == null) {
hideLoadingFragment();
return;
......@@ -113,21 +133,31 @@ import java.io.OutputStream;
PictureTranslateBean bean = new PictureTranslateBean();
bean.setImageUrl(path);
bean.setTitle(text.getText());
bean.setTime(System.currentTimeMillis());
PictureTranslateResultActivity.startPictureTranslateResultActivity(PictureTranslateShowPhotoActivity.this, bean);
finish();
if (bitmap.isRecycled()) {
return;
}
bitmap.recycle();
if (sBitmap == null || sBitmap.isRecycled()) {
return;
}
sBitmap.recycle();
},
e -> {
crop.setVisibility(View.VISIBLE);
extract.setVisibility(View.VISIBLE);
hideLoadingFragment();
showFragment(new AgainFragment(), android.R.id.content);
LogUtils.e("AAAAAA", e.getMessage());
if (bitmap.isRecycled()) {
return;
}
bitmap.recycle();
if (sBitmap == null || sBitmap.isRecycled()) {
return;
}
sBitmap.recycle();
});
}
......@@ -147,7 +177,7 @@ import java.io.OutputStream;
if (path == null || path.isEmpty()) {
Toast.makeText(this, getString(R.string.app_toast_the_file_is_corrupted), Toast.LENGTH_SHORT).show();
} else {
bitmap = BitmapFactory.decodeFile(path);
bitmap = BitmapFactory.decodeFile(path);
ExifInterface exif = null;
try {
exif = new ExifInterface(path);
......@@ -167,7 +197,7 @@ import java.io.OutputStream;
int orientation = exif != null ? exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) : ExifInterface.ORIENTATION_NORMAL;
int rotate = getRotateValueForOrientation(orientation);
LogUtils.e(rotate+"");
LogUtils.e(rotate + "");
if (rotate != 0) {
matrix.postRotate(rotate);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
......@@ -259,6 +289,7 @@ import java.io.OutputStream;
return;
}
bitmap.recycle();
EventBus.getDefault().unregister(this);
}
public static void startPictureTranslateShowPhotoActivity(Context context, Uri uri) {
......
......@@ -68,7 +68,7 @@ public class PictureTranslateStartActivity extends BaseActivity {
}
public void setProgressBarProgress(int i) {
if (i >= 100) {
if (i > 100) {
if (handler != null) {
handler.removeCallbacksAndMessages(null);
}
......
package com.ads.cal.picturetranslate.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.camera.core.ExperimentalGetImage;
import com.ads.cal.picturetranslate.R;
import com.ads.cal.picturetranslate.base.BaseActivity;
@ExperimentalGetImage public class PrivacyPolicyActivity extends BaseActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_privacy_policy);
String html = "<h1>Privacy Policy</h1>\n" +
"\n" +
"<p>Thank you for using our Android Image Text Extraction app. We highly value your privacy, and as such, we have formulated the following privacy policy to help you understand how we collect, use, and protect your personal information. Please read the following carefully.</p>\n" +
"\n" +
"<h2>Collected Information</h2>\n" +
"\n" +
"<p>Our app uses the following third-party frameworks and permissions to provide its functionality and may collect the following information:</p>\n" +
"\n" +
"<h3>1. Glide</h3>\n" +
"<p>We use Glide to load and display images. Glide may collect information about your device and image loading to enhance performance and user experience.</p>\n" +
"\n" +
"<h3>2. Android-Gif-Drawable</h3>\n" +
"<p>Android-Gif-Drawable is used to support the display of GIF images. It may collect information about GIF images for proper decoding and display.</p>\n" +
"\n" +
"<h3>3. EventBus</h3>\n" +
"<p>EventBus is used for event handling and communication. It may log information related to event handling but does not directly collect personally identifiable information.</p>\n" +
"\n" +
"<h3>4. AndroidX.Camera</h3>\n" +
"<p>We use AndroidX.Camera to access the camera device for image text extraction. The app will require the following permissions:</p>\n" +
"<ul>\n" +
" <li><code>android.permission.CAMERA</code></li>\n" +
" <li><code>android.hardware.camera.any</code></li>\n" +
" <li><code>android.hardware.camera</code> (optional, if available)</li>\n" +
"</ul>\n" +
"\n" +
"<h3>5. Google ML Kit</h3>\n" +
"<p>We use Google ML Kit for image text extraction. This framework may involve processing of image data but does not store or transmit images or extracted text data.</p>\n" +
"\n" +
"<h3>6. Other Permissions</h3>\n" +
"<p>The app may also require the following permissions:</p>\n" +
"<ul>\n" +
" <li><code>android.permission.RECORD_AUDIO</code></li>\n" +
" <li><code>android.permission.WRITE_EXTERNAL_STORAGE</code> (only for Android versions 28 and below)</li>\n" +
" <li><code>android.permission.READ_MEDIA_IMAGES</code></li>\n" +
"</ul>\n" +
"\n" +
"<h2>Use of Information</h2>\n" +
"\n" +
"<p>The information we collect will be used for the following purposes:</p>\n" +
"<ul>\n" +
" <li>Providing the core functionality of the app, such as image text extraction.</li>\n" +
" <li>Improving app performance and user experience.</li>\n" +
" <li>Complying with legal regulations and requirements.</li>\n" +
"</ul>\n" +
"\n" +
"<h2>Protection of Information</h2>\n" +
"\n" +
"<p>We have implemented appropriate security measures to protect your personal information from unauthorized access, disclosure, or misuse. We retain your information only for the duration necessary to fulfill the collection purposes.</p>\n" +
"\n" +
"<h2>Contact Us</h2>\n" +
"\n" +
"<p>If you have any questions or concerns regarding our privacy policy or data processing, please feel free to contact us through the following means:</p>\n" +
"<p>Email: contact@example.com</p>\n" +
"\n" +
"<p>This privacy policy may be updated periodically, and we recommend checking it regularly for the latest information.</p>\n" +
"\n" +
"<p>Last Updated: September 27, 2023</p>\n" +
"\n" +
"<hr>";
TextView textView = findViewById(R.id.html);
textView.setText(Html.fromHtml(html));
textView.setMovementMethod(LinkMovementMethod.getInstance());
LinearLayout layout = findViewById(R.id.title_layout);
layout.setOnClickListener(v -> {
finish();
});
}
public static void startPrivacyPolicyActivity(Context context) {
Intent intent = new Intent(context, PrivacyPolicyActivity.class);
context.startActivity(intent);
}
}
......@@ -42,9 +42,16 @@ public class PictureTranslateListAdapter extends RecyclerView.Adapter<PictureTra
if (data == null) {
data = new ArrayList<>();
} else {
for (PictureTranslateBean translateBean : data) {
if (translateBean.getTime() == bean.getTime()) {
data.remove(translateBean);
break;
}
}
bean.setTime(bean.getNewTime());
data.add(0, bean);
}
notifyItemChanged(0);
notifyDataSetChanged();
}
public void updateData(List<PictureTranslateBean> beans) {
......
......@@ -3,19 +3,32 @@ package com.ads.cal.picturetranslate.base;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.camera.core.ExperimentalGetImage;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.ads.cal.picturetranslate.R;
import com.ads.cal.picturetranslate.activity.PictureTranslateStartActivity;
import com.ads.cal.picturetranslate.adapter.PictureTranslateListAdapter;
import com.ads.cal.picturetranslate.bean.PictureTranslateBean;
import com.ads.cal.picturetranslate.fragment.LoadingFragment;
public class BaseActivity extends FragmentActivity {
@ExperimentalGetImage public class BaseActivity extends FragmentActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (this instanceof PictureTranslateStartActivity) {
return;
}
getWindow().setStatusBarColor(getColor(R.color.color_0073FF)); // 设置颜色
}
......@@ -66,15 +79,26 @@ public class BaseActivity extends FragmentActivity {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (!fragment.isAdded()) {
fragmentTransaction.add(containerViewId, fragment);
if (containerViewId == android.R.id.content) {
fragmentTransaction.addToBackStack("fragment");
}
fragmentTransaction.commit();
} else {
fragmentTransaction.show(fragment);
}
}
public void popBackStackFragment() {
FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0) {
fragmentManager.popBackStack();
}
}
protected void hineFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.hide(fragment);
}
}
......@@ -7,6 +7,7 @@ public class PictureTranslateBean implements Serializable {
private String imageUrl;
private String title;
private long time;
private long newTime;
public void setImageUrl(String imageUrl) {
......@@ -33,4 +34,11 @@ public class PictureTranslateBean implements Serializable {
return title;
}
public void setNewTime(long newTime) {
this.newTime = newTime;
}
public long getNewTime() {
return newTime;
}
}
package com.ads.cal.picturetranslate.fragment;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.camera.core.ExperimentalGetImage;
import androidx.fragment.app.Fragment;
import com.ads.cal.picturetranslate.R;
import com.ads.cal.picturetranslate.activity.PictureTranslateShowPhotoActivity;
import com.ads.cal.picturetranslate.base.BaseActivity;
@ExperimentalGetImage public class AgainFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return initView(inflater);
}
private View initView(LayoutInflater inflater) {
View view = inflater.inflate(R.layout.fragment_again, null, false);
view.findViewById(R.id.got_it).setOnClickListener(v -> {
Activity activity = getActivity();
if (activity instanceof PictureTranslateShowPhotoActivity) {
((PictureTranslateShowPhotoActivity)activity).extractFunction();
}
backFragment();
});
return view;
}
private void backFragment() {
Activity activity = getActivity();
if (activity instanceof BaseActivity) {
((BaseActivity)activity).popBackStackFragment();
}
}
}
package com.ads.cal.picturetranslate.fragment;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.camera.core.ExperimentalGetImage;
import androidx.fragment.app.Fragment;
import com.ads.cal.picturetranslate.PictureApplication;
import com.ads.cal.picturetranslate.R;
import com.ads.cal.picturetranslate.ThreadUtils;
import com.ads.cal.picturetranslate.activity.PictureTranslateListMainActivity;
import com.ads.cal.picturetranslate.base.BaseActivity;
@ExperimentalGetImage public class DeleteFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return initView(inflater);
}
private View initView(LayoutInflater inflater) {
View view = inflater.inflate(R.layout.fragment_delete, null, false);
TextView cancel = view.findViewById(R.id.cancel);
TextView clear = view.findViewById(R.id.clear);
cancel.setOnClickListener(v -> backFragment());
clear.setOnClickListener(v -> {
ThreadUtils.startRunnable(() -> {
PictureApplication.getDataBaseManager().deleteData();
Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(() -> {
if (activity instanceof PictureTranslateListMainActivity) {
((PictureTranslateListMainActivity)activity).requestData();
}
backFragment();
});
}
});
});
return view;
}
private void backFragment() {
Activity activity = getActivity();
if (activity instanceof BaseActivity) {
((BaseActivity)activity).popBackStackFragment();
}
}
}
package com.ads.cal.picturetranslate.fragment;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
......@@ -9,11 +10,17 @@ import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.camera.core.ExperimentalGetImage;
import androidx.fragment.app.Fragment;
import com.ads.cal.picturetranslate.R;
import com.ads.cal.picturetranslate.activity.AboutActivity;
import com.ads.cal.picturetranslate.activity.PrivacyPolicyActivity;
import java.util.Objects;
@ExperimentalGetImage
public class SettingFragment extends Fragment {
@Nullable
......@@ -28,32 +35,32 @@ public class SettingFragment extends Fragment {
RelativeLayout email_layout = view.findViewById(R.id.email_layout);
RelativeLayout policy_layout = view.findViewById(R.id.policy_layout);
RelativeLayout about_layout = view.findViewById(R.id.about_layout);
share_layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, "分享内容"); // 设置要分享的内容
startActivity(Intent.createChooser(shareIntent, "分享到"));
share_layout.setOnClickListener(v -> {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
Activity activity = getActivity();
if (activity != null) {
String packageName = activity.getPackageName();
shareIntent.putExtra(Intent.EXTRA_TEXT, "The best Text Extraction app ! \n https://play.google.com/store/apps/details?id=" + packageName); // 设置要分享的内容
}
startActivity(Intent.createChooser(shareIntent, "分享到"));
});
email_layout.setOnClickListener(v -> {
// 创建一个Intent,指定Action为发送邮件
Intent emailIntent = new Intent(Intent.ACTION_SEND);
// 设置邮件的类型为“text/plain”
emailIntent.setType("text/plain");
// 添加收件人(可选)
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"zl@cc.com"});
// 启动邮件客户端
startActivity(Intent.createChooser(emailIntent, "选择邮件客户端"));
});
policy_layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
// 创建一个Intent,指定Action为发送邮件
Intent emailIntent = new Intent(Intent.ACTION_SEND);
// 设置邮件的类型为“text/plain”
emailIntent.setType("text/plain");
// 添加收件人(可选)
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"zl@gmail.com"});
// 设置要使用的Gmail应用程序包名
emailIntent.setPackage("com.google.android.gm");
startActivity(emailIntent);
} catch (Exception e) {
e.printStackTrace();
}
});
policy_layout.setOnClickListener(v -> PrivacyPolicyActivity.startPrivacyPolicyActivity(getContext()));
about_layout.setOnClickListener(v -> AboutActivity.startAboutActivity(getContext()));
return view;
}
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="180dp"/>
<solid android:color="#e9eaef"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@mipmap/app_icon_recent_press"/>
<item android:state_selected="true" android:drawable="@mipmap/app_icon_recent_press"/>
<item android:drawable="@mipmap/app_icon_recent_default"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@mipmap/app_icon_setting_press"/>
<item android:state_selected="true" android:drawable="@mipmap/app_icon_setting_press"/>
<item android:drawable="@mipmap/app_icon_setting"/>
</selector>
\ No newline at end of file
......@@ -8,14 +8,22 @@
android:id="@+id/listData"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottom_nav"
android:layout_below="@+id/title" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:background="@color/white"
android:src="@mipmap/app_status_bar_bg" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="53dp"
android:layout_marginTop="19dp"
android:background="@color/white"
android:gravity="center_vertical"
android:paddingStart="14dp"
android:paddingEnd="14dp"
......@@ -48,12 +56,6 @@
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="@mipmap/app_status_bar_bg" />
<LinearLayout
android:id="@+id/not_data_layout"
android:layout_width="match_parent"
......@@ -82,21 +84,27 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/title"
android:clickable="true"
android:focusable="true"
android:background="@color/white"
android:visibility="gone" />
<RelativeLayout
android:id="@+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:layout_alignParentBottom="true"
android:background="@mipmap/app_nav_bg">
<ImageView
android:id="@+id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="70dp"
android:src="@mipmap/app_icon_photo" />
android:src="@drawable/app_home_icon_select" />
<ImageView
android:id="@+id/setting"
......@@ -105,7 +113,7 @@
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="70dp"
android:src="@mipmap/app_icon_setting" />
android:src="@drawable/app_setting_icon_select" />
</RelativeLayout>
......@@ -119,7 +127,6 @@
android:background="@mipmap/app_takephoto_hint"
android:gravity="center"
android:paddingBottom="15dp"
android:text="@string/app_take_photo_clk_hint"
android:textColor="@color/white"
android:textSize="14sp" />
......
......@@ -70,6 +70,7 @@
android:id="@+id/image"
android:layout_width="80dp"
android:layout_height="80dp"
android:scaleType="centerCrop"
android:layout_below="@+id/result_scroll"
android:layout_marginTop="20dp" />
......
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<LinearLayout
android:id="@+id/title_layout"
android:layout_width="wrap_content"
android:layout_height="53dp"
android:layout_marginTop="19dp"
android:orientation="horizontal"
android:paddingStart="14dp"
android:paddingEnd="14dp">
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:src="@mipmap/app_icon_gray_back" />
<TextView
android:layout_width="match_parent"
android:layout_height="53dp"
android:gravity="center_vertical"
android:text="@string/app_policy"
android:textColor="#1C1C1C"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="@mipmap/app_status_bar_bg" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/title_layout">
<TextView
android:id="@+id/html"
android:layout_width="match_parent"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:paddingTop="20dp"
android:textColor="@color/black"
android:layout_height="wrap_content" />
</ScrollView>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#99000000">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/app_white_corner_4"
android:orientation="vertical"
android:layout_gravity="center"
android:paddingStart="24dp"
android:paddingTop="27dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:paddingEnd="24dp"
android:paddingBottom="27dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_tip"
android:textColor="@color/black"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/app_again"
android:textColor="#5B5D62"
android:textSize="16sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<TextView
android:id="@+id/got_it"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_weight="1"
android:background="@drawable/app_extract_corner_180"
android:gravity="center"
android:text="@string/app_got_it"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#99000000">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/app_white_corner_4"
android:orientation="vertical"
android:layout_gravity="center"
android:paddingStart="24dp"
android:paddingTop="27dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:paddingEnd="24dp"
android:paddingBottom="27dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_tip"
android:textColor="@color/black"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/app_delete_history"
android:textColor="#5B5D62"
android:textSize="16sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<TextView
android:id="@+id/cancel"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_marginEnd="5dp"
android:layout_weight="1"
android:background="@drawable/app_e9eaef_corner_180"
android:gravity="center"
android:text="@string/app_cancel"
android:textColor="#5B5D62"
android:textSize="16sp" />
<TextView
android:id="@+id/clear"
android:layout_width="0dp"
android:layout_height="48dp"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:background="@drawable/app_extract_corner_180"
android:gravity="center"
android:text="@string/app_clear"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
......@@ -30,6 +30,12 @@
<string name="app_not_data">Noting found here</string>
<string name="app_take_photo_clk_hint">Click to take a photo to extract text</string>
<string name="app_delete">Delete</string>
<string name="app_tip">Tip</string>
<string name="app_delete_history">Are you sure to clear all the history right now?</string>
<string name="app_clear">Clear</string>
<string name="app_save_automatically">Saved Automatically</string>
<string name="app_again">The content was not recognized, please try again.</string>
<string name="app_got_it">Got it</string>
</resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment