How to get optimized java code from kotlin source file? - android

I have converted below kotlin file from existing options
#Entity
data class DatabaseVideo constructor(
#PrimaryKey
val url: String,
val updated: String,
val title: String,
val description: String,
val thumbnail: String)
/**
* Map DatabaseVideos to domain entities
*/
fun List<DatabaseVideo>.asDomainModel(): List<DevByteVideo> {
return map {
DevByteVideo(
url = it.url,
title = it.title,
description = it.description,
updated = it.updated,
thumbnail = it.thumbnail)
}
}
The Java out put file is here as below
#Metadata(
mv = {1, 1, 18},
bv = {1, 0, 3},
k = 2,
d1 = {"\u0000\u0010\n\u0000\n\u0002\u0010 \n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0000\u001a\u0016\u0010\u0000\u001a\b\u0012\u0004\u0012\u00020\u00020\u0001*\b\u0012\u0004\u0012\u00020\u00030\u0001¨\u0006\u0004"},
d2 = {"asDomainModel", "", "Lcom/example/android/devbyteviewer/domain/DevByteVideo;", "Lcom/example/android/devbyteviewer/database/DatabaseVideo;", "app_debug"}
)
public final class DatabaseEntitiesKt {
#NotNull
public static final List asDomainModel(#NotNull List $this$asDomainModel) {
Intrinsics.checkParameterIsNotNull($this$asDomainModel, "$this$asDomainModel");
Iterable $this$map$iv = (Iterable)$this$asDomainModel;
int $i$f$map = false;
Collection destination$iv$iv = (Collection)(new ArrayList(CollectionsKt.collectionSizeOrDefault($this$map$iv, 10)));
int $i$f$mapTo = false;
Iterator var6 = $this$map$iv.iterator();
while(var6.hasNext()) {
Object item$iv$iv = var6.next();
DatabaseVideo it = (DatabaseVideo)item$iv$iv;
int var9 = false;
String var10002 = it.getUrl();
String var10003 = it.getTitle();
String var10004 = it.getDescription();
String var10005 = it.getUpdated();
String var10 = it.getThumbnail();
String var11 = var10005;
String var12 = var10004;
String var13 = var10003;
String var14 = var10002;
DevByteVideo var16 = new DevByteVideo(var13, var12, var14, var11, var10);
destination$iv$iv.add(var16);
}
return (List)destination$iv$iv;
}
}
// DatabaseVideo.java
package com.example.android.devbyteviewer.database;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
#Metadata(
mv = {1, 1, 18},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000\"\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0012\n\u0002\u0010\u000b\n\u0002\b\u0002\n\u0002\u0010\b\n\u0002\b\u0002\b\u0087\b\u0018\u00002\u00020\u0001B-\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0003\u0012\u0006\u0010\u0005\u001a\u00020\u0003\u0012\u0006\u0010\u0006\u001a\u00020\u0003\u0012\u0006\u0010\u0007\u001a\u00020\u0003¢\u0006\u0002\u0010\bJ\t\u0010\u000f\u001a\u00020\u0003HÆ\u0003J\t\u0010\u0010\u001a\u00020\u0003HÆ\u0003J\t\u0010\u0011\u001a\u00020\u0003HÆ\u0003J\t\u0010\u0012\u001a\u00020\u0003HÆ\u0003J\t\u0010\u0013\u001a\u00020\u0003HÆ\u0003J;\u0010\u0014\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u00032\b\b\u0002\u0010\u0004\u001a\u00020\u00032\b\b\u0002\u0010\u0005\u001a\u00020\u00032\b\b\u0002\u0010\u0006\u001a\u00020\u00032\b\b\u0002\u0010\u0007\u001a\u00020\u0003HÆ\u0001J\u0013\u0010\u0015\u001a\u00020\u00162\b\u0010\u0017\u001a\u0004\u0018\u00010\u0001HÖ\u0003J\t\u0010\u0018\u001a\u00020\u0019HÖ\u0001J\t\u0010\u001a\u001a\u00020\u0003HÖ\u0001R\u0011\u0010\u0006\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\t\u0010\nR\u0011\u0010\u0007\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\u000b\u0010\nR\u0011\u0010\u0005\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\f\u0010\nR\u0011\u0010\u0004\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\r\u0010\nR\u0016\u0010\u0002\u001a\u00020\u00038\u0006X\u0087\u0004¢\u0006\b\n\u0000\u001a\u0004\b\u000e\u0010\n¨\u0006\u001b"},
d2 = {"Lcom/example/android/devbyteviewer/database/DatabaseVideo;", "", "url", "", "updated", "title", "description", "thumbnail", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", "getDescription", "()Ljava/lang/String;", "getThumbnail", "getTitle", "getUpdated", "getUrl", "component1", "component2", "component3", "component4", "component5", "copy", "equals", "", "other", "hashCode", "", "toString", "app_debug"}
)
#Entity
public final class DatabaseVideo {
#PrimaryKey
#NotNull
private final String url;
#NotNull
private final String updated;
#NotNull
private final String title;
#NotNull
private final String description;
#NotNull
private final String thumbnail;
#NotNull
public final String getUrl() {
return this.url;
}
#NotNull
public final String getUpdated() {
return this.updated;
}
#NotNull
public final String getTitle() {
return this.title;
}
#NotNull
public final String getDescription() {
return this.description;
}
#NotNull
public final String getThumbnail() {
return this.thumbnail;
}
public DatabaseVideo(#NotNull String url, #NotNull String updated, #NotNull String title, #NotNull String description, #NotNull String thumbnail) {
Intrinsics.checkParameterIsNotNull(url, "url");
Intrinsics.checkParameterIsNotNull(updated, "updated");
Intrinsics.checkParameterIsNotNull(title, "title");
Intrinsics.checkParameterIsNotNull(description, "description");
Intrinsics.checkParameterIsNotNull(thumbnail, "thumbnail");
super();
this.url = url;
this.updated = updated;
this.title = title;
this.description = description;
this.thumbnail = thumbnail;
}
#NotNull
public final String component1() {
return this.url;
}
#NotNull
public final String component2() {
return this.updated;
}
#NotNull
public final String component3() {
return this.title;
}
#NotNull
public final String component4() {
return this.description;
}
#NotNull
public final String component5() {
return this.thumbnail;
}
#NotNull
public final DatabaseVideo copy(#NotNull String url, #NotNull String updated, #NotNull String title, #NotNull String description, #NotNull String thumbnail) {
Intrinsics.checkParameterIsNotNull(url, "url");
Intrinsics.checkParameterIsNotNull(updated, "updated");
Intrinsics.checkParameterIsNotNull(title, "title");
Intrinsics.checkParameterIsNotNull(description, "description");
Intrinsics.checkParameterIsNotNull(thumbnail, "thumbnail");
return new DatabaseVideo(url, updated, title, description, thumbnail);
}
// $FF: synthetic method
public static DatabaseVideo copy$default(DatabaseVideo var0, String var1, String var2, String var3, String var4, String var5, int var6, Object var7) {
if ((var6 & 1) != 0) {
var1 = var0.url;
}
if ((var6 & 2) != 0) {
var2 = var0.updated;
}
if ((var6 & 4) != 0) {
var3 = var0.title;
}
if ((var6 & 8) != 0) {
var4 = var0.description;
}
if ((var6 & 16) != 0) {
var5 = var0.thumbnail;
}
return var0.copy(var1, var2, var3, var4, var5);
}
#NotNull
public String toString() {
return "DatabaseVideo(url=" + this.url + ", updated=" + this.updated + ", title=" + this.title + ", description=" + this.description + ", thumbnail=" + this.thumbnail + ")";
}
public int hashCode() {
String var10000 = this.url;
int var1 = (var10000 != null ? var10000.hashCode() : 0) * 31;
String var10001 = this.updated;
var1 = (var1 + (var10001 != null ? var10001.hashCode() : 0)) * 31;
var10001 = this.title;
var1 = (var1 + (var10001 != null ? var10001.hashCode() : 0)) * 31;
var10001 = this.description;
var1 = (var1 + (var10001 != null ? var10001.hashCode() : 0)) * 31;
var10001 = this.thumbnail;
return var1 + (var10001 != null ? var10001.hashCode() : 0);
}
public boolean equals(#Nullable Object var1) {
if (this != var1) {
if (var1 instanceof DatabaseVideo) {
DatabaseVideo var2 = (DatabaseVideo)var1;
if (Intrinsics.areEqual(this.url, var2.url) && Intrinsics.areEqual(this.updated, var2.updated) && Intrinsics.areEqual(this.title, var2.title) && Intrinsics.areEqual(this.description, var2.description) && Intrinsics.areEqual(this.thumbnail, var2.thumbnail)) {
return true;
}
}
return false;
} else {
return true;
}
}
}
It is seems to be buggy. very difficult to understand.is there any options to get pure java code ? please let me know if we can able to perform conversion other than android studio

