I just released my first application on the Android Market. It is Voice Dictionary which is a very useful tool for translating words or phrases between 17 different languages (Chinese, English, French, German, Italian, Spanish etc), the Voice Dictionary also supports Text-To-Speech to give you a full experience of pronunciation.
It uses Google Translate service API and eyes-free TTS engine for Android.
Here is a web version Android Market which contains this app's information.
I saw an excellent article in Android Code Source site, it is a Code Style Guide, which is Google Android team asks their developer to respect. Writing code with a good style helps others to read your code, and developer should have a good habit of writing code too.
ListView is a widget which shows items in a vertically scrolling list. I figure out a solution to add horizontal scrolling in a ListView. Here is my new object called MyListView, i used OnGestureListener's onScroll methods to manage the horizontal scrolling.
public class MyListView extends LinearLayout implements OnGestureListener { private GestureDetector mGestureDetector; private ListView mListView;
public MyListView(Context context) { super(context); mGestureDetector = new GestureDetector(this); mGestureDetector.setIsLongpressEnabled(false); mListView = new ListView(context); mListView.setItemsCanFocus(true); String[] items = createStrins(); mListView.setAdapter(new ArrayAdapter(context, android.R.layout.simple_list_item_single_choice, items)); this.addView(mListView, new LinearLayout.LayoutParams(350, LayoutParams.FILL_PARENT)); }
@Override public boolean onDown(MotionEvent arg0) { return false; }
When the orientation of screen changed (portrait to landscape or reciprocate action), the current Activity will be paused->stopped->destroyed and then created->started->resumed with the new configuration (such as language changed, orientation changed..). It means we can detect the orientation on the OnCreate method, to get the current orientation, here is an example:
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { Log.i("info", "landscape"); } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { Log.i("info", "portrait"); }
So you can load the diffrent layout xml file to change your UI or change the layout parameter directly in the code.
1. Generate a keystore using JDK's keytool, here is an example: keytool -genkey -alias youraliasname -keyalg RSA -validity 10000 -keystore yourkeystorename
After executer this line, you should type your keystore password, several personal informations, confimation and type another password for your alias.
2. Sign your application (.apk) with jarsigner, here is an example: jarsigner -keystore yourkeystorepath apkpath youraliasname
Type your keystorepwd to start the signing process.
After these steps, you can install your application on the emulator, or on the device? (I didn't try)
I'm working on the migration my project from M5 to 0.9, i got some exceptions of SQLite which shows "Table/Cursor has not been deactivated or closed" in my database class, i found the problems come from the Cursor. After read the API documents, i understand each opened Cursor should be deactivated and closed after reading its content. Here is an example:
Cursor cursor = sqlite.query(table, null, selection, null, null, null, null); if (cursor.getCount() > 0){ int cursorCount = cursor.getCount(); ArrayList records = new ArrayList(); cursor.moveToFirst(); for (int i=0; i
I created a object of ListView and my own LinearLayout for each row. The first row contains each column's name, so when i refresh this ListView, the first row don't change, so i pass the first row's value to a variable, and use clear() to remove all my ListView's element, and then add the variable in the ListView. I thought what i should do is create new LinearLayout and add them in ListView, with notifyDataSetChanged() method the ListView should be refreshed.
A problem comes, in the "refreshed" ListView there isn't new values, the values displayed are the first row which contains all column's name and the first row of value which should be deleted by the below clear().
I checked the list in the adapter of ListView, all the new values didn't added in the adapter's list. I can't figure out what is going on here.
The solution i found right now is after clear all the items, create a new adapter like adapter = new MyAdapter(this), and don't forget reset this adapter in the ListView.
Vic Gundotra - Engineering VP Allen Hurff, MySpace Steve Horowitz - Android (mobile platform - cool demo) [0:22] Kevin Gibbs - App Engine [0:33] Mark Lucovsky - GData and AJAX API's [0:44] Bruce Johnson - GWT Google Web Toolkit [0.55] David Glazer - Open Social [1:09] Nat Brown, iLike
In theandroid-sdk_m5-rc15_windows, the horizontal scroll bar doesn'twork. Thereis a method setHorizontalScrollBarEnabled( Boolean ) in View class, but there is only vertical scroll bar displayed. It might be a bug in this version.
After several researches of CameraDevice class, i found a good exemple to show how it works. I added a start button to launch the camera, press the middle button to save an image, the image is saved in /data/data/name of package/files/. Press the back button to continue take pictures.
public class CameraTest extends Activity{ private Preview mPreview; private int i = 0;
/** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle);
// Make sure to create a TRANSLUCENT window. This is recquired // for SurfaceView to work. Eventually this'll be done by // the system automatically. getWindow().setFormat(PixelFormat.TRANSLUCENT); mPreview = new Preview(this);
LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL);
Button bt = new Button(this); bt.setText("start"); bt.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { setContentView(mPreview); } });
layout.addView(bt, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); setContentView(layout); }
@Override protected boolean isFullscreenOpaque() { // Our main window is set to translucent, but we know that we will // fill it with opaque data. Tell the system that so it can perform // some important optimizations. return true; }
@Override protected void onResume() { // Because the CameraDevice object is not a shared resource, // it's very important to release it when the activity is paused. super.onResume(); mPreview.resume(); }
@Override protected void onPause() { // Start Preview again when we resume. super.onPause(); mPreview.pause(); }
// Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); mHasSurface = false;
// In this example, we hardcode the size of the preview. In a real // application this should be more dynamic. This guarantees that // the uderlying surface will never change size. mHolder.setFixedSize(320, 240); }
public void resume() { // We do the actual acquisition in a separate thread. Create it now. if (mPreviewThread == null) { mPreviewThread = new PreviewThread(); // If we already have a surface, just start the thread now too. if (mHasSurface == true) { mPreviewThread.start(); } } }
public void pause() { // Stop Preview. if (mPreviewThread != null) { mPreviewThread.requestExitAndWait(); mPreviewThread = null; } }
public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, start our main acquisition thread. mHasSurface = true; if (mPreviewThread != null) { mPreviewThread.start(); } }
public void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when we return. Stop the preview. mHasSurface = false; pause(); }
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // Surface size or format has changed. This should not happen in this // example. }
class PreviewThread extends Thread { private boolean mDone;
PreviewThread() { super(); mDone = false; }
@Override public void run() { // We first open the CameraDevice and configure it. CameraDevice camera = CameraDevice.open(); if (camera != null) { CameraDevice.CaptureParams param = new CameraDevice.CaptureParams(); param.type = 1; // preview param.srcWidth = 1280; param.srcHeight = 960; param.leftPixel = 0; param.topPixel = 0; param.outputWidth = 320; param.outputHeight = 240; param.dataFormat = 2; // RGB_565 camera.setCaptureParams(param); }
// This is our main acquisition thread's loop, we go until // asked to quit. SurfaceHolder holder = mHolder; while (!mDone) { // Lock the surface, this returns a Canvas that can // be used to render into. Canvas canvas = holder.lockCanvas();
// Capture directly into the Surface if (camera != null) { camera.capture(canvas); }
// And finally unlock and post the surface. holder.unlockCanvasAndPost(canvas); }
// Make sure to release the CameraDevice if (camera != null) camera.close(); }
public void requestExitAndWait() { // don't call this from PreviewThread thread or it a guaranteed // deadlock! mDone = true; try { join(); } catch (InterruptedException ex) { } } } }
First you should enter to your emulator directory (for exemple: android-sdk_m5-rc15_windows/tools ) by "cmd", enter "adb shell mem_profiler" to display memory using information.