Android SQL Lite query very slow - android

I have developed a this function for search all element in a 20 km range respect position of single element into
ArrayList<GeoJsonResponse> result = new ArrayList<GeoJsonResponse>();
Cursor cursor = mDb.query(database_event_schema.TABLE_NAME, null, null, null, null, null, null);
String[] colums = new String[]{database_event_schema._EVENT_ID,database_event_schema._AUTHOR, database_event_schema._LAT,database_event_schema._LON,database_event_schema._PLACE,database_event_schema._MAG,database_event_schema._DEPTH,database_event_schema._TIME};
Double lat,lon,magnitude = null,distance = null;
if (cursor != null) {
while (cursor.moveToNext()) {
try{lat = Double.valueOf(cursor.getString(cursor.getColumnIndex(database_event_schema._LAT)));}catch(Exception e){continue;}
try{lon = Double.valueOf(cursor.getString(cursor.getColumnIndex(database_event_schema._LON)));}catch(Exception e){continue;}
String place = cursor.getString(cursor.getColumnIndex(database_event_schema._PLACE));
double dist_km = Utills.distance(curPos.latitude,curPos.longitude,lat,lon,'K');
if(dist_km>=0 && dist_km<=10) {
String id = cursor.getString(cursor.getColumnIndex(database_event_schema._EVENT_ID));
String author = cursor.getString(cursor.getColumnIndex(database_event_schema._AUTHOR));
try{magnitude = Double.valueOf(cursor.getString(cursor.getColumnIndex(database_event_schema._MAG)));}catch(Exception e){}
try{distance = Double.valueOf(cursor.getString(cursor.getColumnIndex(database_event_schema._DEPTH)));}catch(Exception e){}
String date = cursor.getString(cursor.getColumnIndex(database_event_schema._TIME));
Date dateNew = null;
if(!date.equals(""))
{
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
try {
dateNew = format.parse(date);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("test", e.getLocalizedMessage());
}
}
result.add(new GeoJsonResponse(id,author,place,magnitude,distance,date,dateNew,lat,lon));
}
}
}
return result;
but the query is very slow. How can I increase the speed query?
By this table the query select all element with a location with 20km respect the event selected. The table have 500.000 record whitout index.
The result are show into a list
I have write a wrong code?
Thanks

You should create a SQLite distance function in C (so the distance calculation will be faster) and use it as a filter in your query to limit the results.
See an example (for iOS): http://www.thismuchiknow.co.uk/?p=71

Related

Loading Artists from Android MediaStore along with Artwork

