Wednesday 24 September 2008

T-Mobile G1 is OUT!

First Android-based mobile phone has been released in US!
It will be sold from the 22th of October, priced 179$ (plus taxes and fees; two-year agreement required).
You can know more on this at www.t-mobileg1.com. Unfortunately, it will be SIM-Locked.
Some specifications:
  • 3.2" Touchscreen display (480x320)
  • QWERTY keyboard
  • GPS
  • 3.1Mpixel Camera
  • Qualcomm MSM7210A running @ 528 MHz CPU
  • 256MB ROM / 192MB RAM
  • GSM/GPRS/EDGE
  • UMTS/HSDPA (3G)
  • WiFi 802.11 b/g
  • Bluetooth 2.0 with EDR
  • microSD Card Slot
I hope Politecnico di Torino will buy some of these devices. I'll ask if there's a way for getting a G1 for me (I'll pay it, I swear).

Wednesday 10 September 2008

Android Developers Google Group - A focus on ContentProvider

As requested here, I'm posting some example code for implementing a ContentProvider on which is possible to call openOutputStream and openInputStream.
My only question is: why must I store file path in a database field called '_data', if openFile implementation is programmer's burden?

ElementProvider.java

/*
Copyright (C) 2008 Luca Belluccini

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see
.
*/

package polito.mailandroid;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.os.ParcelFileDescriptor;
import android.text.TextUtils;

public class ElementProvider extends ContentProvider {
private static final String DATABASE_NAME = "poli";
private static final String DATABASE_TABLE = "elements";
private static final int DATABASE_VERSION = 1;
public static final String KEY_ID = "_id";
public static final String KEY_DATA = "_data";
public static final String KEY_MIMETYPE = "mimetype";

private DatabaseHelper mDbH;

private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
}

public void onCreate(SQLiteDatabase db) {
db.execSQL("create table " + DATABASE_TABLE + " (" +
KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_MIMETYPE + " TEXT, " +
KEY_DATA + " TEXT" +
" );");
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
}



public static final int ELEMENTS = 1;
public static final int ELEMENT_ID = 2;
public static final Uri CONTENT_URI = Uri.parse("content://polito.mailandroid/elements");
private static final UriMatcher URI_MATCHER;
private static HashMap
ELEMENTS_LIST_PROJECTION_MAP;
static {
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
URI_MATCHER.addURI("polito.mailandroid", "elements", ELEMENTS);
URI_MATCHER.addURI("polito.mailandroid", "elements/#", ELEMENT_ID);

ELEMENTS_LIST_PROJECTION_MAP = new HashMap
();
ELEMENTS_LIST_PROJECTION_MAP.put(KEY_ID, KEY_ID);
ELEMENTS_LIST_PROJECTION_MAP.put(KEY_DATA, KEY_DATA);
ELEMENTS_LIST_PROJECTION_MAP.put(KEY_MIMETYPE, KEY_MIMETYPE);
}

public boolean onCreate() {
mDbH = new DatabaseHelper(getContext());
return true;
}

public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
String[] projection = new String[] {
ElementProvider.KEY_DATA
};
Cursor c = query(uri,projection,null,null,null);
c.moveToFirst();
String file = c.getString(c.getColumnIndexOrThrow(ElementProvider.KEY_DATA));
c.close();
File f = new File(file);
int m = ParcelFileDescriptor.MODE_READ_ONLY;
if (mode.equalsIgnoreCase("rw"))
m = ParcelFileDescriptor.MODE_READ_WRITE;
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(f,m);
return pfd;
}

