Skip to content

Commit

Permalink
SmsTranslation Project
Browse files Browse the repository at this point in the history
  • Loading branch information
EdenOvad committed Jul 10, 2024
1 parent eec3d77 commit c02959c
Show file tree
Hide file tree
Showing 71 changed files with 2,555 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
plugins {
alias(libs.plugins.androidApplication)
}

android {
namespace 'com.kalman_aovid_arges.smstranslation'
compileSdk 34

defaultConfig {
applicationId "com.kalman_aovid_arges.smstranslation"
minSdk 30
targetSdk 34
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {

implementation libs.appcompat
implementation libs.material
implementation libs.ui.android
implementation libs.preference
implementation libs.activity
implementation libs.constraintlayout
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core
implementation libs.gson
implementation libs.work.runtime

def room_version = "2.6.1"

implementation libs.room.runtime.v261
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation libs.translate
implementation libs.language.id
implementation libs.android.gif.drawable
}
21 changes: 21 additions & 0 deletions src/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
66 changes: 66 additions & 0 deletions src/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.kalman_aovid_arges.smstranslation">

<uses-feature
android:name="android.hardware.telephony"
android:required="false" />

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.SMSTranslation">
<activity
android:name=".SMSViewActivity"
android:exported="false" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".InboxActivity" />
</activity>

<activity
android:name=".SettingsActivity"
android:exported="false"
android:label="@string/title_activity_settings">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".InboxActivity" />
</activity>
<activity
android:name=".InboxActivity"
android:exported="false" />
<activity
android:name=".SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".AboutActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".InboxActivity" />
</activity>

<receiver
android:name=".SmsReceiver"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.kalman_aovid_arges.smstranslation;

import android.os.Bundle;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class AboutActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_about);
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle("About");
}
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.kalman_aovid_arges.smstranslation;

import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.TypeConverters;

@Database(entities = {SMSGroup.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
public abstract SMSGroupDao smsGroupDao();

private static volatile AppDatabase INSTANCE;

public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, "db-sms")
.fallbackToDestructiveMigration()
.build();
}
}
}
return INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package com.kalman_aovid_arges.smstranslation;

import android.content.Context;
import android.content.SharedPreferences;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.mlkit.nl.languageid.LanguageIdentification;
import com.google.mlkit.nl.languageid.LanguageIdentifier;
import com.google.mlkit.nl.translate.TranslateLanguage;
import com.google.mlkit.nl.translate.Translation;
import com.google.mlkit.nl.translate.Translator;
import com.google.mlkit.nl.translate.TranslatorOptions;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;

public class BackgroundWorker extends Worker {
public BackgroundWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}

@NonNull
@Override
public Result doWork() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
boolean isBackgroundTranslationEnabled = preferences.getBoolean("background_translation", false);

if(isBackgroundTranslationEnabled){
translateAllMessages();
}

return Result.success();
}
void translateAllMessages(){
AppDatabase db = AppDatabase.getInstance(getApplicationContext());
List<SMSGroup> smsGroups = db.smsGroupDao().getAll();

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String targetLanguagePref = sharedPreferences.getString("language", "english");

String targetLanguageCode;
if (targetLanguagePref.equals("hebrew")) {
targetLanguageCode = TranslateLanguage.HEBREW;
} else {
targetLanguageCode = TranslateLanguage.ENGLISH;
}

LanguageIdentifier languageIdentifier = LanguageIdentification.getClient();


for (SMSGroup g: smsGroups){
CountDownLatch latch = new CountDownLatch(g.getMessages().size());
for (SMSMessage message : g.getMessages()) {
if (!message.getIsTranslated()) {
languageIdentifier.identifyLanguage(message.getMsgBody())
.addOnSuccessListener(languageCode -> {
if (!languageCode.equals("und")) {
TranslatorOptions options = new TranslatorOptions.Builder()
.setSourceLanguage(Objects.requireNonNull(TranslateLanguage.fromLanguageTag(languageCode)))
.setTargetLanguage(targetLanguageCode)
.build();

Translator translator = Translation.getClient(options);
translator.downloadModelIfNeeded().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void unused) {

}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
}
});
translator.translate(message.getMsgBody())
.addOnSuccessListener(translatedText -> {
message.setTranslatedMsgBody(translatedText);
message.setIsTranslated(true);
latch.countDown();
})
.addOnFailureListener(e -> {
latch.countDown();
});
} else {
latch.countDown();
}
})
.addOnFailureListener(e -> {
e.printStackTrace();
latch.countDown();
});
} else {
latch.countDown();
}
}

}

db.smsGroupDao().insertAll((SMSGroup) smsGroups);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.kalman_aovid_arges.smstranslation;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import androidx.room.TypeConverter;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.io.ByteArrayOutputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

public class Converters {
@TypeConverter
public static Bitmap fromByteArray(byte[] value) {
return value == null ? null : BitmapFactory.decodeByteArray(value, 0, value.length);
}

@TypeConverter
public static byte[] bitmapToByteArray(Bitmap bitmap) {
if (bitmap == null) {
return null;
}

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
return outputStream.toByteArray();
}

@TypeConverter
public static LocalDateTime fromString(String value) {
return value == null ? null : LocalDateTime.parse(value, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}

@TypeConverter
public static String localDateTimeToString(LocalDateTime dateTime) {
return dateTime == null ? null : dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}

@TypeConverter
public static List<SMSMessage> fromJson(String value) {
return new Gson().fromJson(value, new TypeToken<List<SMSMessage>>() {}.getType());
}

@TypeConverter
public static String fromList(List<SMSMessage> list) {
return new Gson().toJson(list);
}
}
Loading

0 comments on commit c02959c

Please sign in to comment.