Android Tutorial - Core Class : Application
Application Widget
//src\apt\tutorial\AlarmActivity.java package apt.tutorial; import android.app.Activity; import android.os.Bundle; public class AlarmActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.alarm); } } //src\apt\tutorial\AppWidget.java package apt.tutorial; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.content.Intent; public class AppWidget extends AppWidgetProvider { @Override public void onUpdate(Context ctxt, AppWidgetManager mgr, int[] appWidgetIds) { ctxt.startService(new Intent(ctxt, WidgetService.class)); } } //src\apt\tutorial\DetailForm.java package apt.tutorial; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.RadioGroup; import android.widget.TextView; import android.widget.Toast; public class DetailForm extends Activity { EditText name=null; EditText address=null; EditText notes=null; EditText feed=null; RadioGroup types=null; RestaurantHelper helper=null; String restaurantId=null; TextView location=null; LocationManager locMgr=null; double latitude=0.0d; double longitude=0.0d; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.detail_form); locMgr=(LocationManager)getSystemService(LOCATION_SERVICE); helper=new RestaurantHelper(this); name=(EditText)findViewById(R.id.name); address=(EditText)findViewById(R.id.addr); notes=(EditText)findViewById(R.id.notes); types=(RadioGroup)findViewById(R.id.types); feed=(EditText)findViewById(R.id.feed); location=(TextView)findViewById(R.id.location); restaurantId=getIntent().getStringExtra(LunchList.ID_EXTRA); if (restaurantId!=null) { load(); } } @Override public void onPause() { save(); super.onPause(); } @Override public void onDestroy() { helper.close(); locMgr.removeUpdates(onLocationChange); super.onDestroy(); } @Override public boolean onCreateOptionsMenu(Menu menu) { new MenuInflater(this).inflate(R.menu.details_option, menu); return(super.onCreateOptionsMenu(menu)); } @Override public boolean onPrepareOptionsMenu(Menu menu) { if (restaurantId==null) { menu.findItem(R.id.location).setEnabled(false); menu.findItem(R.id.map).setEnabled(false); } return(super.onPrepareOptionsMenu(menu)); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId()==R.id.feed) { if (isNetworkAvailable()) { Intent i=new Intent(this, FeedActivity.class); i.putExtra(FeedActivity.FEED_URL, feed.getText().toString()); startActivity(i); } else { Toast .makeText(this, "Sorry, the Internet is not available", Toast.LENGTH_LONG) .show(); } return(true); } else if (item.getItemId()==R.id.location) { locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, onLocationChange); return(true); } else if (item.getItemId()==R.id.map) { Intent i=new Intent(this, RestaurantMap.class); i.putExtra(RestaurantMap.EXTRA_LATITUDE, latitude); i.putExtra(RestaurantMap.EXTRA_LONGITUDE, longitude); i.putExtra(RestaurantMap.EXTRA_NAME, name.getText().toString()); startActivity(i); return(true); } return(super.onOptionsItemSelected(item)); } private boolean isNetworkAvailable() { ConnectivityManager cm=(ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE); NetworkInfo info=cm.getActiveNetworkInfo(); return(info!=null); } private void load() { Cursor c=helper.getById(restaurantId); c.moveToFirst(); name.setText(helper.getName(c)); address.setText(helper.getAddress(c)); notes.setText(helper.getNotes(c)); feed.setText(helper.getFeed(c)); if (helper.getType(c).equals("sit_down")) { types.check(R.id.sit_down); } else if (helper.getType(c).equals("take_out")) { types.check(R.id.take_out); } else { types.check(R.id.delivery); } latitude=helper.getLatitude(c); longitude=helper.getLongitude(c); location.setText(String.valueOf(latitude) +", " +String.valueOf(longitude)); c.close(); } private void save() { if (name.getText().toString().length()>0) { String type=null; switch (types.getCheckedRadioButtonId()) { case R.id.sit_down: type="sit_down"; break; case R.id.take_out: type="take_out"; break; default: type="delivery"; break; } if (restaurantId==null) { helper.insert(name.getText().toString(), address.getText().toString(), type, notes.getText().toString(), feed.getText().toString()); } else { helper.update(restaurantId, name.getText().toString(), address.getText().toString(), type, notes.getText().toString(), feed.getText().toString()); } } } LocationListener onLocationChange=new LocationListener() { public void onLocationChanged(Location fix) { helper.updateLocation(restaurantId, fix.getLatitude(), fix.getLongitude()); location.setText(String.valueOf(fix.getLatitude()) +", " +String.valueOf(fix.getLongitude())); locMgr.removeUpdates(onLocationChange); Toast .makeText(DetailForm.this, "Location saved", Toast.LENGTH_LONG) .show(); } public void onProviderDisabled(String provider) { // required for interface, not used } public void onProviderEnabled(String provider) { // required for interface, not used } public void onStatusChanged(String provider, int status, Bundle extras) { // required for interface, not used } }; } //src\apt\tutorial\EditPreferences.java package apt.tutorial; import android.app.Activity; import android.content.ComponentName; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Bundle; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; public class EditPreferences extends PreferenceActivity { SharedPreferences prefs=null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); } @Override public void onResume() { super.onResume(); prefs=PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(onChange); } @Override public void onPause() { prefs.unregisterOnSharedPreferenceChangeListener(onChange); super.onPause(); } SharedPreferences.OnSharedPreferenceChangeListener onChange= new SharedPreferences.OnSharedPreferenceChangeListener() { public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { if ("alarm".equals(key)) { boolean enabled=prefs.getBoolean(key, false); int flag=(enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED); ComponentName component=new ComponentName(EditPreferences.this, OnBootReceiver.class); getPackageManager() .setComponentEnabledSetting(component, flag, PackageManager.DONT_KILL_APP); if (enabled) { OnBootReceiver.setAlarm(EditPreferences.this); } else { OnBootReceiver.cancelAlarm(EditPreferences.this); } } else if ("alarm_time".equals(key)) { OnBootReceiver.cancelAlarm(EditPreferences.this); OnBootReceiver.setAlarm(EditPreferences.this); } } }; } //src\apt\tutorial\FeedActivity.java package apt.tutorial; import android.app.AlertDialog; import android.app.ListActivity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import org.mcsoxford.rss.RSSItem; import org.mcsoxford.rss.RSSFeed; public class FeedActivity extends ListActivity { public static final String FEED_URL="apt.tutorial.FEED_URL"; private InstanceState state=null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); state=(InstanceState)getLastNonConfigurationInstance(); if (state==null) { state=new InstanceState(); state.handler=new FeedHandler(this); Intent i=new Intent(this, FeedService.class); i.putExtra(FeedService.EXTRA_URL, getIntent().getStringExtra(FEED_URL)); i.putExtra(FeedService.EXTRA_MESSENGER, new Messenger(state.handler)); startService(i); } else { if (state.handler!=null) { state.handler.attach(this); } if (state.feed!=null) { setFeed(state.feed); } } } @Override public Object onRetainNonConfigurationInstance() { if (state.handler!=null) { state.handler.detach(); } return(state); } private void setFeed(RSSFeed feed) { state.feed=feed; setListAdapter(new FeedAdapter(feed)); } private void goBlooey(Throwable t) { AlertDialog.Builder builder=new AlertDialog.Builder(this); builder .setTitle("Exception!") .setMessage(t.toString()) .setPositiveButton("OK", null) .show(); } private static class InstanceState { RSSFeed feed=null; FeedHandler handler=null; } private class FeedAdapter extends BaseAdapter { RSSFeed feed=null; FeedAdapter(RSSFeed feed) { super(); this.feed=feed; } @Override public int getCount() { return(feed.getItems().size()); } @Override public Object getItem(int position) { return(feed.getItems().get(position)); } @Override public long getItemId(int position) { return(position); } @Override public View getView(int position, View convertView, ViewGroup parent) { View row=convertView; if (row==null) { LayoutInflater inflater=getLayoutInflater(); row=inflater.inflate(android.R.layout.simple_list_item_1, parent, false); } RSSItem item=(RSSItem)getItem(position); ((TextView)row).setText(item.getTitle()); return(row); } } private static class FeedHandler extends Handler { FeedActivity activity=null; FeedHandler(FeedActivity activity) { attach(activity); } void attach(FeedActivity activity) { this.activity=activity; } void detach() { this.activity=null; } @Override public void handleMessage(Message msg) { if (msg.arg1==RESULT_OK) { activity.setFeed((RSSFeed)msg.obj); } else { activity.goBlooey((Exception)msg.obj); } } }; } //src\apt\tutorial\FeedService.java package apt.tutorial; import android.app.Activity; import android.app.IntentService; import android.content.Intent; import android.os.Message; import android.os.Messenger; import android.util.Log; import org.mcsoxford.rss.RSSItem; import org.mcsoxford.rss.RSSFeed; import org.mcsoxford.rss.RSSReader; public class FeedService extends IntentService { public static final String EXTRA_URL="apt.tutorial.EXTRA_URL"; public static final String EXTRA_MESSENGER="apt.tutorial.EXTRA_MESSENGER"; public FeedService() { super("FeedService"); } @Override public void onHandleIntent(Intent i) { RSSReader reader=new RSSReader(); Messenger messenger=(Messenger)i.getExtras().get(EXTRA_MESSENGER); Message msg=Message.obtain(); try { RSSFeed result=reader.load(i.getStringExtra(EXTRA_URL)); msg.arg1=Activity.RESULT_OK; msg.obj=result; } catch (Exception e) { Log.e("LunchList", "Exception parsing feed", e); msg.arg1=Activity.RESULT_CANCELED; msg.obj=e; } try { messenger.send(msg); } catch (Exception e) { Log.w("LunchList", "Exception sending results to activity", e); } } } //src\apt\tutorial\LunchList.java package apt.tutorial; import android.app.ListActivity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; import android.os.Bundle; import android.preference.PreferenceManager; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.LayoutInflater; import android.widget.AdapterView; import android.widget.CursorAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; public class LunchList extends ListActivity { public final static String ID_EXTRA="apt.tutorial._ID"; Cursor model=null; RestaurantAdapter adapter=null; RestaurantHelper helper=null; SharedPreferences prefs=null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); helper=new RestaurantHelper(this); prefs=PreferenceManager.getDefaultSharedPreferences(this); initList(); prefs.registerOnSharedPreferenceChangeListener(prefListener); } @Override public void onDestroy() { super.onDestroy(); helper.close(); } @Override public void onListItemClick(ListView list, View view, int position, long id) { Intent i=new Intent(LunchList.this, DetailForm.class); i.putExtra(ID_EXTRA, String.valueOf(id)); startActivity(i); } @Override public boolean onCreateOptionsMenu(Menu menu) { new MenuInflater(this).inflate(R.menu.option, menu); return(super.onCreateOptionsMenu(menu)); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId()==R.id.add) { startActivity(new Intent(LunchList.this, DetailForm.class)); return(true); } else if (item.getItemId()==R.id.prefs) { startActivity(new Intent(this, EditPreferences.class)); return(true); } return(super.onOptionsItemSelected(item)); } private void initList() { if (model!=null) { stopManagingCursor(model); model.close(); } model=helper.getAll(prefs.getString("sort_order", "name")); startManagingCursor(model); adapter=new RestaurantAdapter(model); setListAdapter(adapter); } private SharedPreferences.OnSharedPreferenceChangeListener prefListener= new SharedPreferences.OnSharedPreferenceChangeListener() { public void onSharedPreferenceChanged(SharedPreferences sharedPrefs, String key) { if (key.equals("sort_order")) { initList(); } } }; class RestaurantAdapter extends CursorAdapter { RestaurantAdapter(Cursor c) { super(LunchList.this, c); } @Override public void bindView(View row, Context ctxt, Cursor c) { RestaurantHolder holder=(RestaurantHolder)row.getTag(); holder.populateFrom(c, helper); } @Override public View newView(Context ctxt, Cursor c, ViewGroup parent) { LayoutInflater inflater=getLayoutInflater(); View row=inflater.inflate(R.layout.row, parent, false); RestaurantHolder holder=new RestaurantHolder(row); row.setTag(holder); return(row); } } static class RestaurantHolder { private TextView name=null; private TextView address=null; private ImageView icon=null; RestaurantHolder(View row) { name=(TextView)row.findViewById(R.id.title); address=(TextView)row.findViewById(R.id.address); icon=(ImageView)row.findViewById(R.id.icon); } void populateFrom(Cursor c, RestaurantHelper helper) { name.setText(helper.getName(c)); address.setText(helper.getAddress(c)); if (helper.getType(c).equals("sit_down")) { icon.setImageResource(R.drawable.ball_red); } else if (helper.getType(c).equals("take_out")) { icon.setImageResource(R.drawable.ball_yellow); } else { icon.setImageResource(R.drawable.ball_green); } } } } //src\apt\tutorial\OnAlarmReceiver.java package apt.tutorial; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; public class OnAlarmReceiver extends BroadcastReceiver { private static final int NOTIFY_ME_ID=1337; @Override public void onReceive(Context ctxt, Intent intent) { SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(ctxt); boolean useNotification=prefs.getBoolean("use_notification", true); if (useNotification) { NotificationManager mgr= (NotificationManager)ctxt.getSystemService(Context.NOTIFICATION_SERVICE); Notification note=new Notification(R.drawable.stat_notify_chat, "It's time for lunch!", System.currentTimeMillis()); PendingIntent i=PendingIntent.getActivity(ctxt, 0, new Intent(ctxt, AlarmActivity.class), 0); note.setLatestEventInfo(ctxt, "LunchList", "It's time for lunch! Aren't you hungry?", i); note.flags|=Notification.FLAG_AUTO_CANCEL; mgr.notify(NOTIFY_ME_ID, note); } else { Intent i=new Intent(ctxt, AlarmActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ctxt.startActivity(i); } } } //src\apt\tutorial\OnBootReceiver.java package apt.tutorial; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; import java.util.Calendar; public class OnBootReceiver extends BroadcastReceiver { public static void setAlarm(Context ctxt) { AlarmManager mgr=(AlarmManager)ctxt.getSystemService(Context.ALARM_SERVICE); Calendar cal=Calendar.getInstance(); SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(ctxt); String time=prefs.getString("alarm_time", "12:00"); cal.set(Calendar.HOUR_OF_DAY, TimePreference.getHour(time)); cal.set(Calendar.MINUTE, TimePreference.getMinute(time)); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); if (cal.getTimeInMillis()<System.currentTimeMillis()) { cal.add(Calendar.DAY_OF_YEAR, 1); } android.util.Log.e("***OnBootReceiver", android.text.format.DateFormat.format("MM/dd/yy h:mmaa", cal).toString()); mgr.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, getPendingIntent(ctxt)); } public static void cancelAlarm(Context ctxt) { AlarmManager mgr=(AlarmManager)ctxt.getSystemService(Context.ALARM_SERVICE); mgr.cancel(getPendingIntent(ctxt)); } private static PendingIntent getPendingIntent(Context ctxt) { Intent i=new Intent(ctxt, OnAlarmReceiver.class); return(PendingIntent.getBroadcast(ctxt, 0, i, 0)); } @Override public void onReceive(Context ctxt, Intent intent) { android.util.Log.e("****OnBootReceiver", "got here"); setAlarm(ctxt); } } //src\apt\tutorial\RestaurantHelper.java package apt.tutorial; import android.content.Context; import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; class RestaurantHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME="lunchlist.db"; private static final int SCHEMA_VERSION=3; public RestaurantHelper(Context context) { super(context, DATABASE_NAME, null, SCHEMA_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE restaurants (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, address TEXT, type TEXT, notes TEXT, feed TEXT, lat REAL, lon REAL);"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion<2) { db.execSQL("ALTER TABLE restaurants ADD COLUMN feed TEXT"); } if (oldVersion<3) { db.execSQL("ALTER TABLE restaurants ADD COLUMN lat REAL"); db.execSQL("ALTER TABLE restaurants ADD COLUMN lon REAL"); } } public Cursor getAll(String orderBy) { return(getReadableDatabase() .rawQuery("SELECT _id, name, address, type, notes, lat, lon FROM restaurants ORDER BY "+orderBy, null)); } public Cursor getById(String id) { String[] args={id}; return(getReadableDatabase() .rawQuery("SELECT _id, name, address, type, notes, feed, lat, lon FROM restaurants WHERE _ID=?", args)); } public void insert(String name, String address, String type, String notes, String feed) { ContentValues cv=new ContentValues(); cv.put("name", name); cv.put("address", address); cv.put("type", type); cv.put("notes", notes); cv.put("feed", feed); getWritableDatabase().insert("restaurants", "name", cv); } public void update(String id, String name, String address, String type, String notes, String feed) { ContentValues cv=new ContentValues(); String[] args={id}; cv.put("name", name); cv.put("address", address); cv.put("type", type); cv.put("notes", notes); cv.put("feed", feed); getWritableDatabase().update("restaurants", cv, "_ID=?", args); } public void updateLocation(String id, double lat, double lon) { ContentValues cv=new ContentValues(); String[] args={id}; cv.put("lat", lat); cv.put("lon", lon); getWritableDatabase().update("restaurants", cv, "_ID=?", args); } public String getName(Cursor c) { return(c.getString(1)); } public String getAddress(Cursor c) { return(c.getString(2)); } public String getType(Cursor c) { return(c.getString(3)); } public String getNotes(Cursor c) { return(c.getString(4)); } public String getFeed(Cursor c) { return(c.getString(5)); } public double getLatitude(Cursor c) { return(c.getDouble(6)); } public double getLongitude(Cursor c) { return(c.getDouble(7)); } } //src\apt\tutorial\RestaurantMap.java package apt.tutorial; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.widget.Toast; import com.google.android.maps.GeoPoint; import com.google.android.maps.ItemizedOverlay; import com.google.android.maps.MapActivity; import com.google.android.maps.MapController; import com.google.android.maps.MapView; import com.google.android.maps.OverlayItem; public class RestaurantMap extends MapActivity { public static final String EXTRA_LATITUDE="apt.tutorial.EXTRA_LATITUDE"; public static final String EXTRA_LONGITUDE="apt.tutorial.EXTRA_LONGITUDE"; public static final String EXTRA_NAME="apt.tutorial.EXTRA_NAME"; private MapView map=null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map); double lat=getIntent().getDoubleExtra(EXTRA_LATITUDE, 0); double lon=getIntent().getDoubleExtra(EXTRA_LONGITUDE, 0); map=(MapView)findViewById(R.id.map); map.getController().setZoom(17); GeoPoint status=new GeoPoint((int)(lat*1000000.0), (int)(lon*1000000.0)); map.getController().setCenter(status); map.setBuiltInZoomControls(true); Drawable marker=getResources().getDrawable(R.drawable.marker); marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight()); map .getOverlays() .add(new RestaurantOverlay(marker, status, getIntent().getStringExtra(EXTRA_NAME))); } @Override protected boolean isRouteDisplayed() { return(false); } private class RestaurantOverlay extends ItemizedOverlay<OverlayItem> { private OverlayItem item=null; public RestaurantOverlay(Drawable marker, GeoPoint point, String name) { super(marker); boundCenterBottom(marker); item=new OverlayItem(point, name, name); populate(); } @Override protected OverlayItem createItem(int i) { return(item); } @Override protected boolean onTap(int i) { Toast.makeText(RestaurantMap.this, item.getSnippet(), Toast.LENGTH_SHORT).show(); return(true); } @Override public int size() { return(1); } } } //src\apt\tutorial\TimePreference.java package apt.tutorial; import android.content.Context; import android.content.res.TypedArray; import android.preference.DialogPreference; import android.util.AttributeSet; import android.view.View; import android.widget.TimePicker; public class TimePreference extends DialogPreference { private int lastHour=0; private int lastMinute=0; private TimePicker picker=null; public static int getHour(String time) { String[] pieces=time.split(":"); return(Integer.parseInt(pieces[0])); } public static int getMinute(String time) { String[] pieces=time.split(":"); return(Integer.parseInt(pieces[1])); } public TimePreference(Context ctxt, AttributeSet attrs) { super(ctxt, attrs); setPositiveButtonText("Set"); setNegativeButtonText("Cancel"); } @Override protected View onCreateDialogView() { picker=new TimePicker(getContext()); return(picker); } @Override protected void onBindDialogView(View v) { super.onBindDialogView(v); picker.setCurrentHour(lastHour); picker.setCurrentMinute(lastMinute); } @Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); if (positiveResult) { lastHour=picker.getCurrentHour(); lastMinute=picker.getCurrentMinute(); String time=String.valueOf(lastHour)+":"+String.valueOf(lastMinute); if (callChangeListener(time)) { persistString(time); } } } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return(a.getString(index)); } @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { String time=null; if (restoreValue) { if (defaultValue==null) { time=getPersistedString("00:00"); } else { time=getPersistedString(defaultValue.toString()); } } else { time=defaultValue.toString(); } lastHour=getHour(time); lastMinute=getMinute(time); } } //src\apt\tutorial\WidgetService.java package apt.tutorial; import android.app.IntentService; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.widget.RemoteViews; public class WidgetService extends IntentService { public WidgetService() { super("WidgetService"); } @Override public void onHandleIntent(Intent intent) { ComponentName me=new ComponentName(this, AppWidget.class); RemoteViews updateViews=new RemoteViews("apt.tutorial", R.layout.widget); RestaurantHelper helper=new RestaurantHelper(this); AppWidgetManager mgr=AppWidgetManager.getInstance(this); try { Cursor c=helper .getReadableDatabase() .rawQuery("SELECT COUNT(*) FROM restaurants", null); c.moveToFirst(); int count=c.getInt(0); c.close(); if (count>0) { int offset=(int)(count*Math.random()); String args[]={String.valueOf(offset)}; c=helper .getReadableDatabase() .rawQuery("SELECT _ID, name FROM restaurants LIMIT 1 OFFSET ?", args); c.moveToFirst(); updateViews.setTextViewText(R.id.name, c.getString(1)); Intent i=new Intent(this, DetailForm.class); i.putExtra(LunchList.ID_EXTRA, c.getString(0)); PendingIntent pi=PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT); updateViews.setOnClickPendingIntent(R.id.name, pi); c.close(); } else { updateViews.setTextViewText(R.id.title, this.getString(R.string.empty)); } } finally { helper.close(); } Intent i=new Intent(this, WidgetService.class); PendingIntent pi=PendingIntent.getService(this, 0, i, 0); updateViews.setOnClickPendingIntent(R.id.next, pi); mgr.updateAppWidget(me, updateViews); } } // //res\xml\preferences.xml <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <ListPreference android:key="sort_order" android:title="Sort Order" android:summary="Choose the order the list uses" android:entries="@array/sort_names" android:entryValues="@array/sort_clauses" android:dialogTitle="Choose a sort order" /> <CheckBoxPreference android:key="alarm" android:title="Sound a Lunch Alarm" android:summary="Check if you want to know when it is time for lunch" /> <apt.tutorial.TimePreference android:key="alarm_time" android:title="Lunch Alarm Time" android:defaultValue="12:00" android:summary="Set your desired time for the lunch alarm" android:dependency="alarm" /> <CheckBoxPreference android:key="use_notification" android:title="Use a Notification" android:defaultValue="true" android:summary="Check if you want a status bar icon at lunchtime, or uncheck for a full-screen notice" android:dependency="alarm" /> </PreferenceScreen> //res\xml\widget_provider.xml <?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="300dip" android:minHeight="79dip" android:updatePeriodMillis="1800000" android:initialLayout="@layout/widget" /> // //res\values\arrays.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="sort_names"> <item>By Name, Ascending</item> <item>By Name, Descending</item> <item>By Type</item> <item>By Address, Ascending</item> <item>By Address, Descending</item> </string-array> <string-array name="sort_clauses"> <item>name ASC</item> <item>name DESC</item> <item>type, name ASC</item> <item>address ASC</item> <item>address DESC</item> </string-array> </resources> //res\values\strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">LunchList</string> <string name="empty">No restaurants!</string> </resources> // //res\menu\details_option.xml <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/feed" android:title="RSS Feed" android:icon="@drawable/ic_menu_friendslist" /> <item android:id="@+id/location" android:title="Save Location" android:icon="@drawable/ic_menu_compass" /> <item android:id="@+id/map" android:title="Show on Map" android:icon="@drawable/ic_menu_mapmode" /> </menu> //res\menu\option.xml <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/add" android:title="Add" android:icon="@drawable/ic_menu_add" /> <item android:id="@+id/prefs" android:title="Settings" android:icon="@drawable/ic_menu_preferences" /> </menu> // //res\layout-land\detail_form.xml <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="2" > <TableRow> <TextView android:text="Name:" /> <EditText android:id="@+id/name" android:layout_span="2" /> </TableRow> <TableRow> <TextView android:text="Address:" /> <EditText android:id="@+id/addr" android:layout_span="2" /> </TableRow> <TableRow> <TextView android:text="Type:" /> <RadioGroup android:id="@+id/types"> <RadioButton android:id="@+id/take_out" android:text="Take-Out" /> <RadioButton android:id="@+id/sit_down" android:text="Sit-Down" /> <RadioButton android:id="@+id/delivery" android:text="Delivery" /> </RadioGroup> <LinearLayout android:orientation="vertical"> <EditText android:id="@+id/notes" android:singleLine="false" android:gravity="top" android:lines="2" android:scrollHorizontally="false" android:maxLines="2" android:maxWidth="140sp" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="Notes" /> <EditText android:id="@+id/feed" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="Feed URL" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:text="Location:" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/location" android:text="(not set)" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout> </TableRow> </TableLayout> // //res\layout\alarm.xml <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="It's time for lunch!" android:textSize="30sp" android:textStyle="bold" /> //res\layout\detail_form.xml <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="1" > <TableRow> <TextView android:text="Name:" /> <EditText android:id="@+id/name" /> </TableRow> <TableRow> <TextView android:text="Address:" /> <EditText android:id="@+id/addr" /> </TableRow> <TableRow> <TextView android:text="Type:" /> <RadioGroup android:id="@+id/types"> <RadioButton android:id="@+id/take_out" android:text="Take-Out" /> <RadioButton android:id="@+id/sit_down" android:text="Sit-Down" /> <RadioButton android:id="@+id/delivery" android:text="Delivery" /> </RadioGroup> </TableRow> <TableRow> <TextView android:text="Location:" /> <TextView android:id="@+id/location" android:text="(not set)" /> </TableRow> <EditText android:id="@+id/notes" android:singleLine="false" android:gravity="top" android:lines="2" android:scrollHorizontally="false" android:maxLines="2" android:maxWidth="200sp" android:layout_span="2" android:hint="Notes" android:layout_marginTop="4dip" /> <EditText android:id="@+id/feed" android:layout_span="2" android:hint="Feed URL" /> </TableLayout> //res\layout\main.xml <?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" /> //res\layout\map.xml <?xml version="1.0" encoding="utf-8"?> <com.google.android.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:layout_width="fill_parent" android:layout_height="fill_parent" android:apiKey="00yHj0k7_7vxbuQ9zwyXI4bNMJrAjYrJ9KKHgbQ" android:clickable="true" /> //res\layout\row.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="4dip" > <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentTop="true" android:layout_alignParentBottom="true" android:layout_marginRight="4dip" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:textStyle="bold" android:singleLine="true" android:ellipsize="end" /> <TextView android:id="@+id/address" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:singleLine="true" android:ellipsize="end" /> </LinearLayout> </LinearLayout> //res\layout\widget.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/widget_frame" > <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_alignParentLeft="true" android:layout_toLeftOf="@+id/next" android:textSize="10pt" android:textColor="#FFFFFFFF" /> <ImageButton android:id="@id/next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:src="@drawable/ff" /> </RelativeLayout>
extends Application
package app.test; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.params.ConnManagerParams; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.BasicResponseHandler; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; import android.app.Activity; import android.app.Application; import android.os.Bundle; class MyHttpClient extends Application { private HttpClient httpClient; @Override public void onCreate() { super.onCreate(); httpClient = createHttpClient(); } private HttpClient createHttpClient() { HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params,HTTP.DEFAULT_CONTENT_CHARSET); HttpProtocolParams.setUseExpectContinue(params, true); ConnManagerParams.setTimeout(params, 1000); HttpConnectionParams.setConnectionTimeout(params, 5000); HttpConnectionParams.setSoTimeout(params, 10000); SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory .getSocketFactory(), 80)); schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ClientConnectionManager conMgr = new ThreadSafeClientConnManager( params, schReg); return new DefaultHttpClient(conMgr, params); } public HttpClient getHttpClient() { if (httpClient == null) httpClient = createHttpClient(); return httpClient; } @Override public void onLowMemory() { super.onLowMemory(); shutdownHttpClient(); } @Override public void onTerminate() { super.onTerminate(); shutdownHttpClient(); } private void shutdownHttpClient() { if (httpClient != null && httpClient.getConnectionManager() != null) { httpClient.getConnectionManager().shutdown(); httpClient = null; } } } public class Test extends Activity { private MyHttpClient app; private HttpClient httpClient; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); app = (MyHttpClient) this.getApplication(); httpClient = app.getHttpClient(); getHttpContent(); } public void getHttpContent() { try { HttpGet request = new HttpGet("http://www.google.com/"); HttpParams params = request.getParams(); HttpConnectionParams.setSoTimeout(params, 60000); // 1 minute request.setParams(params); String page = httpClient.execute(request, new BasicResponseHandler()); System.out.println(page); } catch (Exception e) { e.printStackTrace(); } } }
Loads the list of installed applications in mApplications.
package com.example.android.home; import android.content.ComponentName; import android.content.Intent; import android.graphics.drawable.Drawable; /** * Represents a launchable application. An application is made of a name (or title), an intent * and an icon. */ class ApplicationInfo { /** * The application name. */ CharSequence title; /** * The intent used to start the application. */ Intent intent; /** * The application icon. */ Drawable icon; /** * When set to true, indicates that the icon has been resized. */ boolean filtered; /** * Creates the application intent based on a component name and various launch flags. * * @param className the class name of the component representing the intent * @param launchFlags the launch flags */ final void setActivity(ComponentName className, int launchFlags) { intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setComponent(className); intent.setFlags(launchFlags); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof ApplicationInfo)) { return false; } ApplicationInfo that = (ApplicationInfo) o; return title.equals(that.title) && intent.getComponent().getClassName().equals( that.intent.getComponent().getClassName()); } @Override public int hashCode() { int result; result = (title != null ? title.hashCode() : 0); final String name = intent.getComponent().getClassName(); result = 31 * result + (name != null ? name.hashCode() : 0); return result; } } //src\com\example\android\home\ApplicationsStackLayout.java package com.example.android.home; import android.content.Context; import android.content.Intent; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.LayoutInflater; import android.widget.TextView; import java.util.List; public class ApplicationsStackLayout extends ViewGroup implements View.OnClickListener { public static final int HORIZONTAL = 0; public static final int VERTICAL = 1; private View mButton; private LayoutInflater mInflater; private int mFavoritesEnd; private int mFavoritesStart; private List<ApplicationInfo> mFavorites; private List<ApplicationInfo> mRecents; private int mOrientation = VERTICAL; private int mMarginLeft; private int mMarginTop; private int mMarginRight; private int mMarginBottom; private Rect mDrawRect = new Rect(); private Drawable mBackground; private int mIconSize; public ApplicationsStackLayout(Context context) { super(context); initLayout(); } public ApplicationsStackLayout(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ApplicationsStackLayout); mOrientation = a.getInt(R.styleable.ApplicationsStackLayout_stackOrientation, VERTICAL); mMarginLeft = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginLeft, 0); mMarginTop = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginTop, 0); mMarginRight = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginRight, 0); mMarginBottom = a.getDimensionPixelSize(R.styleable.ApplicationsStackLayout_marginBottom, 0); a.recycle(); mIconSize = 42; //(int) getResources().getDimension(android.R.dimen.app_icon_size); initLayout(); } private void initLayout() { mInflater = LayoutInflater.from(getContext()); mButton = mInflater.inflate(R.layout.all_applications_button, this, false); addView(mButton); mBackground = getBackground(); setBackgroundDrawable(null); setWillNotDraw(false); } /** * Return the current orientation, either VERTICAL (default) or HORIZONTAL. * * @return the stack orientation */ public int getOrientation() { return mOrientation; } @Override protected void onDraw(Canvas canvas) { final Drawable background = mBackground; final int right = getWidth(); final int bottom = getHeight(); // Draw behind recents if (mOrientation == VERTICAL) { mDrawRect.set(0, 0, right, mFavoritesStart); } else { mDrawRect.set(0, 0, mFavoritesStart, bottom); } background.setBounds(mDrawRect); background.draw(canvas); // Draw behind favorites if (mFavoritesStart > -1) { if (mOrientation == VERTICAL) { mDrawRect.set(0, mFavoritesStart, right, mFavoritesEnd); } else { mDrawRect.set(mFavoritesStart, 0, mFavoritesEnd, bottom); } background.setBounds(mDrawRect); background.draw(canvas); } super.onDraw(canvas); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); final int widthMode = MeasureSpec.getMode(widthMeasureSpec); final int widthSize = MeasureSpec.getSize(widthMeasureSpec); final int heightMode = MeasureSpec.getMode(heightMeasureSpec); final int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) { throw new IllegalStateException("ApplicationsStackLayout can only be used with " + "measure spec mode=EXACTLY"); } setMeasuredDimension(widthSize, heightSize); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { removeAllApplications(); LayoutParams layoutParams = mButton.getLayoutParams(); final int widthSpec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY); final int heightSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY); mButton.measure(widthSpec, heightSpec); if (mOrientation == VERTICAL) { layoutVertical(); } else { layoutHorizontal(); } } private void layoutVertical() { int childLeft = 0; int childTop = getHeight(); int childWidth = mButton.getMeasuredWidth(); int childHeight = mButton.getMeasuredHeight(); childTop -= childHeight + mMarginBottom; mButton.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); childTop -= mMarginTop; mFavoritesEnd = childTop - mMarginBottom; int oldChildTop = childTop; childTop = stackApplications(mFavorites, childLeft, childTop); if (childTop != oldChildTop) { mFavoritesStart = childTop + mMarginTop; } else { mFavoritesStart = -1; } stackApplications(mRecents, childLeft, childTop); } private void layoutHorizontal() { int childLeft = getWidth(); int childTop = 0; int childWidth = mButton.getMeasuredWidth(); int childHeight = mButton.getMeasuredHeight(); childLeft -= childWidth; mButton.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); childLeft -= mMarginLeft; mFavoritesEnd = childLeft - mMarginRight; int oldChildLeft = childLeft; childLeft = stackApplications(mFavorites, childLeft, childTop); if (childLeft != oldChildLeft) { mFavoritesStart = childLeft + mMarginLeft; } else { mFavoritesStart = -1; } stackApplications(mRecents, childLeft, childTop); } private int stackApplications(List<ApplicationInfo> applications, int childLeft, int childTop) { LayoutParams layoutParams; int widthSpec; int heightSpec; int childWidth; int childHeight; final boolean isVertical = mOrientation == VERTICAL; final int count = applications.size(); for (int i = count - 1; i >= 0; i--) { final ApplicationInfo info = applications.get(i); final View view = createApplicationIcon(mInflater, this, info); layoutParams = view.getLayoutParams(); widthSpec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY); heightSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY); view.measure(widthSpec, heightSpec); childWidth = view.getMeasuredWidth(); childHeight = view.getMeasuredHeight(); if (isVertical) { childTop -= childHeight + mMarginBottom; if (childTop < 0) { childTop += childHeight + mMarginBottom; break; } } else { childLeft -= childWidth + mMarginRight; if (childLeft < 0) { childLeft += childWidth + mMarginRight; break; } } addViewInLayout(view, -1, layoutParams); view.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); if (isVertical) { childTop -= mMarginTop; } else { childLeft -= mMarginLeft; } } return isVertical ? childTop : childLeft; } private void removeAllApplications() { final int count = getChildCount(); for (int i = count - 1; i >= 0; i--) { final View view = getChildAt(i); if (view != mButton) { removeViewAt(i); } } } private View createApplicationIcon(LayoutInflater inflater, ViewGroup group, ApplicationInfo info) { TextView textView = (TextView) inflater.inflate(R.layout.favorite, group, false); info.icon.setBounds(0, 0, mIconSize, mIconSize); textView.setCompoundDrawables(null, info.icon, null, null); textView.setText(info.title); textView.setTag(info.intent); textView.setOnClickListener(this); return textView; } /** * Sets the list of favorites. * * @param applications the applications to put in the favorites area */ public void setFavorites(List<ApplicationInfo> applications) { mFavorites = applications; requestLayout(); } /** * Sets the list of recents. * * @param applications the applications to put in the recents area */ public void setRecents(List<ApplicationInfo> applications) { mRecents = applications; requestLayout(); } public void onClick(View v) { getContext().startActivity((Intent) v.getTag()); } } //src\com\example\android\home\Home.java package com.example.android.home; import android.app.Activity; import android.app.ActivityManager; import android.app.SearchManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PaintFlagsDrawFilter; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.ColorFilter; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.PaintDrawable; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.util.Xml; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.LayoutAnimationController; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.GridView; import android.widget.TextView; import java.io.IOException; import java.io.FileReader; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; public class Home extends Activity { /** * Tag used for logging errors. */ private static final String LOG_TAG = "Home"; /** * Keys during freeze/thaw. */ private static final String KEY_SAVE_GRID_OPENED = "grid.opened"; private static final String DEFAULT_FAVORITES_PATH = "etc/favorites.xml"; private static final String TAG_FAVORITES = "favorites"; private static final String TAG_FAVORITE = "favorite"; private static final String TAG_PACKAGE = "package"; private static final String TAG_CLASS = "class"; // Identifiers for option menu items private static final int MENU_WALLPAPER_SETTINGS = Menu.FIRST + 1; private static final int MENU_SEARCH = MENU_WALLPAPER_SETTINGS + 1; private static final int MENU_SETTINGS = MENU_SEARCH + 1; /** * Maximum number of recent tasks to query. */ private static final int MAX_RECENT_TASKS = 20; private static boolean mWallpaperChecked; private static ArrayList<ApplicationInfo> mApplications; private static LinkedList<ApplicationInfo> mFavorites; private final BroadcastReceiver mWallpaperReceiver = new WallpaperIntentReceiver(); private final BroadcastReceiver mApplicationsReceiver = new ApplicationsIntentReceiver(); private GridView mGrid; private LayoutAnimationController mShowLayoutAnimation; private LayoutAnimationController mHideLayoutAnimation; private boolean mBlockAnimation; private boolean mHomeDown; private boolean mBackDown; private View mShowApplications; private CheckBox mShowApplicationsCheck; private ApplicationsStackLayout mApplicationsStack; private Animation mGridEntry; private Animation mGridExit; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); setContentView(R.layout.home); registerIntentReceivers(); setDefaultWallpaper(); loadApplications(true); bindApplications(); bindFavorites(true); bindRecents(); bindButtons(); mGridEntry = AnimationUtils.loadAnimation(this, R.anim.grid_entry); mGridExit = AnimationUtils.loadAnimation(this, R.anim.grid_exit); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); // Close the menu if (Intent.ACTION_MAIN.equals(intent.getAction())) { getWindow().closeAllPanels(); } } @Override public void onDestroy() { super.onDestroy(); // Remove the callback for the cached drawables or we leak // the previous Home screen on orientation change final int count = mApplications.size(); for (int i = 0; i < count; i++) { mApplications.get(i).icon.setCallback(null); } unregisterReceiver(mWallpaperReceiver); unregisterReceiver(mApplicationsReceiver); } @Override protected void onResume() { super.onResume(); bindRecents(); } @Override protected void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); final boolean opened = state.getBoolean(KEY_SAVE_GRID_OPENED, false); if (opened) { showApplications(false); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(KEY_SAVE_GRID_OPENED, mGrid.getVisibility() == View.VISIBLE); } /** * Registers various intent receivers. The current implementation registers * only a wallpaper intent receiver to let other applications change the * wallpaper. */ private void registerIntentReceivers() { IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); registerReceiver(mWallpaperReceiver, filter); filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addDataScheme("package"); registerReceiver(mApplicationsReceiver, filter); } /** * Creates a new appplications adapter for the grid view and registers it. */ private void bindApplications() { if (mGrid == null) { mGrid = (GridView) findViewById(R.id.all_apps); } mGrid.setAdapter(new ApplicationsAdapter(this, mApplications)); mGrid.setSelection(0); if (mApplicationsStack == null) { mApplicationsStack = (ApplicationsStackLayout) findViewById(R.id.faves_and_recents); } } /** * Binds actions to the various buttons. */ private void bindButtons() { mShowApplications = findViewById(R.id.show_all_apps); mShowApplications.setOnClickListener(new ShowApplications()); mShowApplicationsCheck = (CheckBox) findViewById(R.id.show_all_apps_check); mGrid.setOnItemClickListener(new ApplicationLauncher()); } /** * When no wallpaper was manually set, a default wallpaper is used instead. */ private void setDefaultWallpaper() { if (!mWallpaperChecked) { Drawable wallpaper = peekWallpaper(); if (wallpaper == null) { try { clearWallpaper(); } catch (IOException e) { Log.e(LOG_TAG, "Failed to clear wallpaper " + e); } } else { getWindow().setBackgroundDrawable(new ClippedDrawable(wallpaper)); } mWallpaperChecked = true; } } /** * Refreshes the favorite applications stacked over the all apps button. * The number of favorites depends on the user. */ private void bindFavorites(boolean isLaunching) { if (!isLaunching || mFavorites == null) { if (mFavorites == null) { mFavorites = new LinkedList<ApplicationInfo>(); } else { mFavorites.clear(); } mApplicationsStack.setFavorites(mFavorites); FileReader favReader; // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". final File favFile = new File(Environment.getRootDirectory(), DEFAULT_FAVORITES_PATH); try { favReader = new FileReader(favFile); } catch (FileNotFoundException e) { Log.e(LOG_TAG, "Couldn't find or open favorites file " + favFile); return; } final Intent intent = new Intent(Intent.ACTION_MAIN, null); intent.addCategory(Intent.CATEGORY_LAUNCHER); final PackageManager packageManager = getPackageManager(); try { final XmlPullParser parser = Xml.newPullParser(); parser.setInput(favReader); beginDocument(parser, TAG_FAVORITES); ApplicationInfo info; while (true) { nextElement(parser); String name = parser.getName(); if (!TAG_FAVORITE.equals(name)) { break; } final String favoritePackage = parser.getAttributeValue(null, TAG_PACKAGE); final String favoriteClass = parser.getAttributeValue(null, TAG_CLASS); final ComponentName cn = new ComponentName(favoritePackage, favoriteClass); intent.setComponent(cn); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); info = getApplicationInfo(packageManager, intent); if (info != null) { info.intent = intent; mFavorites.addFirst(info); } } } catch (XmlPullParserException e) { Log.w(LOG_TAG, "Got exception parsing favorites.", e); } catch (IOException e) { Log.w(LOG_TAG, "Got exception parsing favorites.", e); } } mApplicationsStack.setFavorites(mFavorites); } private static void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException { int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // Empty } if (type != XmlPullParser.START_TAG) { throw new XmlPullParserException("No start tag found"); } if (!parser.getName().equals(firstElementName)) { throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + ", expected " + firstElementName); } } private static void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException { int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // Empty } } /** * Refreshes the recently launched applications stacked over the favorites. The number * of recents depends on how many favorites are present. */ private void bindRecents() { final PackageManager manager = getPackageManager(); final ActivityManager tasksManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); final List<ActivityManager.RecentTaskInfo> recentTasks = tasksManager.getRecentTasks( MAX_RECENT_TASKS, 0); final int count = recentTasks.size(); final ArrayList<ApplicationInfo> recents = new ArrayList<ApplicationInfo>(); for (int i = count - 1; i >= 0; i--) { final Intent intent = recentTasks.get(i).baseIntent; if (Intent.ACTION_MAIN.equals(intent.getAction()) && !intent.hasCategory(Intent.CATEGORY_HOME)) { ApplicationInfo info = getApplicationInfo(manager, intent); if (info != null) { info.intent = intent; if (!mFavorites.contains(info)) { recents.add(info); } } } } mApplicationsStack.setRecents(recents); } private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent) { final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0); if (resolveInfo == null) { return null; } final ApplicationInfo info = new ApplicationInfo(); final ActivityInfo activityInfo = resolveInfo.activityInfo; info.icon = activityInfo.loadIcon(manager); if (info.title == null || info.title.length() == 0) { info.title = activityInfo.loadLabel(manager); } if (info.title == null) { info.title = ""; } return info; } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (!hasFocus) { mBackDown = mHomeDown = false; } } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_BACK: mBackDown = true; return true; case KeyEvent.KEYCODE_HOME: mHomeDown = true; return true; } } else if (event.getAction() == KeyEvent.ACTION_UP) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_BACK: if (!event.isCanceled()) { // Do BACK behavior. } mBackDown = true; return true; case KeyEvent.KEYCODE_HOME: if (!event.isCanceled()) { // Do HOME behavior. } mHomeDown = true; return true; } } return super.dispatchKeyEvent(event); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0, MENU_WALLPAPER_SETTINGS, 0, R.string.menu_wallpaper) .setIcon(android.R.drawable.ic_menu_gallery) .setAlphabeticShortcut('W'); menu.add(0, MENU_SEARCH, 0, R.string.menu_search) .setIcon(android.R.drawable.ic_search_category_default) .setAlphabeticShortcut(SearchManager.MENU_KEY); menu.add(0, MENU_SETTINGS, 0, R.string.menu_settings) .setIcon(android.R.drawable.ic_menu_preferences) .setIntent(new Intent(android.provider.Settings.ACTION_SETTINGS)); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_WALLPAPER_SETTINGS: startWallpaper(); return true; case MENU_SEARCH: onSearchRequested(); return true; } return super.onOptionsItemSelected(item); } private void startWallpaper() { final Intent pickWallpaper = new Intent(Intent.ACTION_SET_WALLPAPER); startActivity(Intent.createChooser(pickWallpaper, getString(R.string.menu_wallpaper))); } /** * Loads the list of installed applications in mApplications. */ private void loadApplications(boolean isLaunching) { if (isLaunching && mApplications != null) { return; } PackageManager manager = getPackageManager(); Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0); Collections.sort(apps, new ResolveInfo.DisplayNameComparator(manager)); if (apps != null) { final int count = apps.size(); if (mApplications == null) { mApplications = new ArrayList<ApplicationInfo>(count); } mApplications.clear(); for (int i = 0; i < count; i++) { ApplicationInfo application = new ApplicationInfo(); ResolveInfo info = apps.get(i); application.title = info.loadLabel(manager); application.setActivity(new ComponentName( info.activityInfo.applicationInfo.packageName, info.activityInfo.name), Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); application.icon = info.activityInfo.loadIcon(manager); mApplications.add(application); } } } /** * Shows all of the applications by playing an animation on the grid. */ private void showApplications(boolean animate) { if (mBlockAnimation) { return; } mBlockAnimation = true; mShowApplicationsCheck.toggle(); if (mShowLayoutAnimation == null) { mShowLayoutAnimation = AnimationUtils.loadLayoutAnimation( this, R.anim.show_applications); } // This enables a layout animation; if you uncomment this code, you need to // comment the line mGrid.startAnimation() below // mGrid.setLayoutAnimationListener(new ShowGrid()); // mGrid.setLayoutAnimation(mShowLayoutAnimation); // mGrid.startLayoutAnimation(); if (animate) { mGridEntry.setAnimationListener(new ShowGrid()); mGrid.startAnimation(mGridEntry); } mGrid.setVisibility(View.VISIBLE); if (!animate) { mBlockAnimation = false; } // ViewDebug.startHierarchyTracing("Home", mGrid); } /** * Hides all of the applications by playing an animation on the grid. */ private void hideApplications() { if (mBlockAnimation) { return; } mBlockAnimation = true; mShowApplicationsCheck.toggle(); if (mHideLayoutAnimation == null) { mHideLayoutAnimation = AnimationUtils.loadLayoutAnimation( this, R.anim.hide_applications); } mGridExit.setAnimationListener(new HideGrid()); mGrid.startAnimation(mGridExit); mGrid.setVisibility(View.INVISIBLE); mShowApplications.requestFocus(); // This enables a layout animation; if you uncomment this code, you need to // comment the line mGrid.startAnimation() above // mGrid.setLayoutAnimationListener(new HideGrid()); // mGrid.setLayoutAnimation(mHideLayoutAnimation); // mGrid.startLayoutAnimation(); } /** * Receives intents from other applications to change the wallpaper. */ private class WallpaperIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { getWindow().setBackgroundDrawable(new ClippedDrawable(getWallpaper())); } } /** * Receives notifications when applications are added/removed. */ private class ApplicationsIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { loadApplications(false); bindApplications(); bindRecents(); bindFavorites(false); } } /** * GridView adapter to show the list of all installed applications. */ private class ApplicationsAdapter extends ArrayAdapter<ApplicationInfo> { private Rect mOldBounds = new Rect(); public ApplicationsAdapter(Context context, ArrayList<ApplicationInfo> apps) { super(context, 0, apps); } @Override public View getView(int position, View convertView, ViewGroup parent) { final ApplicationInfo info = mApplications.get(position); if (convertView == null) { final LayoutInflater inflater = getLayoutInflater(); convertView = inflater.inflate(R.layout.application, parent, false); } Drawable icon = info.icon; if (!info.filtered) { //final Resources resources = getContext().getResources(); int width = 42;//(int) resources.getDimension(android.R.dimen.app_icon_size); int height = 42;//(int) resources.getDimension(android.R.dimen.app_icon_size); final int iconWidth = icon.getIntrinsicWidth(); final int iconHeight = icon.getIntrinsicHeight(); if (icon instanceof PaintDrawable) { PaintDrawable painter = (PaintDrawable) icon; painter.setIntrinsicWidth(width); painter.setIntrinsicHeight(height); } if (width > 0 && height > 0 && (width < iconWidth || height < iconHeight)) { final float ratio = (float) iconWidth / iconHeight; if (iconWidth > iconHeight) { height = (int) (width / ratio); } else if (iconHeight > iconWidth) { width = (int) (height * ratio); } final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; final Bitmap thumb = Bitmap.createBitmap(width, height, c); final Canvas canvas = new Canvas(thumb); canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, 0)); // Copy the old bounds to restore them later // If we were to do oldBounds = icon.getBounds(), // the call to setBounds() that follows would // change the same instance and we would lose the // old bounds mOldBounds.set(icon.getBounds()); icon.setBounds(0, 0, width, height); icon.draw(canvas); icon.setBounds(mOldBounds); icon = info.icon = new BitmapDrawable(thumb); info.filtered = true; } } final TextView textView = (TextView) convertView.findViewById(R.id.label); textView.setCompoundDrawablesWithIntrinsicBounds(null, icon, null, null); textView.setText(info.title); return convertView; } } /** * Shows and hides the applications grid view. */ private class ShowApplications implements View.OnClickListener { public void onClick(View v) { if (mGrid.getVisibility() != View.VISIBLE) { showApplications(true); } else { hideApplications(); } } } /** * Hides the applications grid when the layout animation is over. */ private class HideGrid implements Animation.AnimationListener { public void onAnimationStart(Animation animation) { } public void onAnimationEnd(Animation animation) { mBlockAnimation = false; } public void onAnimationRepeat(Animation animation) { } } /** * Shows the applications grid when the layout animation is over. */ private class ShowGrid implements Animation.AnimationListener { public void onAnimationStart(Animation animation) { } public void onAnimationEnd(Animation animation) { mBlockAnimation = false; // ViewDebug.stopHierarchyTracing(); } public void onAnimationRepeat(Animation animation) { } } private class ApplicationLauncher implements AdapterView.OnItemClickListener { public void onItemClick(AdapterView parent, View v, int position, long id) { ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position); startActivity(app.intent); } } private class ClippedDrawable extends Drawable { private final Drawable mWallpaper; public ClippedDrawable(Drawable wallpaper) { mWallpaper = wallpaper; } @Override public void setBounds(int left, int top, int right, int bottom) { super.setBounds(left, top, right, bottom); mWallpaper.setBounds(left, top, left + mWallpaper.getIntrinsicWidth(), top + mWallpaper.getIntrinsicHeight()); } public void draw(Canvas canvas) { mWallpaper.draw(canvas); } public void setAlpha(int alpha) { mWallpaper.setAlpha(alpha); } public void setColorFilter(ColorFilter cf) { mWallpaper.setColorFilter(cf); } public int getOpacity() { return mWallpaper.getOpacity(); } } } //src\com\example\android\home\Wallpaper.java package com.example.android.home; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Gallery; import android.widget.ImageView; import android.widget.Gallery.LayoutParams; import java.io.IOException; import java.io.InputStream; public class Wallpaper extends Activity implements AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener { private static final String LOG_TAG = "Home"; private static final Integer[] THUMB_IDS = { R.drawable.bg_android_icon, R.drawable.bg_sunrise_icon, R.drawable.bg_sunset_icon, }; private static final Integer[] IMAGE_IDS = { R.drawable.bg_android, R.drawable.bg_sunrise, R.drawable.bg_sunset, }; private Gallery mGallery; private boolean mIsWallpaperSet; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.wallpaper); mGallery = (Gallery) findViewById(R.id.gallery); mGallery.setAdapter(new ImageAdapter(this)); mGallery.setOnItemSelectedListener(this); mGallery.setOnItemClickListener(this); } @Override protected void onResume() { super.onResume(); mIsWallpaperSet = false; } public void onItemSelected(AdapterView parent, View v, int position, long id) { getWindow().setBackgroundDrawableResource(IMAGE_IDS[position]); } public void onItemClick(AdapterView parent, View v, int position, long id) { selectWallpaper(position); } private synchronized void selectWallpaper(int position) { if (mIsWallpaperSet) { return; } mIsWallpaperSet = true; try { InputStream stream = getResources().openRawResource(IMAGE_IDS[position]); setWallpaper(stream); setResult(RESULT_OK); finish(); } catch (IOException e) { Log.e(LOG_TAG, "Failed to set wallpaper " + e); } } public void onNothingSelected(AdapterView parent) { } @Override public boolean onTouchEvent(MotionEvent event) { selectWallpaper(mGallery.getSelectedItemPosition()); return true; } public class ImageAdapter extends BaseAdapter { private Context mContext; public ImageAdapter(Context c) { mContext = c; } public int getCount() { return THUMB_IDS.length; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(final int position, View convertView, ViewGroup parent) { ImageView i = new ImageView(mContext); i.setImageResource(THUMB_IDS[position]); i.setAdjustViewBounds(true); i.setLayoutParams(new Gallery.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); i.setBackgroundResource(android.R.drawable.picture_frame); return i; } } } // //res\anim\fade_in.xml <?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="50" /> //res\anim\fade_out.xml <?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="50" /> //res\anim\grid_entry.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <scale android:fromXScale="0.8" android:toXScale="1.0" android:fromYScale="0.9" android:toYScale="1.0" android:pivotX="100%" android:pivotY="100%" android:duration="200" /> <alpha android:fromAlpha="0.5" android:toAlpha="1.0" android:duration="200" /> </set> //res\anim\grid_exit.xml <?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="200" /> //res\anim\hide_applications.xml <?xml version="1.0" encoding="utf-8"?> <gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:rowDelay="25%" android:directionPriority="column" android:animation="@anim/fade_out" /> //res\anim\show_applications.xml <?xml version="1.0" encoding="utf-8"?> <gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:rowDelay="25%" android:directionPriority="column" android:direction="right_to_left|bottom_to_top" android:animation="@anim/fade_in" /> // //res\color\bright_text_dark_focused.xml <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:color="#000" /> <item android:state_focused="true" android:color="#000" /> <item android:state_pressed="true" android:color="#000" /> <item android:color="#FFF" /> </selector> // //res\layout\all_applications_button.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/show_all_apps" android:layout_width="78dip" android:layout_height="65dip" android:orientation="vertical" android:gravity="center_vertical" android:clickable="true" android:focusable="true" android:background="@drawable/all_applications_button_background"> <CheckBox android:id="@+id/show_all_apps_check" android:focusable="false" android:clickable="false" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/all_applications_background" android:button="@drawable/all_applications" android:text="@string/show_all_apps" android:textSize="12dip" android:maxLines="1" android:duplicateParentState="true" android:textColor="@color/bright_text_dark_focused" android:gravity="center_horizontal" /> </LinearLayout> //res\layout\application.xml <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/label" android:layout_width="78dip" android:layout_height="65dip" android:paddingTop="4dip" android:textSize="12dip" android:singleLine="true" android:ellipsize="end" android:textColor="@color/bright_text_dark_focused" android:gravity="center_horizontal|center_vertical" /> //res\layout\favorite.xml <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="78dip" android:layout_height="65dip" android:paddingTop="3dip" android:paddingBottom="3dip" android:clickable="true" android:focusable="true" android:background="@drawable/favorite_background" android:textSize="12dip" android:maxLines="1" android:ellipsize="end" android:textColor="@color/bright_text_dark_focused" android:gravity="center_horizontal|bottom" /> //res\layout\wallpaper.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dip" android:background="#70000000" android:text="@string/wallpaper_instructions" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> <Gallery android:id="@+id/gallery" android:background="#70000000" android:layout_width="match_parent" android:layout_height="60dip" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:gravity="center_vertical" android:spacing="16dp" /> </RelativeLayout> // //res\layout-land\home.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:home="http://schemas.android.com/apk/res/com.example.android.home" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- All applications on the top side of the screen --> <GridView android:id="@+id/all_apps" android:background="@drawable/application_background" android:persistentDrawingCache="animation|scrolling" android:alwaysDrawnWithCache="true" android:scrollbars="none" android:drawSelectorOnTop="false" android:listSelector="@drawable/grid_selector" android:numColumns="auto_fit" android:columnWidth="78dp" android:stretchMode="spacingWidth" android:layout_weight="1.0" android:layout_height="0dip" android:layout_width="match_parent" android:stackFromBottom="true" android:visibility="invisible" /> <!-- Favorites and Recents --> <com.example.android.home.ApplicationsStackLayout android:id="@+id/faves_and_recents" home:stackOrientation="horizontal" home:marginLeft="1dip" home:marginRight="1dip" android:layout_marginTop="0dip" android:layout_width="match_parent" android:layout_height="65dip" android:background="@drawable/application_background" /> </LinearLayout> // //res\layout-port\home.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:home="http://schemas.android.com/apk/res/com.example.android.home" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- All applications on the top side of the screen --> <GridView android:id="@+id/all_apps" android:background="@drawable/application_background" android:persistentDrawingCache="animation|scrolling" android:alwaysDrawnWithCache="true" android:scrollbars="none" android:drawSelectorOnTop="false" android:listSelector="@drawable/grid_selector" android:numColumns="auto_fit" android:columnWidth="78dp" android:stretchMode="spacingWidth" android:layout_weight="1.0" android:layout_height="0dip" android:layout_width="match_parent" android:stackFromBottom="true" android:visibility="invisible" /> <!-- Favorites and Recents --> <com.example.android.home.ApplicationsStackLayout android:id="@+id/faves_and_recents" home:stackOrientation="horizontal" home:marginLeft="1dip" home:marginRight="1dip" android:layout_marginTop="0dip" android:layout_width="match_parent" android:layout_height="65dip" android:background="@drawable/application_background" /> </LinearLayout> // //res\values\attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ApplicationsStackLayout"> <attr name="stackOrientation"> <enum name="horizontal" value="0" /> <enum name="vertical" value="1" /> </attr> <attr name="marginLeft" format="dimension" /> <attr name="marginTop" format="dimension" /> <attr name="marginRight" format="dimension" /> <attr name="marginBottom" format="dimension" /> </declare-styleable> </resources> //res\values\strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <!-- Home --> <string name="home_title">Home Sample</string> <string name="show_all_apps">All</string> <!-- Home Menus --> <string name="menu_wallpaper">Wallpaper</string> <string name="menu_search">Search</string> <string name="menu_settings">Settings</string> <!-- Wallpaper --> <string name="wallpaper_instructions">Tap picture to set portrait wallpaper</string> </resources> //res\values\styles.xml <?xml version="1.0" encoding="utf-8"?> <resources> <style name="Theme" parent="android:Theme"> <item name="android:windowNoTitle">true</item> </style> </resources> // //res\values-cs\strings.xml <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="home_title">"Dom"</string> <string name="show_all_apps">"Ve"</string> <string name="menu_wallpaper">"Tapeta"</string> <string name="menu_search">"Hledat"</string> <!-- no translation found for menu_settings (1769059051084007158) --> <skip /> <string name="wallpaper_instructions">"Klepnutm na obrzek nastavte tapetu portrtu"</string> </resources> // //res\values-land\strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <!-- Wallpaper --> <string name="wallpaper_instructions">Tap image to set landscape wallpaper</string> </resources>
Implementation of the android.app.Instrumentation class, allowing you to run tests against application code.
package app.test; import android.app.Activity; import android.app.Instrumentation; import android.content.ComponentName; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; /** * Front-end for launching {@link ContactsFilterInstrumentation} example * instrumentation class. */ public class Test extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Watch for button clicks. Button button = (Button) findViewById(R.id.go); button.setOnClickListener(mGoListener); } private OnClickListener mGoListener = new OnClickListener() { public void onClick(View v) { startInstrumentation(new ComponentName(Test.this, ContactsFilterInstrumentation.class), null, null); } }; } /** * This is an example implementation of the {@link android.app.Instrumentation} * class, allowing you to run tests against application code. The * instrumentation implementation here is loaded into the application's process, * for controlling and monitoring what it does. */ class ContactsFilterInstrumentation extends Instrumentation { @Override public void onCreate(Bundle arguments) { super.onCreate(arguments); // When this instrumentation is created, we simply want to start // its test code off in a separate thread, which will call back // to us in onStart(). start(); } @Override public void onStart() { super.onStart(); // First start the activity we are instrumenting -- the contacts // list. Intent intent = new Intent(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClassName(getTargetContext(), "com.android.phone.Dialer"); Activity activity = startActivitySync(intent); // This is the Activity object that was started, to do with as we want. Log.i("ContactsFilterInstrumentation", "Started: " + activity); // We are going to enqueue a couple key events to simulate the user // filtering the list. This is the low-level API so we must send both // down and up events. sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_M)); sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_M)); sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A)); sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A)); // Wait for the activity to finish all of its processing. waitForIdleSync(); // And we are done! Log.i("ContactsFilterInstrumentation", "Done!"); finish(Activity.RESULT_OK, null); } } //main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip" android:gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0" android:paddingBottom="4dip" android:text="contacts_filter"/> <Button android:id="@+id/go" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="go"> <requestFocus /> </Button> </LinearLayout>
This application demonstrates the seeking capability of ValueAnimator.
package com.example.android.apis.animation; import java.util.ArrayList; import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RadialGradient; import android.graphics.Shader; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.OvalShape; import android.graphics.drawable.shapes.Shape; import android.os.Bundle; import android.view.View; import android.view.animation.BounceInterpolator; import android.widget.Button; import android.widget.LinearLayout; import android.widget.SeekBar; /** * This application demonstrates the seeking capability of ValueAnimator. The * SeekBar in the UI allows you to set the position of the animation. Pressing * the Run button will play from the current position of the animation. */ public class AnimationSeeking extends Activity { private static final int DURATION = 1500; private SeekBar mSeekBar; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.animation_seeking); LinearLayout container = (LinearLayout) findViewById(R.id.container); final MyAnimationView animView = new MyAnimationView(this); container.addView(animView); Button starter = (Button) findViewById(R.id.startButton); starter.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { animView.startAnimation(); } }); mSeekBar = (SeekBar) findViewById(R.id.seekBar); mSeekBar.setMax(DURATION); mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { public void onStopTrackingTouch(SeekBar seekBar) { } public void onStartTrackingTouch(SeekBar seekBar) { } public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // prevent seeking on app creation if (animView.getHeight() != 0) { animView.seek(progress); } } }); } public class MyAnimationView extends View implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener { private static final int RED = 0xffFF8080; private static final int BLUE = 0xff8080FF; private static final int CYAN = 0xff80ffff; private static final int GREEN = 0xff80ff80; private static final float BALL_SIZE = 100f; public final ArrayList<ShapeHolder> balls = new ArrayList<ShapeHolder>(); AnimatorSet animation = null; ValueAnimator bounceAnim = null; ShapeHolder ball = null; public MyAnimationView(Context context) { super(context); ball = addBall(200, 0); } private void createAnimation() { if (bounceAnim == null) { bounceAnim = ObjectAnimator.ofFloat(ball, "y", ball.getY(), getHeight() - BALL_SIZE).setDuration(1500); bounceAnim.setInterpolator(new BounceInterpolator()); bounceAnim.addUpdateListener(this); } } public void startAnimation() { createAnimation(); bounceAnim.start(); } public void seek(long seekTime) { createAnimation(); bounceAnim.setCurrentPlayTime(seekTime); } private ShapeHolder addBall(float x, float y) { OvalShape circle = new OvalShape(); circle.resize(BALL_SIZE, BALL_SIZE); ShapeDrawable drawable = new ShapeDrawable(circle); ShapeHolder shapeHolder = new ShapeHolder(drawable); shapeHolder.setX(x); shapeHolder.setY(y); int red = (int) (100 + Math.random() * 155); int green = (int) (100 + Math.random() * 155); int blue = (int) (100 + Math.random() * 155); int color = 0xff000000 | red << 16 | green << 8 | blue; Paint paint = drawable.getPaint(); int darkColor = 0xff000000 | red / 4 << 16 | green / 4 << 8 | blue / 4; RadialGradient gradient = new RadialGradient(37.5f, 12.5f, 50f, color, darkColor, Shader.TileMode.CLAMP); paint.setShader(gradient); shapeHolder.setPaint(paint); balls.add(shapeHolder); return shapeHolder; } @Override protected void onDraw(Canvas canvas) { canvas.translate(ball.getX(), ball.getY()); ball.getShape().draw(canvas); } public void onAnimationUpdate(ValueAnimator animation) { invalidate(); long playtime = bounceAnim.getCurrentPlayTime(); // mSeekBar.setProgress((int)playtime); } public void onAnimationCancel(Animator animation) { } public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator) animation).getTarget()); } public void onAnimationRepeat(Animator animation) { } public void onAnimationStart(Animator animation) { } } } /** * A data structure that holds a Shape and various properties that can be used * to define how the shape is drawn. */ class ShapeHolder { private float x = 0, y = 0; private ShapeDrawable shape; private int color; private RadialGradient gradient; private float alpha = 1f; private Paint paint; public void setPaint(Paint value) { paint = value; } public Paint getPaint() { return paint; } public void setX(float value) { x = value; } public float getX() { return x; } public void setY(float value) { y = value; } public float getY() { return y; } public void setShape(ShapeDrawable value) { shape = value; } public ShapeDrawable getShape() { return shape; } public int getColor() { return color; } public void setColor(int value) { shape.getPaint().setColor(value); color = value; } public void setGradient(RadialGradient value) { gradient = value; } public RadialGradient getGradient() { return gradient; } public void setAlpha(float alpha) { this.alpha = alpha; shape.setAlpha((int) ((alpha * 255f) + .5f)); } public float getWidth() { return shape.getShape().getWidth(); } public void setWidth(float width) { Shape s = shape.getShape(); s.resize(width, s.getHeight()); } public float getHeight() { return shape.getShape().getHeight(); } public void setHeight(float height) { Shape s = shape.getShape(); s.resize(s.getWidth(), height); } public ShapeHolder(ShapeDrawable s) { shape = s; } } //layout/animation_seeking.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/container" > <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Run" android:id="@+id/startButton" /> <SeekBar android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/seekBar" /> </LinearLayout> </LinearLayout>
Get Application File Path
//package org.acra.util; import java.io.File; import android.content.Context; import android.content.res.Configuration; import android.os.Environment; import android.os.StatFs; import android.telephony.TelephonyManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.WindowManager; public final class ReportUtils { public static String getApplicationFilePath(Context context) { final File filesDir = context.getFilesDir(); if (filesDir != null) { return filesDir.getAbsolutePath(); } // Log.w(ACRA.LOG_TAG, "Couldn't retrieve ApplicationFilePath for : " + context.getPackageName()); return "Couldn't retrieve ApplicationFilePath"; } }
Creates a file storing a UUID on the first application start. This UUID can then be used as a identifier of this specific application installation.
//package org.acra.util; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.util.UUID; import android.content.Context; import android.util.Log; public class Installation { private static String sID; private static final String INSTALLATION = "ACRA-INSTALLATION"; public synchronized static String id(Context context) { if (sID == null) { final File installation = new File(context.getFilesDir(), INSTALLATION); try { if (!installation.exists()) { writeInstallationFile(installation); } sID = readInstallationFile(installation); } catch (IOException e) { // Log.w(ACRA.LOG_TAG, "Couldn't retrieve InstallationId for " + context.getPackageName(), e); return "Couldn't retrieve InstallationId"; } catch (RuntimeException e) { // Log.w(ACRA.LOG_TAG, "Couldn't retrieve InstallationId for " + context.getPackageName(), e); return "Couldn't retrieve InstallationId"; } } return sID; } private static String readInstallationFile(File installation) throws IOException { final RandomAccessFile f = new RandomAccessFile(installation, "r"); final byte[] bytes = new byte[(int) f.length()]; try { f.readFully(bytes); } finally { f.close(); } return new String(bytes); } private static void writeInstallationFile(File installation) throws IOException { final FileOutputStream out = new FileOutputStream(installation); try { final String id = UUID.randomUUID().toString(); out.write(id.getBytes()); } finally { out.close(); } } }