android ExifInterface platform 1.5, 1.6 [duplicate] - android

Is there any 3rd part api for android to read exif tags from image which support api level starting from 1.5.

The metadata extraction library by Drew Noakes works well for extracting EXIF tags on earlier Android platform versions, with a slight modification. I am using it on Android 1.6 to extract tags from JPEG images.
NOTE: Newer versions of metadata-extractor work directly on Android without modification.
You will need to download and build the source code yourself, and package it with your app. (I'm using release 2.3.1.) Make the following changes to com.drew.imaging.jpeg.JpegMetadataReader:
Remove the following import statement:
import com.sun.image.codec.jpeg.JPEGDecodeParam;
Delete the following method (which you won't need on Android):
public static Metadata readMetadata(JPEGDecodeParam decodeParam) { ... }
Remove the com.drew.metadata.SampleUsage class, which references the method deleted above. Also remove all of the test packages.
That's all there is to it. Here's an example of using the JpegMetadataReader to extract a date-time tag from a JPEG image stored on the SD card:
import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifDirectory;
// other imports and class definition removed for brevity
public static Date extractExifDateTime(String imagePath)
{
Log.d("exif", "Attempting to extract EXIF date/time from image at " + imagePath);
Date datetime = new Date(0); // or initialize to null, if you prefer
try
{
Metadata metadata = JpegMetadataReader.readMetadata(new File(imagePath));
Directory exifDirectory = metadata.getDirectory(ExifDirectory.class);
// these are listed in order of preference
int[] datetimeTags = new int[] { ExifDirectory.TAG_DATETIME_ORIGINAL,
ExifDirectory.TAG_DATETIME,
ExifDirectory.TAG_DATETIME_DIGITIZED };
int datetimeTag = -1;
for (int tag : datetimeTags)
{
if (exifDirectory.containsTag(tag))
{
datetimeTag = tag;
break;
}
}
if (datetimeTag != -1)
{
Log.d("exif", "Using tag " + exifDirectory.getTagName(datetimeTag) + " for timestamp");
SimpleDateFormat exifDatetimeFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
datetime = exifDatetimeFormat.parse(exifDirectory.getString(datetimeTag));
}
else
{
Log.d("exif", "No date/time tags were found");
}
}
catch (Exception e)
{
Log.w("exif", "Unable to extract EXIF metadata from image at " + imagePath, e);
}
return datetime;
}

For what it worth, did you try to use the native ExifInterface class ?
http://developer.android.com/reference/android/media/ExifInterface.html
Should be must faster than using a 3rd party library ;)

Related

(Unity) How to read old game data on Android?

I created and published a game for android with AndEngine three years ago. Now I am preparing the game again with unity. When I send an update, all of the old data is deleted. Because Unity using 'PlayerPrefs' and Android using 'SharedPreferences'.
So, How do I read old data with Unity?
Here is my old code setup:
private SharedPreferences data;
private SharedPreferences.Editor editor;
// ======================================================================
public void setup(Activity activity) {
data = activity.getSharedPreferences("kayit", 0);
editor = data.edit();
}
I don't think its going to be easy accessing persistent data saved with a different engine - but a solution I can see is release an update with the old engine that will upload the data to a remote server, and then download it using Unity, but since you already released the unity version that might not work for you
PlayerPrefs and SharedPreferences are different things.
But there is a solution.
Unity allows to add native android Java or C++ code to your Unity project and use interfaces to access that code.
So you can write some code using Android SDK/NDK methods to access your SharedPreferences and add it as JAR or AAR to your Unity project.
Read about it in the official documentation https://docs.unity3d.com/Manual/PluginsForAndroid.html
private void ReadAndroidSharedPreferences(string packageName, string xmlDataName)
{
string path = "/data/data/" + packageName + "/shared_prefs/" + xmlDataName + ".xml";
FileStream levelFile = File.Open(path, FileMode.Open);
XmlDocument xmlDoc = new XmlDocument();
string xmlText = "";
using (StreamReader sr = new StreamReader(levelFile))
{
string line = null;
do
{
line = sr.ReadLine();
xmlText = xmlText + line + "\n";
} while (line != null);
sr.Close();
levelFile.Close();
}
xmlDoc.LoadXml(xmlText);
var baseNode = xmlDoc.DocumentElement;
foreach (XmlNode node in baseNode.ChildNodes)
{
Debug.Log("Type: " + node.Name);
if (node.Attributes["name"] != null)
Debug.Log("name: " + node.Attributes["name"].Value);
else
Debug.Log("Empty");
if (node.Attributes["value"] != null)
Debug.Log("Value: " + node.Attributes["value"].Value);
else
Debug.Log("Empty");
}
}
Usage:
packageName = "com.yourcompany.yourgame"
xmlDataName = getSharedPreferences file name (in my question, it's "kayit")
You can see all 'int' and 'bool' data on Android Device Monitor.

Missing Meta data in com.googlecode.libphonenumber:libphonenumber:8.8.2 while building signed APK

I added com.googlecode.libphonenumber:libphonenumber:8.8.2 in my project. In debug mode its works normally.But in signed apk its generating the following exception when a library method is called.
Caused by: java.lang.IllegalStateException: missing metadata: /com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD
at com.google.i18n.phonenumbers.e.getMetadataFromSingleFileName(SourceFile:188)
at com.google.i18n.phonenumbers.e.getMetadataFromMultiFilePrefix(SourceFile:116)
at com.google.i18n.phonenumbers.g.getMetadataForRegion(SourceFile:64)
at com.google.i18n.phonenumbers.PhoneNumberUtil.getMetadataForRegion(SourceFile:2211)
at com.google.i18n.phonenumbers.PhoneNumberUtil.getMetadataForRegionOrCallingCode(SourceFile:1330)
at com.google.i18n.phonenumbers.PhoneNumberUtil.parseHelper(SourceFile:3197)
at com.google.i18n.phonenumbers.PhoneNumberUtil.parse(SourceFile:3025)
at com.google.i18n.phonenumbers.PhoneNumberUtil.parse(SourceFile:3015)
at com.revesoft.itelmobiledialer.util.aq.b(SourceFile:697)ode here
Probably you have already fixed it, but it may help others. I had the same issue and I have fixed it as the library FAQs - How do I load libphonenumber resources in my Android app?
A possible problem can be that you are loading the metadata from the main thread. If this is not the case, then
you can copy the data folder with the metadata in your app. Create an assets folder src/main/assets/data.
In your application where you first want to read the data, create your own metadata loader that will read the metadata from its new destination. This is described in the link that I posted. The library FAQs suggest to delete the metadata files from the library in order not to duplicate files.
private static PhoneNumberUtil getPhoneNumberUtilInstance()
{
if(mPhoneNumberUtil == null)
{
mPhoneNumberUtil = PhoneNumberUtil.createInstance(new MetadataLoader()
{
#Override
public InputStream loadMetadata(String metadataFileName)
{
try
{
String[] stringPieces = metadataFileName.split("/");
String metadataName = stringPieces[stringPieces.length - 1];
InputStream is = Factory.get().getApplicationContext().getAssets().open("data/" + metadataName);
return is;
}
catch (IOException e)
{
// Handle somehow!
return null;
}
}
});
}
return mPhoneNumberUtil;
}

Rendering jp2(jpeg2000) to Imageview in android.

I am getting jp2 in base64 format from server end. I am able to convert jpg to jp2 form ImageMagick library and send to server. They are able to convert it to jpg using Buffered Image and ImageIo .
But I am not getting any idea to convert jp2 to jpg and render in Imageview.
Hoping for any help. Thanks in advance.
You probably solved it somehow already, but in case you're still looking for a solution, you can try the JP2 for Android library. (Disclaimer: I wrote the library.) It's based on OpenJPEG, like the DimaArts' response, but it has a bit nicer Java interface.
Add the following dependency to your build.gradle file:
implementation 'com.gemalto.jp2:jp2-android:1.0'
and use the following code to decode the JP2:
byte[] jp2Data = ...; //get the JP2 data from somewhere
Bitmap bmp = new JP2Decoder(jp2Data).decode();
imgView.setImageBitmap(bmp);
You can use OpenJpeg library for decode Jpeg2000. You can use compiled library https://github.com/DimaArts/OpenJpegAndroid. It contains an example of encode jpeg2000. Library supports PNG input and output formats for decoder and encoder.
Try this:
OpenJPEGJavaDecoder decoder = new OpenJPEGJavaDecoder();
String[] params2 = new String[4];
params2[0] = "-i";
params2[1] = mInputPath; // path to jp2
params2[2] = "-o";
params2[3] = mOutputPath // path to png
decoder.decodeJ2KtoImage(params2);
if you are using JNI:
public int decodeJ2KtoImage(String[] parameters) {
return internalDecodeJ2KtoImage(parameters);
}
Try this code from https://stackoverflow.com/a/39103107/2760681
private static void convertImage(int randNum) throws IOException {
try {
File foundFile = new File("c:\\images\\" + randNum + ".jp2");
BufferedImage background = ImageIO.read(foundFile);
ImageIO.write(background, "jpg", new File("c:\\images\\" + randNum + ".jpg"));
System.out.println("jpg file is generated");
} catch (Exception e) {
// TODO: handle exception
System.out.println("No file " + randNum +".jp2 found");
}
}

Could not initialize Tesseract API with language=eng

I am working on an Android app that requires OCR. I have decided to use Tesseract as API but I keep on getting this error:
E/Tesseract(native): Could not initialize Tesseract API with language=eng!
I have already copied file "eng.traineddata" to the location.
I am using Android Studio 2.1.2 (SDK 23)
Testing on device with API 22 Android Lollipop 5.1.1 (Read about Permission issue on Marshmallow)
Here is the code I am using:
public void reads(View view) {
TextView textView = (TextView) findViewById(R.id.textView);
int rotation = 0;
try {
ExifInterface exifInterface = new ExifInterface(mCurrentPhotoPath);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL);
switch (orientation){
case ExifInterface.ORIENTATION_ROTATE_90: rotation = 90; break;
case ExifInterface.ORIENTATION_ROTATE_180: rotation = 180; break;
case ExifInterface.ORIENTATION_ROTATE_270: rotation = 270; break;
}
} catch(Exception e) {
}
int w = imageBitmap.getWidth();
int h = imageBitmap.getHeight();
if (rotation != 0) {
Matrix matrix = new Matrix();
matrix.preRotate(rotation);
imageBitmap = Bitmap.createBitmap(imageBitmap,0,0,w,h,matrix,false);
} else {
imageBitmap = Bitmap.createBitmap(imageBitmap,0,0,w,h);
}
imageBitmap = imageBitmap.copy(Bitmap.Config.ARGB_8888,true);
TessBaseAPI ReadIt = new TessBaseAPI();
ReadIt.init("/storage/emulated/0/","eng");
ReadIt.setImage(imageBitmap);
String Text = ReadIt.getUTF8Text();
if (Text!=null) textView.setText(Text);
}
I have used this line in my build.gradle dependency:
compile 'com.rmtheis:tess-two:6.0.2'
also, I have copied the"eng.traineddata in the folder named tessdata directly by downloading in the particular stated directory.
Tesseract-two isn't using the newest version of the OCR engine, it uses 3.05, so we are forced to use data from here. It seems the new data uses a different model, neural networks. The previous models before 4.0 worked differently.
I have tried using the data from here
and here. These data sets are only compatible with the newest version of tesseract, 4.0 (source), so it won't work if you are using an older version of tesseract.
Are you using tess-two?. In your code:
TessBaseAPI ReadIt = new TessBaseAPI();
ReadIt.init("/storage/emulated/0/","eng");
"/storage/emulated/0/" path should be pointing to your data files. You must have a subdirectory
named "tessdata". See
https://github.com/rmtheis/tess-two/blob/d7a45fd2e08b7ec315cd1e29d1a7e0c72fb24a66/tess-two/src/com/googlecode/tesseract/android/TessBaseAPI.java#L176
Read more at:
Could not initialize Tesseract API with language=eng!
Release permissions of manifest in Activity:
In manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
In onCreate:
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
}
}
If you dont use Marshmallow and still have problem try clean and rebuild project.
I had this same issue and the problem was that Marshmallow specifically requires a new way for your app to get read/write permission to storage. This blog post solved my problem.
In my Main Activity I have the following:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
...
getStorageAccessPermissions(); // Request storage read/write permissions from the user
}
#TargetApi(23)
private void getStorageAccessPermissions() {
int hasWriteStoragePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasWriteStoragePermission != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_WRITE_EXTERNAL_PERMISSIONS);
}
}
Where REQUEST_CODE_WRITE_EXTERNAL_PERMISSIONS is an integer constant declared globally.
In a class that I have extending TessBaseAPI I added the following just for logging purposes to make sure that I actually can access the storage.
/* Checks if external storage is available to at least write to and returns the path name */
private static String isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
String retval = "External storage is not writable";
if (Environment.MEDIA_MOUNTED.equals(state)) {
retval = Environment.getExternalStorageDirectory().toString();
}
return retval;
}
/* Checks if external storage is available to at least read from and returns the path name */
private static String isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
String retval = "External storage is not readable";
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
retval = Environment.getExternalStorageDirectory().toString();
}
return retval;
}
use absolute path to tessdata directory from external storage (not assets)
for example if your models are in
/storage/emulated/0/Android/data/com.xxx.yyy/files/tessmodels/tessdata/
use this path
/storage/emulated/0/Android/data/com.xxx.yyy/files/tessmodels/
make sure you have write/read external storage permissions
use this model, tested with tess-two:9.0.0. I got it from tess-two sample app
Newer versions of tess-two check to make sure that the training data files can be found on the device. If those training data files are not found, a more informative message than the error message you're seeing will be shown.
So when you see this error message on newer versions of tess-two, it means that the training data files were found in the expected location, but they are the wrong version or are otherwise unreadable. Check to make sure you're using the right version of the training data files.