You have to realise that kotlin runs on JVM, hence it can do everything that Java can and nothing more. The extra features that Kotlin provides such as not null types etc are implemented using same byte code that java uses.
All the extra java code that you call "buggy", is there for some specific feature requirement of kotlin.
For example all the Intrinsics.checkParameterIsNotNull checks are there on variables that are declared non nullable, that is how kotlin makes sure that nulls are not introduced in such variables.
So the java output you see doesn't contain any extra code, its the actual java equivalent code of your kotlin class.

Related

Android Realm Query

I love Realm, the ease of use is so good, but sometimes i struggle in finding a way of doing a specific query.
Supposing i would want to query a a table(RealmObject) and get all the results matching a column name (variable), and i want that to be unique for each id, and also the latest record for a given variable name. For instance:
realm.where(RealmMessages.thisClass)
.distinctAsync(RealmMessages.FROM_TABLE)
.addChangeListener(listener)
This will get me all the messages filtered by each unique 'from' field. But this won't work, as i want the latest by 'date' and unique by 'from'.
How would i approach to do this with realm»? Without manually querying all the objects and tho defeating the purpose of 'lazy objects' ?
You can Sort your results from the Realm using the
"realmQuery.findAll(... Sort[] ... Fields[] ...)" method. Also you can
do a multi-query by use groups and "or".
You can also use the "distinct()" method to get the "id" repeated only 1 time
I don't know if this is useful for you, but I did a class and some methods that let me do "fast & automatic queries on Realm".
These are the files:
Put this in the same package of your "Realm Utils Class" (like a "RealmHelper" in which you instantiate your "Realm" instance and where you have all your methods which queries the realm ecc...
public class RealmQueriesData<T> {
private List<QueryData> mQueries;
private QueryFind mFind;
private Class<T> mResultsClass;
/* START Factory Methods */
public static <T> RealmQueriesData<T> newInstanceFindEqualsTo(Class<T> resultsClass, String fieldName, Object value, Case mCase){
return new RealmQueriesData<>(
resultsClass,
QueryData.QUERY_EQUAL, fieldName, value, QueryFind.FIND_ALL, mCase
);
}
public static <T> RealmQueriesData<T> newInstanceCountEqualsTo(Class<T> resultsClass, String fieldName, Object value, Case mCase){
return new RealmQueriesData<>(
resultsClass,
new int[]{QueryData.QUERY_EQUAL, QueryData.QUERY_COUNT}, new String[]{fieldName, null},
new Object[]{value, null}, new Case[]{mCase, null}
);
}
public static <T> RealmQueriesData<T> newInstanceFindNotIn(Class<T> resultsClass, String fieldName, Object[] valuesIn){
return new RealmQueriesData<>(
resultsClass,
QueryData.QUERY_NOT_EQUAL, fieldName, valuesIn, QueryFind.FIND_ALL
);
}
/* END Factory Methods */
/* START Constructor Methods */
public RealmQueriesData(Class<T> resultsClass,
int[] queryTypes, String[] fieldNames, Object[] queryValues, Case[] mCases){
this.mResultsClass = resultsClass;
this.mQueries = new ArrayList<>();
for(int i = 0; i < queryTypes.length; i++){
int type = queryTypes[i];
String field = fieldNames[i];
Object value = queryValues[i];
Case mCase = mCases[i];
this.mQueries.add(
new QueryData(type, field, value, mCase)
);
}
}
public RealmQueriesData(Class<T> resultsClass, int queryType, String fieldName, Object[] queryValuesIn, int findType){
this.mResultsClass = resultsClass;
this.mQueries = new ArrayList<>();
this.mQueries.add(
new QueryData(queryType, fieldName, queryValuesIn)
);
this.mFind = new QueryFind(findType);
}
public RealmQueriesData(Class<T> resultsClass, int queryType, String fieldName, Object queryValue, int findType, Case mCase){
this.mResultsClass = resultsClass;
this.mQueries = new ArrayList<>();
this.mQueries.add(
new QueryData(queryType, fieldName, queryValue, mCase)
);
this.mFind = new QueryFind(findType);
}
public RealmQueriesData(Class<T> resultsClass){
this.mResultsClass = resultsClass;
this.mFind = new QueryFind();
}
/* END Constructor Methods */
/* START Getter & Setter Methods */
public List<QueryData> getQueries() {
return mQueries;
}
public void setQueries(List<QueryData> queries) {
this.mQueries = queries;
}
public QueryFind getFind() {
return mFind;
}
public void setFind(QueryFind find) {
this.mFind = find;
}
public Class<T> getResultsClass(){
return mResultsClass;
}
public void setResultsClass(Class<T> resultClass){
this.mResultsClass = resultClass;
}
/* END Getter & Setter Methods */
/* START Utils Methods */
public void addQuery(QueryData q){
mQueries.add(q);
}
public void addQuery(int type, String fieldName, Object value, Case mCase){
mQueries.add(new QueryData(type, fieldName, value, mCase));
}
public void addQuery(int type, String fieldName, Object value){
mQueries.add(new QueryData(type, fieldName, value));
}
public void addQuery(int type, String fieldName, Object value, Object valueTo){
mQueries.add(new QueryData(type, fieldName, value, valueTo));
}
public void addQuery(int type, String fieldName, Object[] valueIn){
mQueries.add(new QueryData(type, fieldName, valueIn));
}
public void addQuery(int type, String fieldName){
mQueries.add(new QueryData(type, fieldName));
}
/* END Utils Methods */
#Override
public String toString() {
return "RealmQueriesData{" +
"mQueries=" + mQueries.toString() +
", mFind=" + mFind.toString() +
", mResultsClass=" + mResultsClass.toString() +
'}';
}
}
class QueryData {
// QueryData Tipes
public static final int QUERY_NEGATION = 0x0;
public static final int QUERY_OR = 0x1;
public static final int QUERY_BEGIN_GROUP = 0x2;
public static final int QUERY_END_GROUP = 0x3;
public static final int QUERY_AVERAGE = 0x4;
public static final int QUERY_COUNT = 0x5;
public static final int QUERY_DISTINCT = 0x6;
public static final int QUERY_MAX = 0x7;
public static final int QUERY_MAX_DATE = 0x8;
public static final int QUERY_MIN = 0x9;
public static final int QUERY_MIN_DATE = 0xA;
public static final int QUERY_SUM = 0xB;
public static final int QUERY_EQUAL = 0xC;
public static final int QUERY_NOT_EQUAL = 0xD;
public static final int QUERY_CONTAINS = 0xE;
public static final int QUERY_IS_NULL = 0xF;
public static final int QUERY_NOT_NULL = 0x10;
public static final int QUERY_LESS = 0x11;
public static final int QUERY_GREATER = 0x12;
public static final int QUERY_GREATER_EQUAL = 0x13;
public static final int QUERY_LESS_EQUAL = 0x14;
public static final int QUERY_BETWEEN = 0x15;
public static final int QUERY_LIKE = 0x16;
public static final int QUERY_BEGINS = 0x17;
public static final int QUERY_ENDS = 0x18;
public static final int QUERY_IN = 0x19;
public static final int QUERY_IS_EMPTY = 0x1A;
public static final int QUERY_NOT_EMPTY = 0x1B;
int mType;
String mFieldName;
Object mValue;
Object mValueTo;
Object[] mValueIn;
Case mCase;
/* START Constructor Methods */
public QueryData(int type, String fieldName, Object value, Case mCase){
this.mType = type;
this.mFieldName = fieldName;
this.mValue = value;
this.mCase = mCase;
}
public QueryData(int type, String fieldName, Object value){
this.mType = type;
this.mFieldName = fieldName;
this.mValue = value;
}
public QueryData(int type, String fieldName, Object valueFrom, Object valueTo){
this.mType = type;
this.mFieldName = fieldName;
this.mValue = valueFrom;
this.mValueTo = valueTo;
}
public QueryData(int type, String fieldName, Object[] valueIn){
this.mType = type;
this.mFieldName = fieldName;
this.mValueIn = valueIn;
}
public QueryData(int type, String fieldName){
this.mType = type;
this.mFieldName = fieldName;
}
/* END Constructor Methods */
/* START Getter & Setter Methods */
public int getType() {
return mType;
}
public void setType(int type) {
this.mType = type;
}
public String getFieldName() {
return mFieldName;
}
public void setFieldName(String fieldName) {
this.mFieldName = fieldName;
}
public Object getValue(){
return mValue;
}
public void setValue(Object value){
this.mValue = value;
}
public Object getValueTo() {
return mValueTo;
}
public void setValueTo(Object valueTo) {
this.mValueTo = valueTo;
}
public Object[] getValueIn() {
return mValueIn;
}
public void setValueIn(Object[] valueIn) {
this.mValueIn = valueIn;
}
public Case getCase() {
return mCase;
}
public void setCase(Case mCase) {
this.mCase = mCase;
}
/* END Getter & Setter Methods */
#Override
public String toString() {
return "QueryData{" +
"mType=" + mType +
", mFieldName='" + mFieldName + '\'' +
", mValue=" + mValue +
", mValueTo=" + mValueTo +
", mValueIn=" + Arrays.toString(mValueIn) +
", mCase=" + mCase +
'}';
}
}
class QueryFind {
// QueryFind Types
public static final int FIND_ALL = 0x1;
public static final int FIND_ALL_SORTED_FIELD = 0x2;
public static final int FIND_ALL_SORTED_FIELD_SORT = 0x3;
public static final int FIND_ALL_SORTED_ARRAYS = 0x4;
int mType;
List<String> mSortFields;
List<Sort> mSorts;
boolean mRetAll;
/* START Constructor Methods */
public QueryFind(int type, List<String> sortFields, List<Sort> sorts, boolean retAll){
this.mType = type;
this.mSortFields = sortFields != null ? sortFields : new ArrayList<String>();
this.mSorts = sorts != null ? sorts : new ArrayList<Sort>();
this.mRetAll = retAll;
}
public QueryFind(int type, String sortField, Sort sort, boolean retAll){
this.mType = type;
this.mSortFields = new ArrayList<>();
this.mSortFields.add(sortField);
this.mSorts = new ArrayList<>();
this.mSorts.add(sort);
this.mRetAll = retAll;
}
public QueryFind(int type){
this.mType = type;
}
public QueryFind(){
this.mRetAll = true;
}
/* END Constructor Methods */
/* START Getter & Setter Methods */
public int getType() {
return mType;
}
public void setType(int type) {
this.mType = type;
}
public List<String> getSortFields() {
return mSortFields;
}
public void setSortFields(List<String> sortFields) {
this.mSortFields = sortFields;
}
public List<Sort> getSorts() {
return mSorts;
}
public void setSorts(List<Sort> sorts) {
this.mSorts = sorts;
}
public boolean getRetAll() {
return mRetAll;
}
public void setRetAll(boolean retAll) {
this.mRetAll = retAll;
}
/* END Getter & Setter Methods */
/* START Utils Methods */
public void addSort(String sortField, Sort sort){
mSortFields.add(sortField);
mSorts.add(sort);
}
/* END Utils Methods */
#Override
public String toString() {
return "QueryFind{" +
"mType=" + mType +
", mSortFields=" + mSortFields +
", mSorts=" + mSorts +
", mRetAll=" + mRetAll +
'}';
}
}
Then in you "Realm Library File" (like "RealmHelper") add these methods to do the queries by passing them a "RealmQueriesData" instance:
public class RealmHelper {
protected Realm mRealm;
// Instance to have only 1 Realm open 4 every thread in your app
protected static RealmHelper mInstance;
[....]
/* START Realm Query Methods */
// Like the one below but return a List of objects and not a RealmResults
public <T> List<T> doQueryOnRealmAsList(RealmQueriesData filters){
return (List<T>) toList(doQueryOnRealm(filters));
}
// With this you can do every type of query which return values with
// "realmQuery.findAll()" methods
public <T> RealmResults<T> doQueryOnRealm(RealmQueriesData filters){
RealmResults<T> ret = null;
if(filters != null){
List<QueryData> queries = filters.getQueries();
QueryFind find = filters.getFind();
if(queries != null && queries.size() > 0) {
RealmQuery<T> realmQuery = mRealm.where(filters.getResultsClass());
for(QueryData query : queries){
if(query.getType() == QueryData.QUERY_DISTINCT){
ret = realmQuery.distinct(query.getFieldName());
} else {
realmQuery = getRealmQueryFromQueryData(realmQuery, query);
}
}
if(find != null) {
ret = getRealmQueryResults(realmQuery, find);
}
} else {
if(find != null && find.getRetAll()){
ret = (RealmResults<T>) findAllObject(filters.getResultsClass());
}
}
}
return ret;
}
// With this you can do every type of query which return a single value
// with "realmQuery.findFirst()" method.
public <T> T doQueryOnRealmSingleResult(RealmQueriesData filters){
T ret = null;
if(filters != null){
List<QueryData> queries = filters.getQueries();
QueryFind find = filters.getFind();
if(queries != null && queries.size() > 0){
RealmQuery<T> realmQuery = mRealm.where(filters.getResultsClass());
for(QueryData query : queries){
realmQuery = getRealmQueryFromQueryData(realmQuery, query);
}
ret = realmQuery.findFirst();
}
}
return ret;
}
// For queries whose return a Numerical value using SQL built-in functions
// like "max, count, min, average ..."
public Object doMathQueryOnRealm(RealmQueriesData filters){
Object ret = null;
if(filters != null){
List<QueryData> queries = filters.getQueries();
QueryData last = queries.get(queries.size() - 1);
queries.remove(last);
if(queries.size() > 0){
RealmQuery realmQuery = mRealm.where(filters.getResultsClass());
for(QueryData query : queries){
realmQuery = getRealmQueryFromQueryData(realmQuery, query);
}
ret = getMathQueryResult(realmQuery, last);
}
}
return ret;
}
private <T> RealmQuery<T> getRealmQueryFromQueryData(RealmQuery realmQuery, QueryData query){
String field; Object value; Case mCase;
switch(query.getType()){
case QueryData.QUERY_NEGATION:
realmQuery.not();
break;
case QueryData.QUERY_OR:
realmQuery.or();
break;
case QueryData.QUERY_BEGIN_GROUP:
realmQuery.beginGroup();
break;
case QueryData.QUERY_END_GROUP:
realmQuery.endGroup();
break;
case QueryData.QUERY_EQUAL:
field = query.getFieldName();
value = query.getValue();
if(value instanceof String){
mCase = query.getCase();
realmQuery.equalTo(field, value.toString(), mCase);
} else if(value instanceof Integer){
realmQuery.equalTo(field, (Integer) value);
} else if(value instanceof Double){
realmQuery.equalTo(field, (Double) value);
} else if(value instanceof Date){
realmQuery.equalTo(field, (Date) value);
}
break;
case QueryData.QUERY_NOT_EQUAL:
field = query.getFieldName();
value = query.getValue();
if(value instanceof String){
mCase = query.getCase();
realmQuery.notEqualTo(field, value.toString(), mCase);
} else if(value instanceof Integer){
realmQuery.notEqualTo(field, (Integer) value);
} else if(value instanceof Double){
realmQuery.notEqualTo(field, (Double) value);
} else if(value instanceof Date){
realmQuery.notEqualTo(field, (Date) value);
}
break;
case QueryData.QUERY_CONTAINS:
field = query.getFieldName();
value = query.getValue();
mCase = query.getCase();
if(mCase != null){
realmQuery.contains(field, value.toString(), mCase);
} else {
realmQuery.contains(field, value.toString());
}
break;
case QueryData.QUERY_IS_NULL:
realmQuery.isNull(query.getFieldName());
break;
case QueryData.QUERY_NOT_NULL:
realmQuery.isNotNull(query.getFieldName());
break;
case QueryData.QUERY_LESS:
field = query.getFieldName();
value = query.getValue();
if(value instanceof Integer){
realmQuery.lessThan(field, (Integer) value);
} else if(value instanceof Double){
realmQuery.lessThan(field, (Double) value);
} else if(value instanceof Date){
realmQuery.lessThan(field, (Date) value);
}
break;
case QueryData.QUERY_GREATER:
field = query.getFieldName();
value = query.getValue();
if(value instanceof Integer){
realmQuery.greaterThan(field, (Integer) value);
} else if(value instanceof Double){
realmQuery.greaterThan(field, (Double) value);
} else if(value instanceof Date){
realmQuery.greaterThan(field, (Date) value);
}
break;
case QueryData.QUERY_GREATER_EQUAL:
field = query.getFieldName();
value = query.getValue();
if(value instanceof Integer){
realmQuery.greaterThanOrEqualTo(field, (Integer) value);
} else if(value instanceof Double){
realmQuery.greaterThanOrEqualTo(field, (Double) value);
} else if(value instanceof Date){
realmQuery.greaterThanOrEqualTo(field, (Date) value);
}
break;
case QueryData.QUERY_LESS_EQUAL:
field = query.getFieldName();
value = query.getValue();
if(value instanceof Integer){
realmQuery.lessThanOrEqualTo(field, (Integer) value);
} else if(value instanceof Double){
realmQuery.lessThanOrEqualTo(field, (Double) value);
} else if(value instanceof Date){
realmQuery.lessThanOrEqualTo(field, (Date) value);
}
break;
case QueryData.QUERY_BETWEEN:
field = query.getFieldName();
value = query.getValue();
if(value instanceof Integer){
realmQuery.between(field, (Integer) value, (Integer) query.getValueTo());
} else if(value instanceof Double){
realmQuery.between(field, (Double) value, (Double) query.getValueTo());
} else if(value instanceof Date){
realmQuery.between(field, (Date) value, (Date) query.getValueTo());
}
break;
case QueryData.QUERY_LIKE:
field = query.getFieldName();
value = query.getValue();
mCase = query.getCase();
if(mCase != null){
realmQuery.like(field, value.toString(), mCase);
} else {
realmQuery.like(field, value.toString());
}
break;
case QueryData.QUERY_BEGINS:
field = query.getFieldName();
value = query.getValue();
mCase = query.getCase();
if(mCase != null){
realmQuery.beginsWith(field, value.toString(), mCase);
} else {
realmQuery.beginsWith(field, value.toString());
}
break;
case QueryData.QUERY_ENDS:
field = query.getFieldName();
value = query.getValue();
mCase = query.getCase();
if(mCase != null){
realmQuery.endsWith(field, value.toString(), mCase);
} else {
realmQuery.endsWith(field, value.toString());
}
break;
case QueryData.QUERY_IN:
field = query.getFieldName();
Object[] values = query.getValueIn();
if(values instanceof String[]){
realmQuery.in(field, (String[]) values);
} else if(values instanceof Integer[]){
realmQuery.in(field, (Integer[]) values);
} else if(values instanceof Double[]){
realmQuery.in(field, (Double[]) values);
} else if(values instanceof Date[]){
realmQuery.in(field, (Date[]) values);
}
break;
case QueryData.QUERY_IS_EMPTY:
realmQuery.isEmpty(query.getFieldName());
break;
case QueryData.QUERY_NOT_EMPTY:
realmQuery.isNotEmpty(query.getFieldName());
break;
}
return realmQuery;
}
private Object getMathQueryResult(RealmQuery realmQuery, QueryData query){
Object ret = null;
switch(query.getType()){
case QueryData.QUERY_AVERAGE:
ret = realmQuery.average(query.getFieldName());
break;
case QueryData.QUERY_COUNT:
ret = realmQuery.count();
break;
case QueryData.QUERY_MAX:
ret = realmQuery.max(query.getFieldName());
break;
case QueryData.QUERY_MAX_DATE:
ret = realmQuery.maximumDate(query.getFieldName());
break;
case QueryData.QUERY_MIN:
ret = realmQuery.min(query.getFieldName());
break;
case QueryData.QUERY_MIN_DATE:
ret = realmQuery.minimumDate(query.getFieldName());
break;
case QueryData.QUERY_SUM:
ret = realmQuery.sum(query.getFieldName());
break;
}
return ret;
}
private <T> RealmResults<T> getRealmQueryResults(RealmQuery<T> realmQuery, QueryFind find){
RealmResults<T> ret = null;
switch(find.getType()){
case QueryFind.FIND_ALL:
ret = realmQuery.findAll();
break;
case QueryFind.FIND_ALL_SORTED_FIELD:
ret = realmQuery.findAllSorted(find.getSortFields().get(0));
break;
case QueryFind.FIND_ALL_SORTED_FIELD_SORT:
ret = realmQuery.findAllSorted(find.getSortFields().get(0), find.getSorts().get(0));
break;
case QueryFind.FIND_ALL_SORTED_ARRAYS:
ret = realmQuery.findAllSorted(find.getSortFields().toArray(new String[]{}), find.getSorts().toArray(new Sort[]{}));
break;
}
return ret;
}
/* END Realm Query Methods */
}
Normally to do a query I create a new "static Factory Method" in the "RealmQueriesData" class so I can do fast queries on realm just by invoking 1 method.
// GET all RealmObjects in your Realm by searching for all
// realm objects saved that have a specific value for a specific.
// Remember that the "field name" must be the "field attribute name" in the class
// and not the "SerializedName" label value!
// (As you can see in the method which do the query the "Case SENSITIVE / INSENSITIVE"
// is used only if you query a field which is a String type, if you are querying
// another type, like Integer/Double/Date, you can set the "CASE" to "null".
RealmResults<YourRealmObject> listCount = doQueryOnRealm(
RealmQueriesData.newInstanceFindEqualsTo(
YourRealmObject.class, "yourRealmObject Field Name", <field value of YourRealmObject>, <Case (SENSITIVE / INSENSITIVE)>
)
);
// Get a list of all RealmObjects whose have a specific value in a specific field
RealmResults<YourRealmObject> listObjs = doQueryOnRealm(
RealmQueriesData.newInstanceFindEqualsTo(
YourRealmObject.class, "Field Name of YourRealmObject", <Value of YourRealmObject field>, <Case (SENSITIVE / INSENSITIVE)>
)
);
// Like a COUNT query which look for all records that have a specific value
// in a specific column.
long count = (Long) doMathQueryOnRealm(
RealmQueriesData.newInstanceCountEqualsTo(
YourRealmObject.class, "Field Name of YourRealmObject", <Value of YourRealmObject field>, <Case (SENSITIVE / INSENSITIVE)>
)
);
I had to do different methods to query the realm because the realm queries can return different values, so I had to do 3 methods for every kind of return value:
multi-values return ( RealmResults / List ) (findAll method)
single-value return ( T ) (findFirst method)
numerical-value return ( Object ) ( max, min, count, ... queries)
I hope this is Helpful for you.
Bye!
(z3r0)

java.lang.ClassCastException: java.util.HashMap cannot be cast to Ride

DatabaseReference ridesRef = database.getReference("rides");
ridesRef.equalTo(from).orderByChild("from").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i(TAG, "dataSnapshot.getChildrenCount(): " + dataSnapshot.getChildrenCount());
if (dataSnapshot.getChildrenCount() > 0) {
ArrayList<Ride> value = (ArrayList<Ride>) dataSnapshot.getValue();
Log.i(TAG, value.toString());
for (Ride r : value) { // error occurs here
Log.i(TAG, "r.getTime:" + r.getTime());
Log.i(TAG, "getFrom:" + r.getFrom());
}
}
}
});
Log output is:
09-02 18:08:25.070 23651-23651 I/RidesFragment:
dataSnapshot.getChildrenCount(): 1
09-02 18:08:25.070 23651-23651 I/RidesFragment: [{to=Hackerscher
Markt, userID=0, time=1472831718565, regularly=false, price=0,
chosenUserID=0, active=true, places=1, from=Hauptbahnhof Berlin,
meetingPointDescription=blaues ei}]
public class Ride {
private String from;
private String to;
private long time;
private int places;
private String meetingPointDescription;
private boolean regularly;
private boolean active;
private float price;
private int userID;
private int chosenUserID;
public Ride() {
// Default constructor required for calls to DataSnapshot.getValue(Ride.class)
}
public Ride(String from, String to, long time, int places, String meetingPointDescription, boolean regularly,
boolean active, float price, int userID, int chosenUserID) {
this.from = from;
this.to = to;
this.time = time;
this.places = places;
this.meetingPointDescription = meetingPointDescription;
this.regularly = regularly;
this.active = active;
this.price = price;
this.userID = userID;
this.chosenUserID = chosenUserID;
}
// automatically generated getters and setters...
}
Third time I got an answer to my own question :/
ArrayList<Ride> value = (ArrayList<Ride>) dataSnapshot.getValue();
has to be replaced by
GenericTypeIndicator<ArrayList<Ride>> t = new GenericTypeIndicator<ArrayList<Ride>>() {};
ArrayList<Ride> value = dataSnapshot.getValue(t);
and everything works as expected.