I am aware that media artwork is stored under albums and to get them you need to have the album id to access it. I have been able to get the images for tracks and albums using the album id.
However for artists table doesn't have the album id field. Other apps such as Play Music and Poweramp are somehow able to get the track artwork and add them to the respective artists.
How do i achieve this?
The way I do it is to get all albums for an artist and then use the rnd function to return an albumid:
String artist_id = c.getString(c.getColumnIndex(MediaStore.Audio.Artists._ID));
Cursor crs = album.getArtistsAlbumcursor(mContext, artist_id);
if(crs!=null && crs.moveToFirst()) {
Random rn = new Random();
int rnd = rn.nextInt( crs.getCount());
crs.moveToPosition(rnd);
album_id = crs.getLong(crs.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
crs.close();
}
where getArtistsAlbumcursor is:
public Cursor getArtistsAlbumcursor(Context context, String artistId) {
ContentResolver cr = context.getContentResolver();
final String _id = MediaStore.Audio.Media._ID;
final String album_id = MediaStore.Audio.Media.ALBUM_ID;
final String artistid = MediaStore.Audio.Media.ARTIST_ID;
final String[] columns = { _id, album_id, artistid };
String where = artistid +" =?";
String[] aId = {artistId};
return cr.query(uri, columns, where, aId, null);
}
Once you have an albumid you can get your albumart using your original method.
Or
if you want to get the albumart from the mp3 track itself, you will need to implement a libary such as jaudiotagger or org.blinkenlights.jid3.v2.
Life gets a little more complicated but below how to get albumart from the mp3 tag using the JID3 library:
try {
bmp = getmp3AlbumArt(sourceFile);
} catch (Exception e) {
e.printStackTrace();
}
where getmp3Albumart is:
public Bitmap getmp3AlbumArt(File SourceFile) throws Exception {
Bitmap bmp = null;
arrayByte = null;
APICID3V2Frame frames[];
MediaFile MediaFile = new MP3File(SourceFile);
try {
Object obj = null;
obj = MediaFile.getID3V2Tag();
if (obj != null) {
tagImage = (org.blinkenlights.jid3.v2.ID3V2_3_0Tag) obj;
if ((tagImage != null) && (arrayByte == null) && (tagImage.getAPICFrames() != null) && (tagImage.getAPICFrames().length > 0)) {
frames = tagImage.getAPICFrames();
for (int i = 0; i < tagImage.getAPICFrames().length; i++) {
if (frames[i] != null) {
arrayByte = frames[i].getPictureData();
break;
}
}
}
}
} catch (ID3Exception | OutOfMemoryError e) {
e.printStackTrace();
}
if (arrayByte != null) {
try {
bmp = BitmapFactory.decodeByteArray(arrayByte, 0, arrayByte.length);
} catch (Exception|OutOfMemoryError e) {
e.printStackTrace();
}
}
return bmp;
}

create json data in android for call logs

I want to create a json format for my call logs details like the below and send it to the server in android :
{"Calllogs":{
"logdata":[
{
"id":"9791",
"number":"+919122185954",
"duration":"0",
"types":"3",
"date":"1425887846182",
"name":"ww"}
,
{
"id":"9790",
"number":"+91712222777",
"duration":"32",
"types":"1",
"date":"1425880324221",
"name":"Dpika"}
:
:
:
:
]}}
but when i use the below code to fetch all the call logs details in json format and send it to the server , i am getting a very unusual error like when i send 30 contacts it is working fine but when i fetch more than that i am getting an error ????
CODE:
public void GetCallLogs()
{
JSONObject main= new JSONObject();
JSONObject calllogs = new JSONObject();
JSONArray logs = new JSONArray();
Cursor cur = getContentResolver().query(Uri.parse("content://call_log/calls"),null, null, null, "_ID DESC");
cur.moveToFirst();
int nameColumn = cur.getColumnIndex(CallLog.Calls.CACHED_NAME);
int numberColumn = cur.getColumnIndex(CallLog.Calls.NUMBER);
int dateColumn = cur.getColumnIndex(CallLog.Calls.DATE);
int duretion = cur.getColumnIndex(CallLog.Calls.DURATION);
int type = cur.getColumnIndex(CallLog.Calls.TYPE);
int id = cur.getColumnIndex(CallLog.Calls._ID);
int i=0;
JSONObject studenti = new JSONObject();
while (!cur.isAfterLast() && i < 50) {
String name = cur.getString(nameColumn);
String number = cur.getString(numberColumn);
String date = cur.getString(dateColumn);
String duration = cur.getString(duretion);
String types = cur.getString(type);
String ids = cur.getString(id);
try {
studenti.put("id", ids);
studenti.put("name",name);
studenti.put("date", date);
studenti.put("duration", duration);
studenti.put("types", types);
studenti.put("number", number);
Log.d("HERE IN FETCHCALL", "name"+name);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
logs.put(studenti);
studenti = new JSONObject();
cur.moveToNext();
i++;
}
try {
calllogs.put("logdata", logs);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
main.put("Calllogs", calllogs);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Since you are not giving enough info, I must have to assume that you are wanting to create a JSON file with your following code:
name
number
date
duration
types
ids
I have used this link to create JSON files for my ListView.

How to pass filter criterion to APIs in gae project for android

I'm new to android and GAE and trying to create one small android app which manages inventory of vehicles. I'm stuck in a scenario where I need to get aggregated stock count for a particular dealer. The default APIs created by Google doesn't support any such functionality so I created one of my own which is working fine. But the issue is, I need to pass in filter criterion from my android app and I'm not sure how to achieve that.
My GAE code
#ApiMethod(name = "listAggregatedStock", path = "listAggregatedStock")
public CollectionResponse<AggregatedStock> listAggregatedStock(
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit,
#Nullable #Named("columns") String[] columns,
#Nullable #Named("values") String[] values) {
EntityManager mgr = null;
Cursor cursor = null;
List<AggregatedStock> execute = null;
StringBuffer queryString = new StringBuffer();
queryString.append(" select date, vehicleCode, vehicleSubCode, colorCode, sum(count) from Stock as AggregatedStock ");
if(columns != null && columns.length > 0) {
queryString.append(" where ");
int i = 0;
for(String column : columns){
if(i > 0){
queryString.append(" and ");
}
queryString.append(column + " = :" + column);
i++;
}
}
queryString.append(" group by date, vehicleCode, vehicleSubCode, colorCode ");
try {
mgr = getEntityManager();
Query query = mgr.createQuery(queryString.toString());
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
if (limit != null) {
query.setFirstResult(0);
query.setMaxResults(limit);
}
if(columns != null && columns.length > 0) {
for(int i = 0; i < columns.length; i++) {
query.setParameter(columns[i], values[i]);
}
}
List<Object[]> results = (List<Object[]>) query.getResultList();
execute = new ArrayList<AggregatedStock>();
for (Object[] result : results) {
execute.add(new AggregatedStock((Date) result[0],
(String) result[1], (String) result[2],
(String) result[3], ((Long) result[4]).intValue()));
}
cursor = JPACursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and
// accomodate
// for lazy fetch.
for (AggregatedStock obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<AggregatedStock> builder().setItems(execute)
.setNextPageToken(cursorString).build();
}
This is how I'm calling it from my android app
#Override
protected CollectionResponseAggregatedStock doInBackground(
String... params) {
String dealer = params[0];
String vehicle = params[1];
Stockendpoint.Builder endpointBuilder = new Stockendpoint.Builder(
AndroidHttp.newCompatibleTransport(), new JacksonFactory(),
null);
endpointBuilder = CloudEndpointUtils.updateBuilder(endpointBuilder);
CollectionResponseAggregatedStock result;
Stockendpoint endpoint = endpointBuilder.build();
try {
result = endpoint.listAggregatedStock().execute();
} catch (IOException e) {
e.printStackTrace();
result = null;
}
return result;
}
current issue I'm facing is, I'm not able to pass column and values string[]. When I add them like this
result = endpoint.listAggregatedStock(null, null, new String[]{"column"}, new String[]{"value"}).execute();
the signatures doesn't match. I'm not sure if this is the right way. I'm using cloud libraries generated by Google plug-in
I was finally able to achieve it this way
#SuppressWarnings({ "unchecked" })
#ApiMethod(name = "listAggregatedStock", path = "listAggregatedStock")
public List<AggregatedStock> listAggregatedStock(#Nonnull #Named("dealer") String dealer) {
List<AggregatedStock> execute = null;
PersistenceManager pm = getPersistenceManager();
StringBuilder sb = new StringBuilder();
sb.append(" select date, vehicleCode, vehicleSubCode, colorCode, ");
sb.append(" SUM(count) from Stock as AggregatedStock ");
Query query = pm
.newQuery(sb.toString());
query.setFilter(" updatedByDealer == " + dealer);
query.setGrouping(" date, vehicleCode, vehicleSubCode, colorCode ");
query.setOrdering(" vehicleCode desc ");
query.declareImports("import com.sandeepapplabs.dms.Stock");
try {
List<Object[]> results = (List<Object[]>) query.execute();
execute = new ArrayList<AggregatedStock>();
for (Object[] result : results) {
execute.add(new AggregatedStock((Date) result[0],
(String) result[1], (String) result[2],
(String) result[3], ((Long) result[4]).intValue()));
}
} finally {
pm.close();
}
return execute;
}
Instead of doing it GAE default way, I implemented JDO

How do the retrieve the date of the mms from content://mms.

I did get the information on how to retrieve the text and the image for the mms sent from this link: How to Read MMS Data in Android?.
But I am not sure how to retrieve the date for the mms that was sent.
I know I have to look into content://mms and not in content://mms/part.
This is the Mothod to retrieve the mms text:
private String getMmsText(String id) {
Uri partURI = Uri.parse("content://mms/part/" + id);
InputStream is = null;
StringBuilder sb = new StringBuilder();
try {
is = getContentResolver().openInputStream(partURI);
if (is != null) {
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
BufferedReader reader = new BufferedReader(isr);
String temp = reader.readLine();
while (temp != null) {
sb.append(temp);
temp = reader.readLine();
}
}
} catch (IOException e) {
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
return sb.toString();
}
and then, in the onCreate method, I use this code to get the info:
Cursor cursor = getContentResolver().query(uri, null, selectionPart,
null, null);
if (cursor.moveToFirst()) {
do {
String partId = cursor.getString(cursor.getColumnIndex("_id"));
String type = cursor.getString(cursor.getColumnIndex("ct"));
if ("text/plain".equals(type)) {
String data = cursor.getString(cursor
.getColumnIndex("_data"));
if (data != null) {
// implementation of this method above
body = getMmsText(partId);
} else {
body = cursor.getString(cursor.getColumnIndex("text"));
}
}
} while (cursor.moveToNext());
}
try {
main.setText(body);
img.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
I just want to know where can I make changes to get the date value.
Some info will be really helpful.
I'm not overly familiar with MMS's, but I'd imagine something like this would at least get you started
Cursor cursor = activity.getContentResolver().query(Uri.parse("content://mms"),null,null,null,date DESC);
count = cursor.getCount();
if (count > 0)
{
cursor.moveToFirst();
long timestamp = cursor.getLong(2);
Date date = new Date(timestamp);
String subject = cursor.getString(3);
}
It's completely untested of course, but should point you in the right direction. Hope this helps!
Edit
After doing a bit of reading, there used to be (possibly still is) a "bug" with the timestamp in MMS messages, when retrieving the data. If you end up with a silly value (like the epoch), you'll have to * 1000 before using it. Just an aside :) I.e.:
long timestamp = (cursor.getLong(2) * 1000);

Programmatically set R.ID

I downloaded a class from Catch The Cows, it is akin to a Google Map object or at least that is what I am using it for.
It parses an XML file which lists the areas of the screen that should be touchable, and then creates them with this method.
This is here for context, I have commented out some parts of code, and added my own to try and resolve my issue
private Area addShape( String shape, String name, String coords, String id) {
Log.v("IDS:", "id was "+id);
Area a = null;
String rid = id.replace("#+id/", "");
Log.v("IDS:", "rid was "+rid);
// Generate a new ID for the area.
int _id = 1;
View vi = findViewById(_id);
while (vi!=null) {
_id++;
vi = findViewById(_id);
}
//View.generateViewId(); //=0;
Log.v("IDS:", "After conversion final time "+_id);
/*
try {
Class<R.id> res = R.id.class;
Field field = res.getField(rid); // eg. rid = area10
_id = field.getInt(null);
Log.v("IDS:", "After conversion "+_id);
}
catch (Exception e) {
_id = 0;
Log.e("Exception ",e.getMessage());
} finally {
Log.v("IDS:", "After conversion final time "+_id);
}
*/
if (_id != 0) {
if (shape.equalsIgnoreCase("rect")) {
String[] v = coords.split(",");
if (v.length == 4) {
a = new RectArea(_id, name, Float.parseFloat(v[0]),
Float.parseFloat(v[1]),
Float.parseFloat(v[2]),
Float.parseFloat(v[3]));
}
}
if (shape.equalsIgnoreCase("circle")) {
String[] v = coords.split(",");
if (v.length == 3) {
a = new CircleArea(_id,name, Float.parseFloat(v[0]),
Float.parseFloat(v[1]),
Float.parseFloat(v[2])
);
}
}
if (shape.equalsIgnoreCase("poly")) {
a = new PolyArea(_id,name, coords);
}
if (a != null) {
addArea(a);
}
} else {
Log.v("Loading ID: ","_id was 0");
}
return a;
}
Unfortunately nothing was rendering on the screen, and this was because _id = 0. This should be changed with this bit of code:
try {
Class<R.id> res = R.id.class;
Field field = res.getField(rid); // eg. rid = area10
_id = field.getInt(null);
}
How ever I am not sure what it does to try and debug it, can anyone explain what this snippet is doing?
R is a Read-Only class. It is generate at compile time and You should not use reflection to modify its field. Also you should avoid reflection to access the fields values. You should use the official API.
The comment at the first row of the class is
/* AUTO-GENERATED FILE. DO NOT MODIFY. */

Categories

Resources