How to make query using google app engine endpoint for android? - android

I'm developing an Android project using google app engine endpoints. We tried to insert a new query in an automatically generated endpoint class (I have a Poll.java class and a PollEndpoint.java class) in the server side, but the system doesn't work because a red cross is showed on the AppEngine part of the project. No other error message are shown.
Code insert in PollEndpoint.java class:
#ApiMethod(name = "getLastPoll")
public Long getLastPoll(#Named("date") Date date, #Named("creator") String creator) {
EntityManager mgr = getEntityManager();
Key id = null;
try {
Query query = mgr.createQuery("select keyPoll from Poll where creator
=" + creator + " and creationDate = " + date);
id = (Key)query.getSingleResult();
} finally {
mgr.close();
}
return id.getId();
}
Is it correct to do query in this way?

When you get a red cross on the project but can't see any errors I suggest you look at the errors/warning view (I think that's what its called). You haven't specified your IDE so I'm assuming Eclipse.
Most often it is a problem with your build path.

Related

GreenDAO does not persist data across application restart

I want to use GreenDAO for persistence, but I cannot get it to persist my data.
The data is saved and loaded correctly as long as the application is not restarted.
Once i swipe the app away and reopen it from scratch, GreenDAO does not see the previous data (both on the emulator and real device).
This is my entity:
#Entity
public class TestSingleEntity {
#Id(autoincrement = true)
Long id;
int someNumber;
public TestSingleEntity(int someNumber) {
this.someNumber = someNumber;
}
#Generated(hash = 787203968)
public TestSingleEntity(Long id, int someNumber) {
this.id = id;
this.someNumber = someNumber;
}
#Generated(hash = 1371368161)
public TestSingleEntity() {
}
// ... some more stuff
}
This is how I insert entities to database:
Random rnd = new Random();
TestSingleEntity singleEntity = new TestSingleEntity();
singleEntity.setSomeNumber(rnd.nextInt());
DaoSession session = ((MyApp)getApplication()).getDaoSession();
TestSingleEntityDao dao = session.getTestSingleEntityDao();
dao.insert(singleEntity);
Log.d("tgd", "Inserted an entity with id " + singleEntity.getId());
And this is how I read them:
Query query = dao.queryBuilder().orderAsc(TestSingleEntityDao.Properties.SomeNumber).build();
StringBuilder builder = new StringBuilder();
List<TestSingleEntity> result = query.list();
Log.d("size", result.size());
for (TestSingleEntity testSingleEntity : result) {
Log.d("entity", testSingleEntity.toString());
}
As I have said, as long as I stay in the app (moving around in different activities is okay), everytime the insert is called, a new entity with a new ID is created. As soon as I relaunch the app, it goes back to square one.
The setup was taken directly from the GitHub page. What am I doing wrong? Thanks
Disclaimer: GreenDAO has gone through major changes since I last used it so this is purely based on reading their code on the github.
Apparently GreenDAO's poorly documented DevOpenHelper drops all tables on upgrade, so the real question is why is onUpgrade being called when clearly there hasn't been a change to the schema version. Try to look for the log line that mentions dropping the tables as described in the template for DevOpenHelper.
Regardless, using OpenHelper instead should fix the issue.

Why am I unable to use obtain any results by using SQLite's 'LIKE' clause in an AIR Desktop App?