android image exif reader 3rd party api

Is there any 3rd part api for android to read exif tags from image which support api level starting from 1.5.
The metadata extraction library by Drew Noakes works well for extracting EXIF tags on earlier Android platform versions, with a slight modification. I am using it on Android 1.6 to extract tags from JPEG images.
NOTE: Newer versions of metadata-extractor work directly on Android without modification.
You will need to download and build the source code yourself, and package it with your app. (I'm using release 2.3.1.) Make the following changes to com.drew.imaging.jpeg.JpegMetadataReader:
Remove the following import statement:
import com.sun.image.codec.jpeg.JPEGDecodeParam;
Delete the following method (which you won't need on Android):
public static Metadata readMetadata(JPEGDecodeParam decodeParam) { ... }
Remove the com.drew.metadata.SampleUsage class, which references the method deleted above. Also remove all of the test packages.
That's all there is to it. Here's an example of using the JpegMetadataReader to extract a date-time tag from a JPEG image stored on the SD card:
import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifDirectory;
// other imports and class definition removed for brevity
public static Date extractExifDateTime(String imagePath)
{
Log.d("exif", "Attempting to extract EXIF date/time from image at " + imagePath);
Date datetime = new Date(0); // or initialize to null, if you prefer
try
{
Metadata metadata = JpegMetadataReader.readMetadata(new File(imagePath));
Directory exifDirectory = metadata.getDirectory(ExifDirectory.class);
// these are listed in order of preference
int[] datetimeTags = new int[] { ExifDirectory.TAG_DATETIME_ORIGINAL,
ExifDirectory.TAG_DATETIME,
ExifDirectory.TAG_DATETIME_DIGITIZED };
int datetimeTag = -1;
for (int tag : datetimeTags)
{
if (exifDirectory.containsTag(tag))
{
datetimeTag = tag;
break;
}
}
if (datetimeTag != -1)
{
Log.d("exif", "Using tag " + exifDirectory.getTagName(datetimeTag) + " for timestamp");
SimpleDateFormat exifDatetimeFormat = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
datetime = exifDatetimeFormat.parse(exifDirectory.getString(datetimeTag));
}
else
{
Log.d("exif", "No date/time tags were found");
}
}
catch (Exception e)
{
Log.w("exif", "Unable to extract EXIF metadata from image at " + imagePath, e);
}
return datetime;
}
For what it worth, did you try to use the native ExifInterface class ?
http://developer.android.com/reference/android/media/ExifInterface.html
Should be must faster than using a 3rd party library ;)

Categories

Resources