public Uri insert(Uri uri, ContentValues initialValues) {
if (URI_MATCHER.match(uri) != ELEMENTS) {
// !!!
}
ContentValues values;
if (initialValues != null) {
values = new ContentValues(initialValues);
} else {
values = new ContentValues();
}

if (!values.containsKey(KEY_MIMETYPE))
values.put(KEY_MIMETYPE, "plain/text");

SQLiteDatabase mDb = mDbH.getWritableDatabase();
long rowID = mDb.insert(DATABASE_TABLE, "notnull", values);
if (rowID > 0) {
if (!values.containsKey(KEY_DATA)){
try {
String filename = rowID + "";
getContext().openFileOutput(filename, Context.MODE_PRIVATE).close();
String path = getContext().getFileStreamPath(filename).getAbsolutePath();
values.put(KEY_DATA, path);
update(uri,values,KEY_ID + "=" + rowID, null);
} catch (Exception e) {
// !!!
}
}
Uri newUri = ContentUris.withAppendedId(ElementProvider.CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(newUri, null);
return newUri;
}
// !!!
return null;
}

public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
switch (URI_MATCHER.match(uri)) {
case ELEMENTS:
qb.setTables(DATABASE_TABLE);
qb.setProjectionMap(ELEMENTS_LIST_PROJECTION_MAP);
break;
case ELEMENT_ID:
qb.setTables(DATABASE_TABLE);
qb.appendWhere(KEY_ID + "=" + uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
SQLiteDatabase mDb = mDbH.getReadableDatabase();
Cursor c = qb.query(mDb, projection, selection, selectionArgs, null, null, "_id DESC");
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
int code = URI_MATCHER.match(uri);
int count = 0;
SQLiteDatabase mDb = mDbH.getWritableDatabase();
switch (code) {
case ELEMENTS:
count = mDb.update(DATABASE_TABLE, values, selection, selectionArgs);
break;
case ELEMENT_ID:
String id = uri.getPathSegments().get(1);
count =
mDb.update(DATABASE_TABLE, values, KEY_ID + "=" + id
+ (!TextUtils.isEmpty(selection) ? " AND ("
+ selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}

public int delete(Uri uri, String where, String[] whereArgs) {
int code = URI_MATCHER.match(uri);
int count = 0;
SQLiteDatabase mDb = mDbH.getWritableDatabase();
switch (code) {
case ELEMENTS:
// !!! REMOVE ALL FILES
count = mDb.delete(DATABASE_TABLE, where, whereArgs);
break;
case ELEMENT_ID:
String id = uri.getPathSegments().get(1);
// !!! REMOVE ASSOCIATED FILE
count =
mDb.delete(DATABASE_TABLE, KEY_ID + "=" + id
+ (!TextUtils.isEmpty(where) ? " AND (" + where
+ ')' : ""), whereArgs);
break;
default:
// !!!
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}

public String getType(Uri uri) {
String[] projection = new String[] {
ElementProvider.KEY_MIMETYPE
};
Cursor c = query(uri,projection,null,null,null);
c.moveToFirst();
String mimetype = c.getString(c.getColumnIndexOrThrow(ElementProvider.KEY_MIMETYPE));
c.close();
return mimetype;
}

}

Friday 5 September 2008

Antivirus roundup by AV-Test

Here you are a table containing a roundup of several antivirus software.

You can find more here.

Wednesday 3 September 2008

Google Chrome browser SHORT review

Surfing the web by using GBrowser...
Fast, indeed. Uses Webkit, so webpages are displayed correctly... More or less.
Used memory is very low. That could be a great advantage on not very fast machines.
It is a BETA: it is not possible to manage bookmarks... No plug-ins. No extensions.
I think Google released this browser with the aim of provide a fast browser for netbooks and implement some optimization (and integration) with Google Apps (Google Gears).
It cannot replace Mozilla Firefox, now.

Official Google Blog: Google Chrome now live

Tuesday 2 September 2008

Google Chrome

... Unexpected news from big G ...
Google Chrome will be released as Beta version within few hours from now.
Some features I caught on the net seem to be:
  • optimized "Task - Process" management
  • optimized JavaScript engine
  • uses WebKit (as Safari and the Android Browser)
  • designed from scratch, based on nowadays needs
  • optimized Garbage collector
  • (?) maybe based on VMs
Here you can read a clear and easily readable document, explaining why Google is releasing that browser.