I am trying to build a simple Library Management System for a class project. I am using SQLite to do that.
The app looks like this:
At first I select and load everything from the table, which works fine as seen in the above image:
Here is the create table query:
"CREATE TABLE IF NOT EXISTS books (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, isbn TEXT, category TEXT, authors TEXT, publisher TEXT, edition INTEGER, copies INTEGER, pdf TEXT, cover TEXT)";
Here is the query that selects the whole table:
"SELECT id, title, isbn, authors, publisher, edition, copies, pdf, cover FROM books ORDER BY id";
To implement the search functionality, I tried using the 'LIKE' clause, like this:
"SELECT id, title, isbn, category, authors, publisher, edition, copies, pdf, cover FROM books WHERE title LIKE %'"+userInput+"'% ORDER BY id";
When I search with the above query, I get this error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at (address-removed)/BooksContainer.as:124]
And here is line 124:
var numResults:uint = result.data.length;
I tried to change the code but after working with for about a week, I still get the same error.
Yesterday, however I tried to approach it in a different as I was really frustrated and I was sure this approach would work. What I did is I selected the entire table like this:
public function searchBooks(userInput:String)
{
var stat:SQLStatement = new SQLStatement();
stat.sqlConnection = _connection;
stat.text = "SELECT id, title, isbn, category, authors, publisher, edition, copies, pdf, cover FROM books ORDER BY id";
//stat.parameters['#search'] = "%" + userInput + "%";
stat.execute();
trace(stat.text);
searchedString = userInput;
stat.addEventListener(SQLEvent.RESULT, createSearchedContent, false, 0, true);
}
private function createSearchedContent(e:SQLEvent):void
{
var result:SQLResult = e.target.getResult();
_allBooks = result;
trace(result.data);
var numResults:uint = result.data.length;
var currentY:Number = 0;
var xIterator:Number = 0;
for (var i:int = 0; i < numResults; i++)
{
var row:Object = result.data[i];
var bookTitle:String = String(result.data[i].title);
if (bookTitle.toLowerCase().indexOf(searchedString.toLowerCase()) > -1)
{
var book:Book = new Book(row.title, row.isbn, row.category, row.authors, row.publisher, row.edition, row.copies, row.pdf, row.cover);
book.x = book.width * xIterator + 10;
book.y = currentY;
addChild(book);
xIterator++;
if (xIterator == 7)
{
xIterator = 0;
currentY += book.height + 10;
}
}
}
}
Surprisingly enough, I got the same error. I didn't get it at all. Then I put this in the above loop:
var a:String = _main.search_txt.text.toLowerCase();
var b:String = String(row.title.toLowerCase());
trace(b.indexOf(a), a, b);
What I found out is that , in the trace I always get -1 for the searched term.
Here is the output window:
-1 data dark matter and the dinosaures
-1 data a history of religious ideas
-1 data steve jobs
-1 data digital logic design
-1 data thomas calculus
-1 data Data structures and algorithms in java
-1 data data structures in c++
-1 data data structures and algorithms in java
-1 data data structures and algorithms in java
So can any one help me out here?? I've only got a week to finish this project. Thanks in advance.
It looks that percent operators position issue.
Collect query
where something like '%foo%'
Your query
where something like %'foo'%
Put the percent operators inside single quotations.
"SELECT id, title, isbn, category, authors, publisher, edition, copies, pdf, cover FROM books WHERE title LIKE '%"+userInput+"%' ORDER BY id";
You also able to use like clause with parameters.
ActionScript and SQLite parameters on Select using Like

SQLite injection - Doing something wrong with querying

I'm trying to do some Sqlite querying but I don't know if I'm doing it correctly because this feels really unsave to do. So my question is how do I fix this. I'm new to the whole Xamarin and Sqlite usage.
I'm only making a Android project so it is not a cross platform application. I also cant seem to figure out where to get Mono.Data.Sqlite if I even need it. Everything is welcome.
static public List<Users> SelectUser(string name)
{
try
{
var dbConn = new SQLiteConnection(DatabasePath);
{
return dbConn.Query<Users>("SELECT name, email FROM TblUsers where name = " + name+ ";");
}
}
catch (SQLiteException ex)
{
return null;
}
}
You should use Prepared Statements.
There is an official java documentation about Prepared Statements from Oracle here.
You can also search it on google. There are a lot of guides on how to use prepared statements.

How to use Spatialite with Xamarin on Android

