I used O2J - Objective-C to Java Converter for a similar scenario, and it worked very well.
It will do great with your algorithms / logic without much effort.
It is customizable, so you can add your own translations for your Bluetooth code. You can get by translating the bluetooth method calls directly to java if the APIs work the same but probably not. Itβs best to have an indirect layer in the Objective-C code for bluetooth to make it really easy to implement a specific Android version. For example, create BluetoothHelper.m and BluetoothHelper.java, and the translation will be much smoother.
I used it for projects that used FMDatabase. For the FMDatabase part, we already have FMDatabase / FMResultSet as an indirect layer! I myself implemented FMDatabase / FMResultSet, since the API for sqlite Objective-C (based on sqlite functions) is too different from Android. O2J helped me start translating FMDatabase / FMResultSet, and this is what I ended up with ...
FMDatabase:
public class FMDatabase { private SQLiteDatabase database; private HashMap<String, SQLiteStatement> compiled; public FMDatabase(SQLiteDatabase database) { this.database = database; } public FMResultSet executeQuery_arguments(String sql, Object... args) { synchronized (database) { String[] selectionArgs = objectArgsAsStrings(args); Cursor rawQuery = database.rawQuery(sql, selectionArgs); return new FMResultSet(rawQuery); } } public FMResultSet executeQuery(String sql, Object... args) { synchronized (database) { String[] selectionArgs = objectArgsAsStrings(args); Cursor rawQuery = database.rawQuery(sql, selectionArgs); return new FMResultSet(rawQuery); } } public String debugQuery(String sql, Object...args) { StringBuilder sb = new StringBuilder(); FMResultSet rs = executeQuery(sql, args); rs.setupColumnNames(); HashMap names = rs.columnNameToIndexMap(); Set ks = names.keySet(); for (Object k : ks) { sb.append(k); sb.append("\t"); } sb.append("\n"); while(rs.next()) { for (Object k : ks) { String key = k.toString(); if(rs.getType(key) == Cursor.FIELD_TYPE_STRING) { sb.append(rs.stringForColumn(key)); } else if(rs.getType(key) == Cursor.FIELD_TYPE_INTEGER) { sb.append(rs.longForColumn(key)); } else if(rs.getType(key) == Cursor.FIELD_TYPE_FLOAT) { sb.append(rs.doubleForColumn(key)); } else if(rs.getType(key) == Cursor.FIELD_TYPE_BLOB) { sb.append(rs.stringForColumn(key)); } else { sb.append("<NOT STRING>"); } sb.append("\t"); } sb.append("\n"); } return sb.toString(); } public String[] objectArgsAsStrings(Object... args) { String[] selectionArgs = new String[args.length]; for (int i = 0; i < args.length; i++) { Object o = args[i]; if(o instanceof Date) { selectionArgs[i] = Long.toString(((Date) o).getTime()); } else if(o instanceof Boolean) { selectionArgs[i] = ((Boolean) o).booleanValue() ? "TRUE" : "FALSE"; } else { selectionArgs[i] = args[i] == null ? "" : o.toString(); } } return selectionArgs; } public boolean executeUpdate_arguments(String sql, Object... args) { synchronized (database) { String[] selectionArgs = objectArgsAsStrings(args); database.execSQL(sql, selectionArgs); return true; } } public boolean executeUpdate(String sql, Object... args) { synchronized (database) { SQLiteStatement statement = bindToCachedCompiledStatement(sql, args); statement.execute(); return true; } } private SQLiteStatement bindToCachedCompiledStatement(String sql, Object... args) { HashMap<String, SQLiteStatement> statments = getCompiledStatements(); SQLiteStatement statement = statments.get(sql); if (statement == null) { statement = database.compileStatement(sql); statments.put(sql, statement); } statement.clearBindings();
FMResultSet:
public class FMResultSet { private boolean columnNamesSetup; private HashMap<String, Number> columnNameToIndexMap; private Cursor rawQuery; public FMResultSet(Cursor rawQuery) { this.rawQuery = rawQuery; } public void close() { rawQuery.close(); } public void setupColumnNames() { if (columnNameToIndexMap == null) { this.setColumnNameToIndexMap(new HashMap()); } int columnCount = rawQuery.getColumnCount(); int columnIdx = 0; for (columnIdx = 0; columnIdx < columnCount; columnIdx++) { columnNameToIndexMap.put(rawQuery.getColumnName(columnIdx).toLowerCase(), new Integer(columnIdx)); } columnNamesSetup = true; } public boolean next() { return rawQuery.moveToNext(); } public int columnIndexForName(String columnName) { if (!columnNamesSetup) { this.setupColumnNames(); } columnName = columnName.toLowerCase(); Number n = columnNameToIndexMap.get(columnName); if (n != null) { return NumberValueUtil.intVal(n); } Log.i("StdLog", String.format("Warning: I could not find the column named '%s'.", columnName)); return -1; } public int intForColumn(String columnName) { if (!columnNamesSetup) { this.setupColumnNames(); } int columnIdx = this.columnIndexForName(columnName); if (columnIdx == -1) { return 0; } return intForColumnIndex(columnIdx); } public int intForColumnIndex(int columnIdx) { return rawQuery.getInt(columnIdx); } public long longForColumn(String columnName) { if (!columnNamesSetup) { this.setupColumnNames(); } int columnIdx = this.columnIndexForName(columnName); if (columnIdx == -1) { return 0; } return longForColumnIndex(columnIdx); } public long longForColumnIndex(int columnIdx) { return (long) rawQuery.getLong(columnIdx); } public boolean boolForColumn(String columnName) { return (this.intForColumn(columnName) != 0); } public boolean boolForColumnIndex(int columnIdx) { return (this.intForColumnIndex(columnIdx) != 0); } public double doubleForColumn(String columnName) { if (!columnNamesSetup) { this.setupColumnNames(); } int columnIdx = this.columnIndexForName(columnName); if (columnIdx == -1) { return 0; } return doubleForColumnIndex(columnIdx); } public double doubleForColumnIndex(int columnIdx) { return rawQuery.getDouble(columnIdx); } public String stringForColumnIndex(int columnIdx) { return rawQuery.getString(columnIdx); } public String stringForColumn(String columnName) { if (!columnNamesSetup) { this.setupColumnNames(); } int columnIdx = this.columnIndexForName(columnName); if (columnIdx == -1) { return null; } return this.stringForColumnIndex(columnIdx); } public Date dateForColumn(String columnName) { if (!columnNamesSetup) { this.setupColumnNames(); } int columnIdx = this.columnIndexForName(columnName); if (columnIdx == -1) { return null; } return new Date((this.longForColumn(columnName))); } public Date dateForColumnIndex(int columnIdx) { return new Date((this.longForColumnIndex(columnIdx))); } public byte[] dataForColumn(String columnName) { if (!columnNamesSetup) { this.setupColumnNames(); } int columnIdx = this.columnIndexForName(columnName); if (columnIdx == -1) { return null; } return this.dataForColumnIndex(columnIdx); } public byte[] dataForColumnIndex(int columnIdx) { return rawQuery.getBlob(columnIdx); } public HashMap columnNameToIndexMap() { return columnNameToIndexMap; } public void setColumnNameToIndexMap(HashMap value) { columnNameToIndexMap = value; } @SuppressLint("NewApi") public int getType(String string) { return rawQuery.getType(columnIndexForName(string)); } }