Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue #44 - Internet permission #45

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions translate/final/app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2019 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.google.mlkit.codelab.translate"
minSdkVersion 21
targetSdkVersion 29
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
}
kotlinOptions {
jvmTarget = "1.8"
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.3.0'
implementation 'androidx.fragment:fragment-ktx:1.2.4'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

// Add CameraX dependencies
def camerax_version = "1.0.0-beta10"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-view:1.0.0-alpha17"

// Add ML Kit dependencies
implementation 'com.google.android.gms:play-services-mlkit-text-recognition:16.1.1'
implementation 'com.google.mlkit:language-id:16.1.1'
implementation 'com.google.mlkit:translate:16.1.1'
}
21 changes: 21 additions & 0 deletions translate/final/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
45 changes: 45 additions & 0 deletions translate/final/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2019 Google Inc. All Rights Reserved.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.mlkit.codelab.translate">

<uses-permission android:name="android.permission.CAMERA" />
<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/AppTheme">
<activity android:name=".MainActivity" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Automatically download the text recognition model after app install -->
<meta-data
android:name="com.google.ml.vision.DEPENDENCIES"
android:value="ocr" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2019 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.google.mlkit.codelab.translate

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.mlkit.codelab.translate.main.MainFragment

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, MainFragment.newInstance())
.commitNow()
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright 2019 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package com.google.mlkit.codelab.translate.analyzer

import android.content.Context
import android.graphics.Rect
import android.util.Log
import android.widget.Toast
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.MutableLiveData
import com.google.android.gms.tasks.Task
import com.google.mlkit.common.MlKitException
import com.google.mlkit.codelab.translate.util.ImageUtils
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.text.Text
import com.google.mlkit.vision.text.TextRecognition
import java.lang.Exception

/**
* Analyzes the frames passed in from the camera and returns any detected text within the requested
* crop region.
*/
class TextAnalyzer(
private val context: Context,
private val lifecycle: Lifecycle,
private val result: MutableLiveData<String>,
private val imageCropPercentages: MutableLiveData<Pair<Int, Int>>
) : ImageAnalysis.Analyzer {

// TODO: Instantiate TextRecognition detector

// TODO: Add lifecycle observer to properly close ML Kit detectors

@androidx.camera.core.ExperimentalGetImage
override fun analyze(imageProxy: ImageProxy) {
val mediaImage = imageProxy.image ?: return

val rotationDegrees = imageProxy.imageInfo.rotationDegrees

// We requested a setTargetAspectRatio, but it's not guaranteed that's what the camera
// stack is able to support, so we calculate the actual ratio from the first frame to
// know how to appropriately crop the image we want to analyze.
val imageHeight = mediaImage.height
val imageWidth = mediaImage.width

val actualAspectRatio = imageWidth / imageHeight

val convertImageToBitmap = ImageUtils.convertYuv420888ImageToBitmap(mediaImage)
val cropRect = Rect(0, 0, imageWidth, imageHeight)

// If the image has a way wider aspect ratio than expected, crop less of the height so we
// don't end up cropping too much of the image. If the image has a way taller aspect ratio
// than expected, we don't have to make any changes to our cropping so we don't handle it
// here.
val currentCropPercentages = imageCropPercentages.value ?: return
if (actualAspectRatio > 3) {
val originalHeightCropPercentage = currentCropPercentages.first
val originalWidthCropPercentage = currentCropPercentages.second
imageCropPercentages.value =
Pair(originalHeightCropPercentage / 2, originalWidthCropPercentage)
}

// If the image is rotated by 90 (or 270) degrees, swap height and width when calculating
// the crop.
val cropPercentages = imageCropPercentages.value ?: return
val heightCropPercent = cropPercentages.first
val widthCropPercent = cropPercentages.second
val (widthCrop, heightCrop) = when (rotationDegrees) {
90, 270 -> Pair(heightCropPercent / 100f, widthCropPercent / 100f)
else -> Pair(widthCropPercent / 100f, heightCropPercent / 100f)
}

cropRect.inset(
(imageWidth * widthCrop / 2).toInt(),
(imageHeight * heightCrop / 2).toInt()
)
val croppedBitmap =
ImageUtils.rotateAndCrop(convertImageToBitmap, rotationDegrees, cropRect)

// TODO call recognizeText() once implemented
}

fun recognizeText() {
// TODO Use ML Kit's TextRecognition to analyze frames from the camera live feed.
}

private fun getErrorMessage(exception: Exception): String? {
val mlKitException = exception as? MlKitException ?: return exception.message
return if (mlKitException.errorCode == MlKitException.UNAVAILABLE) {
"Waiting for text recognition model to be downloaded"
} else exception.message
}

companion object {
private const val TAG = "TextAnalyzer"
}
}
Loading