I want to use Spatialite instead of plain SQLite with Xamarin on Android, to manage and display geographical data. Built-in SQLite does not allow to load extensions. How can I do it?
Short answer: you need to use own customized SQLite as Android Native Library, like with other NDK libraries. The tricky part is to get useful not so trivial C# API for the database. Xamarin docs seems to have guides for very simple single method APIs only.
As I am way more familiar to Java than .Net, then I used combination of Android Java library (.jar) and Android native library (.so). Android Java library has already Java API wrapper for the database, it is exactly the same wrapper as can be used in the usual Android Java applications. Of course, technically direct access of the native library from C# would be also possible, so java/jar could be excluded from the story. If you know good tools for that, let me know also.
Create .jar binding project for Xamarin, add it to the same solution as your Android project
Add jsqlite.jar to Jars folder of the bindings project. Get it from here: jsqlite.jar
Add native library binaries (libjsqlite.so and libproj.so) to your application project, create folder libs/armeabi for this. Get these from Nutiteq AdvancedMap3D project
Define the .so files as AndroidNativeLibrary, and set Copy to Output Directory
Fix binding definitions to remove build errors. Add following to Transforms/Metadata.xml of your bindings project:
<remove-node path="/api/package[#name='jsqlite']/class[#name='Backup']/field[#name='handle']" />
<remove-node path="/api/package[#name='jsqlite']/class[#name='Database']/field[#name='handle']"/>
<attr path="/api/package[#name='jsqlite']" name="managedName">jsqlite</attr>
This should generate you working C# API to bundled SQLite, together with Spatialite, Proj.4 and GEOS included. The jsqlite DB API itself is different from other C# SQLite APIs, you need to use callback classes. See following examples To check versions of the modules:
try {
db.Open ("/sdcard/mapxt/estonia-latest-map.sqlite", Constants.SqliteOpenReadonly);
// show versions to verify that modules are there
db.Exec ("SELECT spatialite_version(), proj4_version(), geos_version(), sqlite_version()", new GeneralQryResult ());
} catch (jsqlite.Exception ex) {
Log.Error( ex.LocalizedMessage );
}
...
// prints query results as text
public class GeneralQryResult : Java.Lang.Object, ICallback
{
public bool Newrow (string[] rowdata)
{
string row = "";
foreach (var data in rowdata) {
row += data + " | ";
}
Log.Info(row);
return false;
}
public void Types (string[] types)
{
// never called really
}
public void Columns (string[] cols){
Log.Debug ("Query result:");
string row = "";
foreach (var col in cols) {
row += col + " | ";
}
Log.Info (row);
}
}
Finally now a query of real spatial data, using Nutiteq 3D Maps SDK for Xamarin to visualize it:
// Spatialite query, show results on map
// 1. create style and layer for data
LineStyle.Builder lineStyleBuilder = new LineStyle.Builder ();
lineStyleBuilder.SetColor (NutiteqComponents.Color.Argb(0xff, 0x5C, 0x40, 0x33)); //brown
lineStyleBuilder.SetWidth (0.05f);
LineStyle lineStyle = lineStyleBuilder.Build ();
GeometryLayer geomLayer = new GeometryLayer (view.Layers.BaseLayer.Projection);
view.Layers.AddLayer (geomLayer);
// 2. do the query, pass results to the layer
Database db = new Database ();
try {
db.Open ("/sdcard/mapxt/estonia-latest-map.sqlite", Constants.SqliteOpenReadonly);
// spatial query. Limit to 1000 objects to avoid layer overloading
String qry = "SELECT id, HEX(AsBinary(Transform(geometry,3857))), sub_type, name FROM ln_railway LIMIT 1000";
db.Exec (qry, new SpatialQryResult (geomLayer, lineStyle));
} catch (jsqlite.Exception ex) {
Log.Error( ex.LocalizedMessage );
}
...
// adds query results to given layer, with given style
public class SpatialQryResult : Java.Lang.Object, ICallback
{
GeometryLayer _geomLayer;
Style _geomStyle;
public SpatialQryResult(GeometryLayer geomLayer, Style geomStyle){
_geomLayer = geomLayer;
_geomStyle = geomStyle;
}
public bool Newrow (string[] rowdata)
{
string id = rowdata [0];
string geomHex = rowdata [1];
string type = rowdata [2];
string name = rowdata [3];
Label label;
if (name != null && name.Length > 1) {
label = new DefaultLabel (name, type);
} else {
label = null;
}
Geometry[] lineGeoms = WkbRead.ReadWkb(new ByteArrayInputStream(Utils
.HexStringToByteArray(geomHex)), rowdata);
// following fails if not Line, change for other geometries
foreach (Line lineGeom in lineGeoms) {
_geomLayer.Add(new Line(lineGeom.VertexList, label, (LineStyle)_geomStyle, _geomLayer));
}
return false;
}
}