android, Comparator sort wrong

I have a Comparator to sort by 3 values:
ORDER_BY_Points
ORDER_BY_Gdif // goals difference
ORDER_BY_Goals
First I get a array from a json string. I send the array to StandingsSort.ORDER_BY_RULES
Arrays.sort(addressArray, StandingsSort.ORDER_BY_RULES);
Here is my code:
static final Comparator<Standings> ORDER_BY_Points = new Comparator<Standings>() {
public int compare(Standings a1, Standings a2) {
return a1.points.compareTo(a2.points);
}
};
static final Comparator<Standings> ORDER_BY_Gdif = new Comparator<Standings>() {
public int compare(Standings a1, Standings a2) {
return a1.Gdif.compareTo(a2.Gdif);
}
};
static final Comparator<Standings> ORDER_BY_Goals = new Comparator<Standings>() {
public int compare(Standings a1, Standings a2) {
return a1.goalsP.compareTo(a2.goalsP);
}
};
static final Comparator<Standings> ORDER_BY_RULES = new Comparator<Standings>() {
public int compare(Standings a1, Standings a2) {
int i = ORDER_BY_Points.compare(a1,a2);
if(i == 0){
i = ORDER_BY_Gdif.compare(a1,a2);
if(i == 0){
i = ORDER_BY_Goals.compare(a1,a2);
}
}
return i;
}
};
class Standings {
String teamName;
String goalsP;
String goalsM;
String Gdif;
String points;
#Override
public String toString() {
return "" + teamName + "," + goalsP + ":" + goalsM + "," + Gdif + "," + points + "";
}
public Standings(String teamName, String goalsP,
String goalsM, String Gdif, String points) {
super();
this.teamName = teamName;
this.goalsP = goalsP;
this.goalsM = goalsM;
this.Gdif = Gdif;
this.points = points;
}
}
But the result is not OK! Here is the result
Name, Goals, GDif, Points
Team,11:9,2,10
Team,5:3,2,10
Team,9:2,7,11
Team,0:6,-6,2
Team,3:9,-6,2
Team,6:9,-3,3
Team,8:13,-5,3
Team,8:9,-1,5
Team,8:11,-3,5
Team,8:7,1,5
Why does the Comparator sort wrong?
Since you store the points as Strings, "10" comes before "2", "3", and "5". If you want to compare these in order by the numerical value, you need to convert them into ints first.
Similarly, Gdif and Goals are compared as Strings which is probably not what you want.

