Posts Tagged ‘Databases’
[DevoxxFR2012] Advanced Android Patterns: Mastering Services, Content Providers, and Asynchronous Operations
Lecturer
Mathias Seguy founded Android2EE, specializing in Android training, expertise, and consulting. Holding a PhD in Fundamental Mathematics and an engineering degree from ENSEEIHT, he transitioned from critical J2EE projects—serving as technical expert, manager, project leader, and technical director—to focus on Android. Mathias authored multiple books on Android development, available via Android2ee.com, and contributes articles to Developpez.com.
Abstract
This article delves into Mathias Seguy’s continuation of essential Android development concepts, emphasizing services for background tasks, content providers for data sharing, and patterns for lifecycle synchronization. Building on foundational elements, it analyzes implementation strategies for bound/unbound services, CRUD operations in providers, and thread management with handlers/AsyncTasks. Within Android’s resource-constrained environment, the discussion evaluates techniques for internationalization, resource optimization, and database integration. Through detailed code examples, it assesses implications for application responsiveness, data integrity, and cross-app interoperability, guiding developers toward efficient, maintainable architectures.
Implementing Services for Background Processing
Services enable persistent operations independent of UI, running in the application’s main thread—necessitating offloading to avoid ANRs. Mathias distinguishes unbound (started via startService(), autonomous) from bound (via bindService(), allowing communication).
Lifecycle binding is critical: Align service states with calling components using booleans for running/pausing. Code for an unbound service:
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Start task
return START_STICKY; // Restart if killed
}
@Override
public void onDestroy() {
// Cleanup
}
}
Bound services use Binder for IPC:
public class MyBoundService extends Service {
private final IBinder binder = new LocalBinder();
public class LocalBinder extends Binder {
MyBoundService getService() {
return MyBoundService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
These ensure tasks like downloads persist, enhancing user experience without freezing interfaces.
Crafting Content Providers for Data Exposure
Content providers standardize data access across apps, using URIs for queries. Mathias outlines creation: Extend ContentProvider, define URIs via UriMatcher.
CRUD implementation:
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(DBHelper.MY_TABLE);
if (matcher.match(uri) == ITEM) {
qb.appendWhere(DBHelper.ID + "=" + uri.getLastPathSegment());
}
return db.query(qb.getTables(), projection, qb.getWhere(), selectionArgs, null, null, sortOrder);
}
Manifest declaration:
<provider
android:name=".MyProvider"
android:authorities="com.example.provider"
android:exported="true"
android:readPermission="com.example.READ"
android:writePermission="com.example.WRITE" />
This facilitates secure sharing, like contacts or media, promoting modular ecosystems.
Asynchronous Patterns and Resource Management
Asynchrony prevents UI blocks: Handlers for UI updates, AsyncTasks for background work. Pattern: Bind threads to activity lifecycles with flags.
onRetainNonConfigurationInstance() passes objects across rotations (pre-Fragments):
@Override
public Object onRetainNonConfigurationInstance() {
return myThread;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myThread = (MyThread) getLastNonConfigurationInstance();
if (myThread == null) {
myThread = new MyThread();
}
}
Resources: Externalize strings in values/strings.xml for localization; use qualifiers like values-fr for French.
These patterns optimize for device variability, ensuring fluid performance.
Database Integration and Permissions
SQLite via SQLiteOpenHelper manages schemas:
public class DBHelper extends SQLiteOpenHelper {
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + MY_TABLE + " (_id INTEGER PRIMARY KEY, name TEXT);");
}
}
Permissions in manifest control access, balancing security with functionality.
Testing and Project Management Strategies
Unit tests with JUnit; instrumentation via AndroidJUnitRunner. Maven for builds, Hudson/Jenkins for CI.
Implications: These foster reliable apps, mitigating fragmentation. In enterprise mobility, they enable scalable, secure solutions.
Mathias’s methodical breakdown equips developers for real-world challenges.