Android billing - in the file Security.java should the base64EncodedPublicKey be the encoded value?

Should I paste the actual public key of my app right into the value of this variable?
Or should I encode it and then whatever the encoded string is, I'd make that string into the value of this variable?
Which should it be?
The public key present in your Android Developer Console (which can be found under 'Edit Profile') is already Base64 encoded. Just copy paste the content of the key in your source file. For example, if you have something like this:
Then in your Security.java:
String base64EncodedPublicKey = "MIIBIjANBgkqhkiG9w0BAQ......";
As the Google sample code for In-app billing say, you should obfuscate this public key.
Instead of just storing the entire literal string here embedded in the
program, construct the key at runtime from pieces or
use bit manipulation (for example, XOR with some other string) to hide
the actual key. The key itself is not secret information, but we don't
want to make it easy for an attacker to replace the public key with one
of their own and then fake messages from the server.
I use very simple Java code to generate the Java Class that will give me back the public key. The basic idea is to use recursion to recreate the key using inner static class. It's just food for thought.
It's a "good-enough" approach for my niche market. See this stackexchange security question for more information on obfuscation.
public static void main(String[] args) throws Exception {
String className = genClassName();
PrintWriter writer = new PrintWriter("C:\\" + className + ".java", "iso-8859-1");
printClass(className, writer, "XXXXXX-YOUR-PUBLIC-KEY-GOES-HERE-XXXXXXX", true);
writer.close();
}
private static String genClassName() {
return "Class" + UUID.randomUUID().toString().replaceAll("-", "");
}
private static String printClass(String thisClass, PrintWriter writer, String key, boolean root) {
int split = key.length() / 2;
if (split < 10) {
writer.println("public " + (root ? "" : "static") + " class " + thisClass + " {");
writer.println("public static String get() {");
writer.println("return \"" + key + "\";");
writer.println("}");
writer.println("}");
} else {
String first = key.substring(0, split);
String last = key.substring(split, key.length());
writer.println("public " + (root ? "" : "static") + " class " + thisClass + " {");
String class1 = printClass(genClassName(), writer, first, false);
String class2 = printClass(genClassName(), writer, last, false);
writer.println("public static String get() {");
writer.println("return " + class1 + ".get() + " + class2 + ".get();");
writer.println("}");
writer.println("}");
}
return thisClass;
}
You need the public key in the program's source code so that you can check the signature. Yes, there's nonzero, unavoidable risk that a cracker will find it, replace it with a fake, and feed your program fake purchases.
You cannot completely hide the key from prying eyes, but you can obfuscate. You can break up the Base64 string into several string constants in different spots and concatenate them before use. Better give the chunks inconspicuous names (not like MY_PUBLIC_KEY_PART_4). You can also apply an additional layer of soft encryption to it - something like XOR a value. You can add an integrity check - make sure the key has not been spoofed (say, store the hash of a key elsewhere and check). But this is all still security via obscurity - a determined enough hacker will get through.
Also consider ProGuard, the built-in code obfuscation tool.
If you have a server component as part of your app, then you can move most of the elements of your security, including your public key, to your server. On the server, you can generate the nonce and verify the purchase (I've moved mine to a RESTFul WCF service). If your server component is .NET based, then you'll probably have to generate a modulus and an exponent from your public key so that you can use the RNGCryptoServiceProvider class. There's a Google I/O video which gives an overview to In-App Billing amongst others.

Categories

Resources