Error while converting text to QR code

I am trying to create a text to QR code converter.
I used the core2.2.jar from http://code.google.com/p/zxing/downloads/list and the code as told in Integrating the ZXing library directly into my Android application.
My Main.Activity is as shown below
package com.example.qr_androidone;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.view.Menu;
import android.widget.ImageView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
//super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
ImageView imageView = (ImageView) findViewById(R.id.qrCode);
String qrData = "Data I want to encode in QR code";
int qrCodeDimention = 500;
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrData, null,
Contents.Type.TEXT, BarcodeFormat.QR_CODE.toString(), qrCodeDimention);
try {
Bitmap bitmap = qrCodeEncoder.encodeAsBitmap();
imageView.setImageBitmap(bitmap);
} catch (WriterException e) {
e.printStackTrace();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
I used the "Contents.java" and "QRCodeEncoder.java" as shown in link Integrating the ZXing library directly into my Android application. I changed "activity_main.xml" also , as shown in above link
There are no errors in compiling, but there is error when the app runs
Could not find class 'com.google.zxing.EncodeHintType', referenced
from method com.example.qr_androidone.QRCodeEncoder.encodeAsBitmap
Could not find class 'com.google.zxing.MultiFormatWriter', referenced
from method com.example.qr_androidone.QRCodeEncoder.encodeAsBitmap
java.lang.NoClassDefFoundError: com.google.zxing.BarcodeFormat
Please help me solve the error
Download de JAR file, go to your Build Path and Import it from External JARs.
http://repo1.maven.org/maven2/com/google/zxing/core/2.2/
Then import it in your project.
you need the class of QRCodeEncoder.java..
public class QRCodeEncoder {
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
// private int dimension = Integer.MAX_VALUE;
private String contents = null;
private String displayContents = null;
private String title = null;
private BarcodeFormat format = null;
private boolean encoded = false;
public QRCodeEncoder(String data, Bundle bundle, String type, String format) {
// this.dimension = dimension;
encoded = encodeContents(data, bundle, type, format);
}
public String getContents() {
return contents;
}
public String getDisplayContents() {
return displayContents;
}
public String getTitle() {
return title;
}
private boolean encodeContents(String data, Bundle bundle, String type, String formatString) {
// Default to QR_CODE if no format given.
format = null;
if (formatString != null) {
try {
format = BarcodeFormat.valueOf(formatString);
} catch (IllegalArgumentException iae) {
// Ignore it then
}
}
if (format == null || format == BarcodeFormat.QR_CODE) {
this.format = BarcodeFormat.QR_CODE;
encodeQRCodeContents(data, bundle, type);
} else if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
return contents != null && contents.length() > 0;
}
private void encodeQRCodeContents(String data, Bundle bundle, String type) {
if (type.equals(Contents.Type.TEXT)) {
if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
} else if (type.equals(Contents.Type.EMAIL)) {
data = trim(data);
if (data != null) {
contents = "mailto:" + data;
displayContents = data;
title = "E-Mail";
}
} else if (type.equals(Contents.Type.PHONE)) {
data = trim(data);
if (data != null) {
contents = "tel:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "Phone";
}
} else if (type.equals(Contents.Type.SMS)) {
data = trim(data);
if (data != null) {
contents = "sms:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "SMS";
}
} else if (type.equals(Contents.Type.CONTACT)) {
if (bundle != null) {
StringBuilder newContents = new StringBuilder(100);
StringBuilder newDisplayContents = new StringBuilder(100);
newContents.append("MECARD:");
String name = trim(bundle.getString(ContactsContract.Intents.Insert.NAME));
if (name != null) {
newContents.append("N:").append(escapeMECARD(name)).append(';');
newDisplayContents.append(name);
}
String address = trim(bundle.getString(ContactsContract.Intents.Insert.POSTAL));
if (address != null) {
newContents.append("ADR:").append(escapeMECARD(address)).append(';');
newDisplayContents.append('\n').append(address);
}
Collection<String> uniquePhones = new HashSet<String>(Contents.PHONE_KEYS.length);
for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
String phone = trim(bundle.getString(Contents.PHONE_KEYS[x]));
if (phone != null) {
uniquePhones.add(phone);
}
}
for (String phone : uniquePhones) {
newContents.append("TEL:").append(escapeMECARD(phone)).append(';');
newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
}
Collection<String> uniqueEmails = new HashSet<String>(Contents.EMAIL_KEYS.length);
for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
String email = trim(bundle.getString(Contents.EMAIL_KEYS[x]));
if (email != null) {
uniqueEmails.add(email);
}
}
for (String email : uniqueEmails) {
newContents.append("EMAIL:").append(escapeMECARD(email)).append(';');
newDisplayContents.append('\n').append(email);
}
String url = trim(bundle.getString(Contents.URL_KEY));
if (url != null) {
// escapeMECARD(url) -> wrong escape e.g. http\://zxing.google.com
newContents.append("URL:").append(url).append(';');
newDisplayContents.append('\n').append(url);
}
String note = trim(bundle.getString(Contents.NOTE_KEY));
if (note != null) {
newContents.append("NOTE:").append(escapeMECARD(note)).append(';');
newDisplayContents.append('\n').append(note);
}
// Make sure we've encoded at least one field.
if (newDisplayContents.length() > 0) {
newContents.append(';');
contents = newContents.toString();
displayContents = newDisplayContents.toString();
title = "Contact";
} else {
contents = null;
displayContents = null;
}
}
} else if (type.equals(Contents.Type.LOCATION)) {
if (bundle != null) {
float latitude = bundle.getFloat("LAT", Float.MAX_VALUE);
float longitude = bundle.getFloat("LONG", Float.MAX_VALUE);
if (latitude != Float.MAX_VALUE && longitude != Float.MAX_VALUE) {
contents = "geo:" + latitude + ',' + longitude;
displayContents = latitude + "," + longitude;
title = "Location";
}
}
}
}
public Bitmap encodeAsBitmap() throws WriterException {
if (!encoded) return null;
Hashtable<EncodeHintType, String> hints = null;
String encoding = guessAppropriateEncoding(contents);
if (encoding != null) {
hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result =writer.encode(contents, format, 300, 300, hints);
int width = result.getWidth();
int height =result.getHeight();
int[] pixels = new int[width * height];
// All are 0, or black, by default
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
if(result.get(x, y) )
{
pixels[offset + x] = BLACK ;
}
else
pixels[offset + x] = WHITE ;
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
private static String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) { return "UTF-8"; }
}
return null;
}
private static String trim(String s) {
if (s == null) { return null; }
String result = s.trim();
return result.length() == 0 ? null : result;
}
private static String escapeMECARD(String input) {
if (input == null || (input.indexOf(':') < 0 && input.indexOf(';') < 0)) { return input; }
int length = input.length();
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == ':' || c == ';') {
result.append('\\');
}
result.append(c);
}
return result.toString();
}
}
and also need content.java class..
public class Contents {
private Contents() {
}
public static final class Type {
public static final String TEXT = "TEXT_TYPE";
public static final String EMAIL = "EMAIL_TYPE";
public static final String PHONE = "PHONE_TYPE";
public static final String SMS = "SMS_TYPE";
public static final String CONTACT = "CONTACT_TYPE";
public static final String LOCATION = "LOCATION_TYPE";
private Type() {
}
}
public static final String URL_KEY = "URL_KEY";
public static final String NOTE_KEY = "NOTE_KEY";
public static final String[] PHONE_KEYS = {
ContactsContract.Intents.Insert.PHONE, ContactsContract.Intents.Insert.SECONDARY_PHONE,
ContactsContract.Intents.Insert.TERTIARY_PHONE
};
public static final String[] PHONE_TYPE_KEYS = {
ContactsContract.Intents.Insert.PHONE_TYPE,
ContactsContract.Intents.Insert.SECONDARY_PHONE_TYPE,
ContactsContract.Intents.Insert.TERTIARY_PHONE_TYPE
};
public static final String[] EMAIL_KEYS = {
ContactsContract.Intents.Insert.EMAIL, ContactsContract.Intents.Insert.SECONDARY_EMAIL,
ContactsContract.Intents.Insert.TERTIARY_EMAIL
};
public static final String[] EMAIL_TYPE_KEYS = {
ContactsContract.Intents.Insert.EMAIL_TYPE,
ContactsContract.Intents.Insert.SECONDARY_EMAIL_TYPE,
ContactsContract.Intents.Insert.TERTIARY_EMAIL_TYPE
};
}
also need the core.jar file..
its perfectly work...

How can I parse price from Google Play In-app Billing

I use the follow code to parse price from Google Play In-app Billing:
private static Number parsePrice(String priceFromGoogle) {
Locale currencyLocale = getCurrencyLocale(priceFromGoogle);
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(currencyLocale);
Number number = null;
try {
number = numberFormat.parse(priceFromGoogle);
} catch (ParseException e) {
e.printStackTrace();
}
return number;
}
private Locale getCurrencyLocale(String price) {
Locale locale = null;
for (Locale availableLocale : Locale.getAvailableLocales()) {
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(availableLocale);
try {
numberFormat.parse(price);
locale = availableLocale;
break;
} catch (ParseException e) {
//do nothing
}
}
return locale;
}
It works fine on my test devices and in my locale. But on some devices and in some countries I encounter prices like this: "Php1,337.07", "US$ 29.99", "MX$374.79". My approach doesn't work in this case.
Is there an universal approach to solve this problem?
Check their In-app billing sample project and modify SkuDetails.java so that you can get that information as well:
import org.json.JSONException;
import org.json.JSONObject;
/**
* Represents an in-app product's listing details.
*/
public class SkuDetails {
String mItemType;
String mSku;
String mType;
int mPriceAmountMicros;
String mPriceCurrencyCode;
String mPrice;
String mTitle;
String mDescription;
String mJson;
public SkuDetails(String jsonSkuDetails) throws JSONException {
this(IabHelper.ITEM_TYPE_INAPP, jsonSkuDetails);
}
public SkuDetails(String itemType, String jsonSkuDetails) throws JSONException {
mItemType = itemType;
mJson = jsonSkuDetails;
JSONObject o = new JSONObject(mJson);
mSku = o.optString("productId");
mType = o.optString("type");
mPrice = o.optString("price");
mPriceAmountMicros = o.optInt("price_amount_micros");
mPriceCurrencyCode = o.optString("price_currency_code");
mTitle = o.optString("title");
mDescription = o.optString("description");
}
public String getSku() { return mSku; }
public String getType() { return mType; }
public String getPrice() { return mPrice; }
public String getTitle() { return mTitle; }
public String getDescription() { return mDescription; }
public int getPriceAmountMicros() { return mPriceAmountMicros; }
public String getPriceCurrencyCode() { return mPriceCurrencyCode; }
#Override
public String toString() {
return "SkuDetails:" + mJson;
}
}
You can get the price in micros in the JSON retrieved by IabHelper.
This is not officially documented but here is how I've done it by editing SkuDetails.java :
public class SkuDetails {
...
Double mPriceMicros;
public SkuDetails(String itemType, String jsonSkuDetails) throws JSONException {
...
String priceMicros = o.optString("price_amount_micros");
if (priceMicros != null) {
String format = new StringBuilder(priceMicros).insert(priceMicros.length() - 6, ".").toString();
mPriceMicros = Double.parseDouble(format);
}
}
...
public Double getPriceMicros() { return mPriceMicros; }
}
Hope this helps !
PS : I tried your Price class but it parsed 0.8 for 0,89 €
As Google Play may return prices in currency format which is unsupported by java.text.NumberFormat, I wrote my own implementation
public class Price {
private double value;
private String currency;
private String pattern;
private DecimalFormat decimalFormat;
private Price() {}
private static String currencyToDecimalFormat(String value, Price price) {
char decimalSeparator = '.';
char groupingSeparator = 0;
if (value.length() >= 3) {
char[] chars = value.toCharArray();
if (chars[chars.length - 2] == ',') {
decimalSeparator = ',';
chars[chars.length - 2] = '.';
} else if (chars[chars.length - 3] == ',') {
decimalSeparator = ',';
chars[chars.length - 3] = '.';
}
value = new String(chars);
}
if (value.contains(",")) {
groupingSeparator = ',';
value = value.replaceAll(",", "");
} else if (value.contains(" ")) {
groupingSeparator = ' ';
value = value.replaceAll(" ", "");
} else if (value.contains("\u00A0")) {
groupingSeparator = '\u00A0';
value = value.replaceAll("\u00A0", "");
}
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
if (groupingSeparator != 0) {
price.decimalFormat = new DecimalFormat("###,###.00");
symbols.setGroupingSeparator(groupingSeparator);
} else {
price.decimalFormat = new DecimalFormat("######.00");
}
symbols.setDecimalSeparator(decimalSeparator);
price.decimalFormat.setDecimalFormatSymbols(symbols);
return value.replaceAll(",", "");
}
public static Price parsePrice(String priceFromGoogle) {
Price price = new Price();
StringBuilder patternBuilder = new StringBuilder();
Pattern pattern = Pattern.compile("(?:[0-9]{1,3})(?:[0-9,.\\s\u00A0]+)");
Matcher matcher = pattern.matcher(priceFromGoogle);
matcher.find();
String priceString = matcher.group();
if (priceFromGoogle.indexOf(priceString) == 0) {
if (priceFromGoogle.length() != priceString.length()) {
price.currency = priceFromGoogle.substring(priceString.length());
} else {
price.currency = "";
}
} else {
price.currency = priceFromGoogle.substring(0, priceFromGoogle.indexOf(priceString));
}
price.currency = price.currency.trim();
if (priceFromGoogle.startsWith(price.currency)) {
patternBuilder.append("%1s");
char nextChar = priceFromGoogle.charAt(price.currency.length());
if (nextChar == ' ' || nextChar == 0xA0) {
patternBuilder.append(' ');
}
patternBuilder.append("%2$s");
} else {
patternBuilder.append("%2$s");
char prevChar = priceFromGoogle.charAt(priceFromGoogle.indexOf(price.currency) - 1);
if (prevChar == ' ' || prevChar == 0xA0) {
patternBuilder.append(' ');
}
patternBuilder.append("%1s");
}
price.pattern = patternBuilder.toString();
priceString = trim(priceString);
priceString = currencyToDecimalFormat(priceString, price);
price.value = Double.parseDouble(priceString);
return price;
}
#Override
public String toString() {
if (pattern != null) {
return String.format(pattern, currency, decimalFormat.format(value));
} else {
return "";
}
}
}
EDIT1:
Because of Google uses non-breaking space instead of usual space you need check this and use custom trim function:
public static String trim(String text) {
int start = 0, last = text.length() - 1;
int end = last;
while ((start <= end) && (text.charAt(start) <= ' ' || text.charAt(start) == 0xA0)) {
start++;
}
while ((end >= start) && (text.charAt(end) <= ' ' || text.charAt(end) == 0xA0)) {
end--;
}
if (start == 0 && end == last) {
return text;
}
return text.substring(start, end);
}

Categories

Resources