├── .gitignore ├── EatApplication ├── .gitignore ├── Eat │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.txt │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── ic_launcher-web.png │ │ ├── java │ │ └── com │ │ │ └── eat │ │ │ ├── StartActivity.java │ │ │ ├── chapter1 │ │ │ └── Chapter1Activity.java │ │ │ ├── chapter10 │ │ │ ├── Chapter10Activity.java │ │ │ └── FileDownloadActivity.java │ │ │ ├── chapter11 │ │ │ ├── BluetoothActivity.java │ │ │ ├── BluetoothService.java │ │ │ ├── BoundLocalActivity.java │ │ │ ├── BoundLocalActivity2.java │ │ │ ├── BoundLocalService.java │ │ │ ├── BoundLocalService2.java │ │ │ ├── Chapter11Activity.java │ │ │ ├── DownloadActivity.java │ │ │ └── DownloadService.java │ │ │ ├── chapter12 │ │ │ ├── AlarmBroadcastActivity.java │ │ │ ├── AlarmReceiver.java │ │ │ ├── Chapter12Activity.java │ │ │ ├── NetworkCheckerIntentService.java │ │ │ ├── WebService.java │ │ │ └── WebServiceActivity.java │ │ │ ├── chapter13 │ │ │ ├── Chapter13Activity.java │ │ │ └── ExpandableContactListActivity.java │ │ │ ├── chapter14 │ │ │ ├── BasicActivity.java │ │ │ ├── BasicLoader.java │ │ │ ├── Chapter14Activity.java │ │ │ ├── ChromeBookmarkActivity.java │ │ │ ├── ContactActivity.java │ │ │ ├── EditBookmarkDialog.java │ │ │ ├── FileActivity.java │ │ │ ├── FileListFragment.java │ │ │ └── FileLoader.java │ │ │ ├── chapter2 │ │ │ └── Chapter2Activity.java │ │ │ ├── chapter3 │ │ │ └── Chapter3Activity.java │ │ │ ├── chapter4 │ │ │ ├── Chapter4Activity.java │ │ │ ├── ConsumeAndQuitThreadActivity.java │ │ │ ├── HandlerCallbackActivity.java │ │ │ ├── HandlerExampleActivity.java │ │ │ ├── LooperActivity.java │ │ │ ├── MQDebugActivity.java │ │ │ └── PipeExampleActivity.java │ │ │ ├── chapter5 │ │ │ ├── Chapter5Activity.java │ │ │ ├── MessengerOnewayActivity.java │ │ │ ├── MessengerTwowayActivity.java │ │ │ └── WorkerThreadService.java │ │ │ ├── chapter6 │ │ │ └── Chapter6Activity.java │ │ │ ├── chapter7 │ │ │ ├── Chapter7Activity.java │ │ │ ├── ThreadFragment.java │ │ │ ├── ThreadRetainActivity.java │ │ │ └── ThreadRetainWithFragmentActivity.java │ │ │ ├── chapter8 │ │ │ ├── ChainedNetworkActivity.java │ │ │ ├── Chapter8Activity.java │ │ │ ├── MyHandlerThread.java │ │ │ └── SharedPreferencesActivity.java │ │ │ └── chapter9 │ │ │ ├── Chapter9Activity.java │ │ │ ├── ECSImageDownloaderActivity.java │ │ │ ├── InvokeActivity.java │ │ │ ├── LowPriorityThreadFactory.java │ │ │ ├── PrestartedCores.java │ │ │ ├── SimpleExecutor.java │ │ │ └── TaskTrackingThreadPool.java │ │ └── res │ │ ├── drawable-hdpi │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ │ ├── layout │ │ ├── activity_alarm_broadcast.xml │ │ ├── activity_basic.xml │ │ ├── activity_bluetooth.xml │ │ ├── activity_bookmarks.xml │ │ ├── activity_bound_local_service_async_client.xml │ │ ├── activity_bound_local_service_sync_client.xml │ │ ├── activity_chapter1.xml │ │ ├── activity_chapter10.xml │ │ ├── activity_chapter11.xml │ │ ├── activity_chapter12.xml │ │ ├── activity_chapter13.xml │ │ ├── activity_chapter14.xml │ │ ├── activity_chapter2.xml │ │ ├── activity_chapter3.xml │ │ ├── activity_chapter4.xml │ │ ├── activity_chapter5.xml │ │ ├── activity_chapter6.xml │ │ ├── activity_chapter7.xml │ │ ├── activity_chapter8.xml │ │ ├── activity_chapter9.xml │ │ ├── activity_download_service.xml │ │ ├── activity_ecs_image_downloader.xml │ │ ├── activity_file.xml │ │ ├── activity_file_download.xml │ │ ├── activity_futuretask_preload.xml │ │ ├── activity_handler_callback.xml │ │ ├── activity_handler_example.xml │ │ ├── activity_invoke.xml │ │ ├── activity_looper.xml │ │ ├── activity_messenger_client.xml │ │ ├── activity_mq_debug.xml │ │ ├── activity_pipe.xml │ │ ├── activity_retain_thread.xml │ │ ├── activity_shared_preferences.xml │ │ ├── activity_start.xml │ │ ├── activity_web_service.xml │ │ └── dialog_edit_bookmark.xml │ │ ├── menu │ │ └── start.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── dimens.xml │ │ └── strings.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Eclipse project files 19 | .classpath 20 | .project 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Intellij project files 26 | *.iml 27 | *.ipr 28 | *.iws 29 | .idea/ 30 | -------------------------------------------------------------------------------- /EatApplication/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /EatApplication/Eat/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /EatApplication/Eat/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'android' 2 | 3 | android { 4 | compileSdkVersion 19 5 | buildToolsVersion '19.1.0' 6 | 7 | defaultConfig { 8 | minSdkVersion 16 9 | targetSdkVersion 19 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | runProguard false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 17 | } 18 | } 19 | lintOptions { 20 | abortOnError false 21 | } 22 | } 23 | 24 | dependencies { 25 | compile fileTree(dir: 'libs', include: ['*.jar', '*.aar']) 26 | } 27 | -------------------------------------------------------------------------------- /EatApplication/Eat/proguard-rules.txt: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/andersgoransson/development/android-sdk-macosx/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the ProGuard 5 | # include property in project.properties. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 40 | 41 | 44 | 45 | 46 | 49 | 50 | 51 | 54 | 57 | 60 | 63 | 66 | 69 | 72 | 73 | 74 | 77 | 80 | 83 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 94 | 95 | 96 | 99 | 102 | 105 | 106 | 107 | 110 | 113 | 116 | 117 | 118 | 121 | 124 | 127 | 128 | 129 | 132 | 135 | 136 | 137 | 140 | 143 | 144 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 156 | 157 | 160 | 161 | 162 | 163 | 166 | 169 | 170 | 173 | 174 | 175 | 176 | 179 | 182 | 183 | 184 | 187 | 190 | 193 | 196 | 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersgoransson/eatbookexamples/b6476cba9d931982b2f8c07a5fb7c529b3ba73d4/EatApplication/Eat/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/StartActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.chapter10.Chapter10Activity; 9 | import com.eat.chapter11.Chapter11Activity; 10 | import com.eat.chapter12.Chapter12Activity; 11 | import com.eat.chapter13.Chapter13Activity; 12 | import com.eat.chapter14.Chapter14Activity; 13 | import com.eat.chapter4.Chapter4Activity; 14 | import com.eat.chapter5.Chapter5Activity; 15 | import com.eat.chapter6.Chapter6Activity; 16 | import com.eat.chapter7.Chapter7Activity; 17 | import com.eat.chapter8.Chapter8Activity; 18 | import com.eat.chapter9.Chapter9Activity; 19 | 20 | public class StartActivity extends Activity { 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_start); 26 | } 27 | 28 | public void onChapter1(View v) { 29 | // Empty, no examples in this chapter. 30 | } 31 | 32 | public void onChapter2(View v) { 33 | // Empty, no examples in this chapter. 34 | } 35 | 36 | public void onChapter3(View v) { 37 | // Empty, no examples in this chapter. 38 | } 39 | 40 | public void onChapter4(View v) { 41 | startActivity(new Intent(this, Chapter4Activity.class)); 42 | } 43 | 44 | public void onChapter5(View v) { 45 | startActivity(new Intent(this, Chapter5Activity.class)); 46 | } 47 | 48 | public void onChapter6(View v) { 49 | startActivity(new Intent(this, Chapter6Activity.class)); 50 | } 51 | 52 | public void onChapter7(View v) { 53 | startActivity(new Intent(this, Chapter7Activity.class)); 54 | } 55 | 56 | public void onChapter8(View v) { 57 | startActivity(new Intent(this, Chapter8Activity.class)); 58 | } 59 | 60 | public void onChapter9(View v) { 61 | startActivity(new Intent(this, Chapter9Activity.class)); 62 | } 63 | 64 | public void onChapter10(View v) { 65 | startActivity(new Intent(this, Chapter10Activity.class)); 66 | } 67 | 68 | public void onChapter11(View v) { 69 | startActivity(new Intent(this, Chapter11Activity.class)); 70 | } 71 | 72 | public void onChapter12(View v) { 73 | startActivity(new Intent(this, Chapter12Activity.class)); 74 | } 75 | 76 | public void onChapter13(View v) { 77 | startActivity(new Intent(this, Chapter13Activity.class)); 78 | } 79 | 80 | public void onChapter14(View v) { 81 | startActivity(new Intent(this, Chapter14Activity.class)); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter1/Chapter1Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter1; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | 10 | public class Chapter1Activity extends Activity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_chapter1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter10/Chapter10Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter10; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | 10 | public class Chapter10Activity extends Activity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_chapter10); 16 | } 17 | 18 | public void onFileDownloadActivity(View v) { 19 | startActivity(new Intent(this, FileDownloadActivity.class)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter10/FileDownloadActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter10; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.os.AsyncTask; 7 | import android.os.Bundle; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | import android.widget.LinearLayout; 11 | import android.widget.ProgressBar; 12 | 13 | import com.eat.R; 14 | 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.net.MalformedURLException; 18 | import java.net.URL; 19 | 20 | 21 | public class FileDownloadActivity extends Activity { 22 | 23 | private static final String[] DOWNLOAD_URLS = { 24 | "http://developer.android.com/design/media/devices_displays_density@2x.png", 25 | "http://developer.android.com/design/media/iconography_launcher_example2.png", 26 | "http://developer.android.com/design/media/iconography_actionbar_focal.png", 27 | "http://developer.android.com/design/media/iconography_actionbar_colors.png" 28 | }; 29 | 30 | DownloadTask mFileDownloaderTask; 31 | 32 | // Views from layout file 33 | private ProgressBar mProgressBar; 34 | private LinearLayout mLayoutImages; 35 | 36 | @Override 37 | public void onCreate(Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | 40 | setContentView(R.layout.activity_file_download); 41 | mProgressBar = (ProgressBar) findViewById(R.id.progress_bar); 42 | mProgressBar.setMax(DOWNLOAD_URLS.length); 43 | mLayoutImages = (LinearLayout) findViewById(R.id.layout_images); 44 | 45 | mFileDownloaderTask = new DownloadTask(this); 46 | mFileDownloaderTask.execute(DOWNLOAD_URLS); 47 | } 48 | 49 | @Override 50 | protected void onDestroy() { 51 | super.onDestroy(); 52 | mFileDownloaderTask.setActivity(null); 53 | mFileDownloaderTask.cancel(true); 54 | } 55 | 56 | private static class DownloadTask extends AsyncTask { 57 | 58 | private FileDownloadActivity mActivity; 59 | private int mCount = 0; 60 | 61 | public DownloadTask(FileDownloadActivity activity) { 62 | mActivity = activity; 63 | } 64 | 65 | public void setActivity(FileDownloadActivity activity) { 66 | mActivity = activity; 67 | } 68 | 69 | @Override 70 | protected void onPreExecute() { 71 | super.onPreExecute(); 72 | mActivity.mProgressBar.setVisibility(View.VISIBLE); 73 | mActivity.mProgressBar.setProgress(0); 74 | } 75 | 76 | @Override 77 | protected Void doInBackground(String... urls) { 78 | for (String url : urls) { 79 | if (!isCancelled()) { 80 | Bitmap bitmap = downloadFile(url); 81 | publishProgress(bitmap); 82 | } 83 | } 84 | return null; 85 | } 86 | 87 | 88 | @Override 89 | protected void onProgressUpdate(Bitmap... bitmaps) { 90 | super.onProgressUpdate(bitmaps); 91 | if (mActivity != null) { 92 | mActivity.mProgressBar.setProgress(++mCount); 93 | ImageView iv = new ImageView(mActivity); 94 | iv.setImageBitmap(bitmaps[0]); 95 | mActivity.mLayoutImages.addView(iv); 96 | } 97 | } 98 | 99 | @Override 100 | protected void onPostExecute(Void aVoid) { 101 | super.onPostExecute(aVoid); 102 | if (mActivity != null) { 103 | mActivity.mProgressBar.setVisibility(View.GONE); 104 | } 105 | } 106 | 107 | @Override 108 | protected void onCancelled() { 109 | super.onCancelled(); 110 | if (mActivity != null) { 111 | mActivity.mProgressBar.setVisibility(View.GONE); 112 | } 113 | } 114 | 115 | 116 | private Bitmap downloadFile(String url) { 117 | Bitmap bitmap = null; 118 | try { 119 | bitmap = BitmapFactory 120 | .decodeStream((InputStream) new URL(url) 121 | .getContent()); 122 | } catch (MalformedURLException e) { 123 | e.printStackTrace(); 124 | } catch (IOException e) { 125 | e.printStackTrace(); 126 | } 127 | return bitmap; 128 | } 129 | 130 | } 131 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter11/BluetoothActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter11; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | 10 | 11 | public class BluetoothActivity extends Activity { 12 | public void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_bluetooth); 15 | } 16 | 17 | public void onStartListening(View v) { 18 | Intent intent = new Intent(this, BluetoothService.class); 19 | intent.putExtra(BluetoothService.COMMAND_KEY, BluetoothService.COMMAND_START_LISTENING); 20 | startService(intent); 21 | } 22 | 23 | public void onStopListening(View v) { 24 | Intent intent = new Intent(this, BluetoothService.class); 25 | stopService(intent); 26 | } 27 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter11/BluetoothService.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter11; 2 | 3 | import android.app.Service; 4 | import android.bluetooth.BluetoothAdapter; 5 | import android.bluetooth.BluetoothServerSocket; 6 | import android.bluetooth.BluetoothSocket; 7 | import android.content.Intent; 8 | import android.content.res.Configuration; 9 | import android.os.IBinder; 10 | import android.util.Log; 11 | 12 | import java.io.IOException; 13 | import java.util.UUID; 14 | 15 | 16 | public class BluetoothService extends Service { 17 | 18 | private static final String TAG = "BluetoothService"; 19 | public static final String COMMAND_KEY = "command_key"; 20 | public static final String COMMAND_START_LISTENING = "command_start_discovery"; 21 | 22 | private static final UUID MY_UUID = new UUID(323476234, 34587387); 23 | private static final String SDP_NAME = "custom_sdp_name"; 24 | 25 | 26 | private BluetoothAdapter mAdapter; 27 | private BluetoothServerSocket mServerSocket; 28 | private boolean mListening = false; 29 | private Thread listeningThread; 30 | 31 | 32 | public IBinder onBind(Intent intent) { 33 | return null; 34 | } 35 | 36 | @Override 37 | public void onCreate() { 38 | super.onCreate(); 39 | mAdapter = BluetoothAdapter.getDefaultAdapter(); 40 | } 41 | 42 | @Override 43 | public int onStartCommand(Intent intent, int flags, int startId) { 44 | if (mAdapter != null) { 45 | if (intent.getStringExtra(COMMAND_KEY).equals(COMMAND_START_LISTENING) && mListening == false) { 46 | startListening(); 47 | } 48 | } 49 | return START_REDELIVER_INTENT; 50 | } 51 | 52 | private void startListening() { 53 | mListening = true; 54 | listeningThread = new Thread(new Runnable() { 55 | 56 | @Override 57 | public void run() { 58 | BluetoothSocket socket = null; 59 | try { 60 | mServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord(SDP_NAME, MY_UUID); 61 | socket = mServerSocket.accept(); 62 | 63 | if (socket != null) { 64 | // Handle BT connection 65 | } 66 | 67 | } catch (IOException e) { 68 | Log.d(TAG, "Server socket closed"); 69 | } 70 | } 71 | }); 72 | listeningThread.start(); 73 | } 74 | 75 | private void stopListening() { 76 | mListening = false; 77 | try { 78 | if (mServerSocket != null) { 79 | mServerSocket.close(); 80 | } 81 | } catch (IOException e) { 82 | e.printStackTrace(); 83 | } 84 | } 85 | 86 | @Override 87 | public void onDestroy() { 88 | super.onDestroy(); 89 | stopListening(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter11/BoundLocalActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter11; 2 | 3 | import android.app.Activity; 4 | import android.app.Service; 5 | import android.content.ComponentName; 6 | import android.content.Intent; 7 | import android.content.ServiceConnection; 8 | import android.os.Bundle; 9 | import android.os.IBinder; 10 | import android.view.View; 11 | import android.widget.TextView; 12 | 13 | import com.eat.R; 14 | 15 | import java.lang.ref.WeakReference; 16 | 17 | 18 | public class BoundLocalActivity extends Activity { 19 | 20 | private LocalServiceConnection mLocalServiceConnection = new LocalServiceConnection(); 21 | private BoundLocalService mBoundLocalService; 22 | private boolean mIsBound; 23 | 24 | public void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | bindService(new Intent(BoundLocalActivity.this, BoundLocalService.class), 27 | mLocalServiceConnection, 28 | Service.BIND_AUTO_CREATE); 29 | mIsBound = true; 30 | } 31 | @Override 32 | protected void onDestroy() { super.onDestroy(); 33 | if (mIsBound) { 34 | try { 35 | unbindService(mLocalServiceConnection); 36 | mIsBound = false; 37 | } catch (IllegalArgumentException e) { 38 | // No bound service 39 | } 40 | } 41 | } 42 | private class LocalServiceConnection implements ServiceConnection { 43 | @Override 44 | public void onServiceConnected(ComponentName componentName, IBinder iBinder) { 45 | mBoundLocalService = ((BoundLocalService.ServiceBinder)iBinder).getService(); 46 | 47 | // At this point clients can invoke methods in the Service, 48 | // i.e. publishedMethod1 and publishedMethod2. 49 | } 50 | 51 | @Override 52 | public void onServiceDisconnected(ComponentName componentName) { 53 | mBoundLocalService = null; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter11/BoundLocalActivity2.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter11; 2 | 3 | import android.app.Activity; 4 | import android.app.Service; 5 | import android.content.ComponentName; 6 | import android.content.Intent; 7 | import android.content.ServiceConnection; 8 | import android.os.Bundle; 9 | import android.os.IBinder; 10 | import android.view.View; 11 | import android.widget.TextView; 12 | 13 | import com.eat.R; 14 | 15 | import java.lang.ref.WeakReference; 16 | 17 | 18 | public class BoundLocalActivity2 extends Activity { 19 | 20 | private TextView tvStatus; 21 | 22 | private LocalServiceConnection mLocalServiceConnection = new LocalServiceConnection(); 23 | private boolean mIsBound; 24 | private BoundLocalService2 mBoundLocalService; 25 | 26 | private static class ServiceListener implements BoundLocalService2.OperationListener { 27 | 28 | private WeakReference mWeakActivity; 29 | 30 | public ServiceListener(BoundLocalActivity2 activity) { 31 | this.mWeakActivity = new WeakReference(activity); 32 | } 33 | 34 | @Override 35 | public void onOperationDone(final int someResult) { 36 | final BoundLocalActivity2 localReferenceActivity = mWeakActivity.get(); 37 | if (localReferenceActivity != null) { 38 | localReferenceActivity.runOnUiThread(new Runnable(){ 39 | @Override 40 | public void run() { 41 | localReferenceActivity.tvStatus.setText(Integer.toString(someResult)); 42 | } 43 | }); 44 | } 45 | } 46 | } 47 | 48 | public void onCreate(Bundle savedInstanceState) { 49 | super.onCreate(savedInstanceState); 50 | setContentView(R.layout.activity_bound_local_service_sync_client); 51 | tvStatus = (TextView) findViewById(R.id.text_status); 52 | 53 | bindService(new Intent(BoundLocalActivity2.this, BoundLocalService2.class), mLocalServiceConnection, Service.BIND_AUTO_CREATE); 54 | mIsBound = true; 55 | } 56 | 57 | @Override 58 | protected void onDestroy() { 59 | super.onDestroy(); 60 | if (mIsBound) { 61 | try { 62 | unbindService(mLocalServiceConnection); 63 | mIsBound = false; 64 | } catch (IllegalArgumentException e) { 65 | // No bound service 66 | } 67 | } 68 | } 69 | 70 | 71 | public void onClickExecuteOnClientUIThread(View v) { 72 | if (mBoundLocalService != null) { 73 | mBoundLocalService.doLongAsyncOperation(new ServiceListener(this)); 74 | } 75 | } 76 | 77 | private class LocalServiceConnection implements ServiceConnection { 78 | 79 | @Override 80 | public void onServiceConnected(ComponentName componentName, IBinder iBinder) { 81 | mBoundLocalService = ((BoundLocalService2.ServiceBinder)iBinder).getService(); 82 | } 83 | 84 | @Override 85 | public void onServiceDisconnected(ComponentName componentName) { 86 | mBoundLocalService = null; 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter11/BoundLocalService.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter11; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.Binder; 6 | import android.os.IBinder; 7 | import android.util.Log; 8 | 9 | 10 | public class BoundLocalService extends Service { 11 | 12 | private final ServiceBinder mBinder = new ServiceBinder(); 13 | 14 | public IBinder onBind(Intent intent) { 15 | return mBinder; 16 | } 17 | 18 | public class ServiceBinder extends Binder { 19 | public BoundLocalService getService() { 20 | return BoundLocalService.this; 21 | } 22 | } 23 | 24 | // Methods published to clients. 25 | public void publishedMethod1() { /* TO IMPLEMENT */ } 26 | 27 | public void publishedMethod2() { /* TO IMPLEMENT */ } 28 | } 29 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter11/BoundLocalService2.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter11; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.content.res.Configuration; 6 | import android.os.Binder; 7 | import android.os.IBinder; 8 | import android.os.SystemClock; 9 | import android.util.Log; 10 | 11 | import java.util.concurrent.Executor; 12 | 13 | 14 | public class BoundLocalService2 extends Service { 15 | 16 | private final ServiceBinder mBinder = new ServiceBinder(); 17 | private final TaskExecutor executor = new TaskExecutor(); 18 | 19 | public interface OperationListener { 20 | public void onOperationDone(int i); 21 | } 22 | 23 | public IBinder onBind(Intent intent) { 24 | return mBinder; 25 | } 26 | 27 | @Override 28 | public void onCreate() { 29 | super.onCreate(); 30 | 31 | } 32 | 33 | public class ServiceBinder extends Binder { 34 | public BoundLocalService2 getService() { 35 | return BoundLocalService2.this; 36 | } 37 | } 38 | 39 | 40 | public int doLongSyncOperation() { 41 | return longOperation(); 42 | } 43 | 44 | public void doLongAsyncOperation(final OperationListener listener) { 45 | executor.execute(new Runnable() { 46 | @Override 47 | public void run() { 48 | int result = longOperation(); 49 | listener.onOperationDone(result); 50 | } 51 | }); 52 | } 53 | 54 | private int longOperation() { 55 | SystemClock.sleep(10000); 56 | return 42; 57 | } 58 | 59 | public class TaskExecutor implements Executor { 60 | @Override 61 | public void execute(Runnable runnable) { 62 | new Thread(runnable).start(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter11/Chapter11Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter11; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | import com.eat.chapter10.FileDownloadActivity; 10 | 11 | public class Chapter11Activity extends Activity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_chapter11); 17 | } 18 | 19 | public void onBluetoothActivity(View v) { 20 | startActivity(new Intent(this, BluetoothActivity.class)); 21 | } 22 | 23 | public void onDownloadActivity(View v) { 24 | startActivity(new Intent(this, DownloadActivity.class)); 25 | } 26 | 27 | public void onBoundLocalActivity(View v) { 28 | startActivity(new Intent(this, BoundLocalActivity.class)); 29 | } 30 | 31 | public void onBoundLocalActivity2(View v) { 32 | startActivity(new Intent(this, BoundLocalActivity2.class)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter11/DownloadActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter11; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.view.View; 9 | 10 | import com.eat.R; 11 | 12 | 13 | public class DownloadActivity extends Activity { 14 | 15 | private static final String DOWNLOAD_URL = "http://developer.android.com/design/media/devices_displays_density@2x.png"; 16 | 17 | 18 | public void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_download_service); 21 | } 22 | 23 | public void onStartDownload(View v) { 24 | Intent intent = new Intent("com.eat.ACTION_DOWNLOAD"); 25 | intent.setData(Uri.parse(DOWNLOAD_URL)); 26 | startService(intent); 27 | } 28 | 29 | public void onStopService(View v) { 30 | Intent intent = new Intent(this, DownloadService.class); 31 | stopService(intent); 32 | } 33 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter11/DownloadService.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter11; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.IBinder; 7 | import android.os.SystemClock; 8 | import android.util.Log; 9 | 10 | import java.util.concurrent.ExecutorService; 11 | import java.util.concurrent.Executors; 12 | 13 | 14 | public class DownloadService extends Service { 15 | 16 | private ExecutorService mDownloadExecutor; 17 | private int mCommandCount; 18 | 19 | public IBinder onBind(Intent intent) { 20 | return null; 21 | } 22 | 23 | @Override 24 | public void onCreate() { 25 | super.onCreate(); 26 | mDownloadExecutor = Executors.newFixedThreadPool(4); 27 | } 28 | 29 | @Override 30 | public void onDestroy() { 31 | super.onDestroy(); 32 | mDownloadExecutor.shutdownNow(); 33 | } 34 | 35 | @Override 36 | public int onStartCommand(Intent intent, int flags, int startId) { 37 | synchronized (this) { 38 | mCommandCount++; 39 | } 40 | if (intent != null) { 41 | downloadFile(intent.getData()); 42 | } 43 | return START_REDELIVER_INTENT; 44 | } 45 | 46 | private void downloadFile(final Uri uri) { 47 | mDownloadExecutor.submit(new Runnable() { 48 | @Override 49 | public void run() { 50 | 51 | // Simulate long file download 52 | SystemClock.sleep(10000); 53 | 54 | synchronized (this) { 55 | if (--mCommandCount <= 0) { 56 | stopSelf(); 57 | } 58 | } 59 | } 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter12/AlarmBroadcastActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter12; 2 | 3 | import android.app.Activity; 4 | import android.app.AlarmManager; 5 | import android.app.PendingIntent; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.content.IntentFilter; 9 | import android.os.Bundle; 10 | import android.os.SystemClock; 11 | import android.widget.TextView; 12 | 13 | import com.eat.R; 14 | 15 | 16 | public class AlarmBroadcastActivity extends Activity { 17 | 18 | private static final long ONE_HOUR = 60 * 60 * 1000; 19 | TextView tvStatus; 20 | 21 | AlarmManager am; 22 | 23 | AlarmReceiver alarmReceiver; 24 | 25 | public void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_alarm_broadcast); 28 | tvStatus = (TextView) findViewById(R.id.text_alarm_status); 29 | 30 | alarmReceiver = new AlarmReceiver(); 31 | registerReceiver(alarmReceiver, new IntentFilter("com.eat.alarmreceiver")); 32 | 33 | PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent("com.eat.alarmreceiver"), PendingIntent.FLAG_UPDATE_CURRENT); 34 | am = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE )); 35 | am.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() 36 | + ONE_HOUR, ONE_HOUR, pendingIntent); 37 | tvStatus.setText("Alarm is set"); 38 | } 39 | 40 | @Override 41 | protected void onDestroy() { 42 | super.onDestroy(); 43 | unregisterReceiver(alarmReceiver); 44 | } 45 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter12/AlarmReceiver.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter12; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | public class AlarmReceiver extends BroadcastReceiver { 8 | 9 | public void onReceive(Context context, Intent intent) { 10 | context.startService(new Intent(context, NetworkCheckerIntentService.class)); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter12/Chapter12Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter12; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | import com.eat.chapter11.BoundLocalActivity; 10 | import com.eat.chapter11.BoundLocalActivity2; 11 | 12 | public class Chapter12Activity extends Activity { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_chapter12); 18 | } 19 | 20 | public void onAlarmBroadcastActivity(View v) { 21 | startActivity(new Intent(this, AlarmBroadcastActivity.class)); 22 | } 23 | 24 | public void onWebServiceActivity(View v) { 25 | startActivity(new Intent(this, WebServiceActivity.class)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter12/NetworkCheckerIntentService.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter12; 2 | 3 | import android.app.IntentService; 4 | import android.app.Notification; 5 | import android.app.NotificationManager; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | 9 | import com.eat.R; 10 | 11 | 12 | public class NetworkCheckerIntentService extends IntentService { 13 | 14 | public NetworkCheckerIntentService() { 15 | super("NetworkCheckerThread"); 16 | } 17 | 18 | @Override 19 | protected void onHandleIntent(Intent intent) { 20 | if (isNewNetworkDataAvailable()) { 21 | addStatusBarNotification(); 22 | } 23 | } 24 | 25 | private boolean isNewNetworkDataAvailable() { 26 | // Network request code omitted. Returns dummy result. 27 | return true; 28 | } 29 | 30 | private void addStatusBarNotification() { 31 | Notification.Builder mBuilder = 32 | new Notification.Builder(this) 33 | .setSmallIcon(R.drawable.ic_launcher) 34 | .setContentTitle("New network data") 35 | .setContentText("New data can be downloaded."); 36 | 37 | NotificationManager mNotificationManager = 38 | (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 39 | mNotificationManager.notify(1, mBuilder.build()); 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter12/WebService.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter12; 2 | 3 | import java.io.IOException; 4 | import java.net.URI; 5 | import java.net.URISyntaxException; 6 | 7 | import org.apache.http.HttpEntity; 8 | import org.apache.http.HttpResponse; 9 | import org.apache.http.StatusLine; 10 | import org.apache.http.client.HttpClient; 11 | import org.apache.http.client.methods.HttpGet; 12 | import org.apache.http.client.methods.HttpPost; 13 | import org.apache.http.client.methods.HttpRequestBase; 14 | import org.apache.http.entity.StringEntity; 15 | import org.apache.http.impl.client.DefaultHttpClient; 16 | import org.apache.http.util.EntityUtils; 17 | 18 | import android.app.IntentService; 19 | import android.content.Intent; 20 | import android.net.Uri; 21 | import android.os.Bundle; 22 | import android.os.ResultReceiver; 23 | 24 | public class WebService extends IntentService { 25 | private static final String TAG = WebService.class.getName(); 26 | public static final int GET = 1; 27 | public static final int POST = 2; 28 | 29 | public static final String INTENT_KEY_REQUEST_TYPE = "com.eat.INTENT_KEY_REQUEST_TYPE"; 30 | public static final String INTENT_KEY_JSON = "com.eat.INTENT_KEY_JSON"; 31 | public static final String INTENT_KEY_RECEIVER = "com.eat.INTENT_KEY_RECEIVER"; 32 | public static final String BUNDLE_KEY_REQUEST_RESULT = "com.eat.BUNDLE_KEY_REQUEST_RESULT"; 33 | 34 | public WebService() { 35 | super(TAG); 36 | } 37 | 38 | @Override 39 | protected void onHandleIntent(Intent intent) { 40 | 41 | Uri uri = intent.getData(); 42 | int requestType = intent.getIntExtra(INTENT_KEY_REQUEST_TYPE, 0); 43 | String json = (String)intent.getSerializableExtra(INTENT_KEY_JSON); 44 | ResultReceiver receiver = intent.getParcelableExtra(INTENT_KEY_RECEIVER); 45 | 46 | try { 47 | HttpRequestBase request = null; 48 | switch (requestType) { 49 | case GET: { 50 | request = new HttpGet(); 51 | // Request setup omitted 52 | break; 53 | } 54 | case POST: { 55 | request = new HttpPost(); 56 | if (json != null) { 57 | ((HttpPost)request).setEntity(new StringEntity(json)); 58 | } 59 | // Request setup omitted 60 | break; 61 | } 62 | } 63 | 64 | if (request != null) { 65 | request.setURI(new URI(uri.toString())); 66 | HttpResponse response = doRequest(request); 67 | HttpEntity httpEntity = response.getEntity(); 68 | StatusLine responseStatus = response.getStatusLine(); 69 | int statusCode = responseStatus != null ? responseStatus.getStatusCode() : 0; 70 | 71 | if (httpEntity != null) { 72 | Bundle resultBundle = new Bundle(); 73 | resultBundle.putString(BUNDLE_KEY_REQUEST_RESULT, EntityUtils.toString(httpEntity)); 74 | receiver.send(statusCode, resultBundle); 75 | } 76 | else { 77 | receiver.send(statusCode, null); 78 | } 79 | } 80 | else { 81 | receiver.send(0, null); 82 | 83 | } 84 | } 85 | catch (IOException e) { 86 | receiver.send(0, null); 87 | } catch (URISyntaxException e) { 88 | e.printStackTrace(); 89 | } 90 | } 91 | 92 | private HttpResponse doRequest(HttpRequestBase request) throws IOException { 93 | HttpClient client = new DefaultHttpClient(); 94 | 95 | // HttpClient configuration omitted 96 | 97 | return client.execute(request); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter12/WebServiceActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter12; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.os.ResultReceiver; 9 | import android.view.View; 10 | 11 | import com.eat.R; 12 | 13 | public class WebServiceActivity extends Activity { 14 | 15 | private final static String TAG = WebServiceActivity.class.getSimpleName(); 16 | private final static String getUrl = "http://dn.se"; // Dummy 17 | private final static String postUrl = "http://dn.se"; // Dummy 18 | 19 | private ResultReceiver mReceiver; 20 | 21 | public WebServiceActivity() { 22 | mReceiver = new ResultReceiver(new Handler()) { 23 | @Override 24 | protected void onReceiveResult(int resultCode, Bundle resultData) { 25 | int httpStatus = resultCode; 26 | String jsonResult = null; 27 | if (httpStatus == 200) { // OK 28 | if (resultData != null) { 29 | jsonResult= resultData.getString(WebService.BUNDLE_KEY_REQUEST_RESULT); 30 | // Omitted: Handle response 31 | } 32 | } 33 | else { 34 | // Handle error 35 | } 36 | } 37 | 38 | }; 39 | } 40 | 41 | @Override 42 | public void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | setContentView(R.layout.activity_web_service); 45 | } 46 | 47 | public void doPost(View v) { 48 | Intent intent = new Intent(this, WebService.class); 49 | intent.setData(Uri.parse(postUrl)); 50 | intent.putExtra(WebService.INTENT_KEY_REQUEST_TYPE, WebService.POST); 51 | intent.putExtra(WebService.INTENT_KEY_JSON, "{\"foo\":\"bar\"}"); 52 | intent.putExtra(WebService.INTENT_KEY_RECEIVER, mReceiver); 53 | startService(intent); 54 | } 55 | 56 | public void doGet(View v) { 57 | Intent intent = new Intent(this, WebService.class); 58 | intent.setData(Uri.parse(getUrl)); 59 | intent.putExtra(WebService.INTENT_KEY_REQUEST_TYPE, WebService.GET); 60 | intent.putExtra(WebService.INTENT_KEY_RECEIVER, mReceiver); 61 | startService(intent); 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter13/Chapter13Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter13; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | import com.eat.chapter12.WebServiceActivity; 10 | 11 | public class Chapter13Activity extends Activity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_chapter13); 17 | } 18 | 19 | public void onExpandableContactListActivity(View v) { 20 | startActivity(new Intent(this, ExpandableContactListActivity.class)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter13/ExpandableContactListActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter13; 2 | 3 | import android.app.ExpandableListActivity; 4 | import android.content.AsyncQueryHandler; 5 | import android.content.ContentUris; 6 | import android.content.Context; 7 | import android.database.Cursor; 8 | import android.net.Uri; 9 | import android.os.Bundle; 10 | import android.provider.ContactsContract.CommonDataKinds.Phone; 11 | import android.provider.ContactsContract.Contacts; 12 | import android.widget.CursorTreeAdapter; 13 | import android.widget.SimpleCursorTreeAdapter; 14 | 15 | 16 | public class ExpandableContactListActivity extends ExpandableListActivity { 17 | 18 | private static final String[] CONTACTS_PROJECTION = new String[] { 19 | Contacts._ID, 20 | Contacts.DISPLAY_NAME 21 | }; 22 | private static final int GROUP_ID_COLUMN_INDEX = 0; 23 | 24 | private static final String[] PHONE_NUMBER_PROJECTION = new String[] { 25 | Phone._ID, 26 | Phone.NUMBER 27 | }; 28 | 29 | private static final int TOKEN_GROUP = 0; 30 | private static final int TOKEN_CHILD = 1; 31 | 32 | private QueryHandler mQueryHandler; 33 | private CursorTreeAdapter mAdapter; 34 | 35 | @Override 36 | public void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | 39 | // Set up our adapter 40 | mAdapter = new MyExpandableListAdapter( 41 | this, 42 | android.R.layout.simple_expandable_list_item_1, 43 | android.R.layout.simple_expandable_list_item_1, 44 | new String[] { Contacts.DISPLAY_NAME }, // Name for group layouts 45 | new int[] { android.R.id.text1 }, 46 | new String[] { Phone.NUMBER }, // Number for child layouts 47 | new int[] { android.R.id.text1 }); 48 | 49 | setListAdapter(mAdapter); 50 | 51 | mQueryHandler = new QueryHandler(this, mAdapter); 52 | 53 | // Query for people 54 | mQueryHandler.startQuery(TOKEN_GROUP, 55 | null, 56 | Contacts.CONTENT_URI, 57 | CONTACTS_PROJECTION, 58 | Contacts.HAS_PHONE_NUMBER, 59 | null, 60 | Contacts.DISPLAY_NAME + " ASC"); 61 | } 62 | 63 | @Override 64 | protected void onDestroy() { 65 | super.onDestroy(); 66 | mQueryHandler.cancelOperation(TOKEN_GROUP); 67 | mQueryHandler.cancelOperation(TOKEN_CHILD); 68 | mAdapter.changeCursor(null); 69 | mAdapter = null; 70 | } 71 | 72 | private static final class QueryHandler extends AsyncQueryHandler { 73 | private CursorTreeAdapter mAdapter; 74 | 75 | public QueryHandler(Context context, CursorTreeAdapter adapter) { 76 | super(context.getContentResolver()); 77 | this.mAdapter = adapter; 78 | } 79 | 80 | @Override 81 | protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 82 | switch (token) { 83 | case TOKEN_GROUP: 84 | mAdapter.setGroupCursor(cursor); 85 | break; 86 | 87 | case TOKEN_CHILD: 88 | int groupPosition = (Integer) cookie; 89 | mAdapter.setChildrenCursor(groupPosition, cursor); 90 | break; 91 | } 92 | } 93 | } 94 | 95 | public class MyExpandableListAdapter extends SimpleCursorTreeAdapter { 96 | 97 | // Note that the constructor does not take a Cursor. This is done to avoid querying the 98 | // database on the main thread. 99 | public MyExpandableListAdapter(Context context, int groupLayout, 100 | int childLayout, String[] groupFrom, int[] groupTo, String[] childrenFrom, 101 | int[] childrenTo) { 102 | 103 | super(context, null, groupLayout, groupFrom, groupTo, childLayout, childrenFrom, 104 | childrenTo); 105 | } 106 | 107 | @Override 108 | protected Cursor getChildrenCursor(Cursor groupCursor) { 109 | // Given the group, we return a cursor for all the children within that group 110 | 111 | // Return a cursor that points to this contact's phone numbers 112 | Uri.Builder builder = Contacts.CONTENT_URI.buildUpon(); 113 | ContentUris.appendId(builder, groupCursor.getLong(GROUP_ID_COLUMN_INDEX)); 114 | builder.appendEncodedPath(Contacts.Data.CONTENT_DIRECTORY); 115 | Uri phoneNumbersUri = builder.build(); 116 | 117 | mQueryHandler.startQuery(TOKEN_CHILD, 118 | groupCursor.getPosition(), 119 | phoneNumbersUri, 120 | PHONE_NUMBER_PROJECTION, 121 | Phone.MIMETYPE + "=?", 122 | new String[] { Phone.CONTENT_ITEM_TYPE }, 123 | null); 124 | 125 | return null; 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter14/BasicActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter14; 2 | 3 | import android.app.Activity; 4 | import android.app.LoaderManager; 5 | import android.content.Loader; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.TextView; 9 | 10 | import com.eat.R; 11 | 12 | public class BasicActivity extends Activity implements LoaderManager.LoaderCallbacks{ 13 | 14 | private static final int BASIC_LOADER_ID = 0; 15 | 16 | TextView tvResult; 17 | 18 | public void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_basic); 21 | tvResult = (TextView) findViewById(R.id.text_result); 22 | getLoaderManager().initLoader(BASIC_LOADER_ID, null, this); 23 | } 24 | 25 | @Override 26 | public Loader onCreateLoader(int id, Bundle args) { 27 | return new BasicLoader(this); 28 | } 29 | 30 | @Override 31 | public void onLoadFinished(Loader loader, Integer data) { 32 | tvResult.setText(Integer.toString(data)); 33 | } 34 | 35 | @Override 36 | public void onLoaderReset(Loader loader) { 37 | // Empty 38 | } 39 | 40 | public void onLoad(View v) { 41 | getLoaderManager().getLoader(BASIC_LOADER_ID).forceLoad(); 42 | } 43 | 44 | public void onCancel(View v) { 45 | getLoaderManager().getLoader(BASIC_LOADER_ID).cancelLoad(); 46 | } 47 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter14/BasicLoader.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter14; 2 | 3 | import android.content.AsyncTaskLoader; 4 | import android.content.Context; 5 | import android.os.SystemClock; 6 | import android.util.Log; 7 | 8 | import java.util.Random; 9 | 10 | public class BasicLoader extends AsyncTaskLoader{ 11 | 12 | private static final String TAG = "BasicLoader"; 13 | 14 | public BasicLoader(Context context) { 15 | super(context); 16 | } 17 | 18 | @Override 19 | protected boolean onCancelLoad() { 20 | Log.d(TAG, "onCancelLoad"); 21 | return super.onCancelLoad(); 22 | } 23 | 24 | @Override 25 | protected void onStartLoading() { 26 | super.onStartLoading(); 27 | forceLoad(); 28 | } 29 | 30 | @Override 31 | public Integer loadInBackground() { 32 | return loadData(); 33 | } 34 | 35 | private int loadData() { 36 | SystemClock.sleep(3000); 37 | Random rand = new Random(); 38 | int data = rand.nextInt(50); 39 | Log.d(TAG, "loadData - data = " + data); 40 | return data; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter14/Chapter14Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter14; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | import com.eat.chapter13.ExpandableContactListActivity; 10 | 11 | public class Chapter14Activity extends Activity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_chapter14); 17 | } 18 | 19 | public void onBasicActivity(View v) { 20 | startActivity(new Intent(this, BasicActivity.class)); 21 | } 22 | 23 | public void onChromeBookmarkActivity(View v) { 24 | startActivity(new Intent(this, ChromeBookmarkActivity.class)); 25 | } 26 | 27 | public void onContactActivity(View v) { 28 | startActivity(new Intent(this, ContactActivity.class)); 29 | } 30 | 31 | public void onFileActivity(View v) { 32 | startActivity(new Intent(this, FileActivity.class)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter14/ChromeBookmarkActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter14; 2 | 3 | import android.app.*; 4 | import android.content.*; 5 | import android.database.Cursor; 6 | import android.net.Uri; 7 | import android.os.Bundle; 8 | import android.provider.Browser; 9 | import android.view.View; 10 | import android.widget.AdapterView; 11 | import android.widget.ListView; 12 | import android.widget.SimpleCursorAdapter; 13 | 14 | import com.eat.R; 15 | 16 | public class ChromeBookmarkActivity extends Activity implements LoaderManager.LoaderCallbacks { 17 | 18 | // Definition of bookmark access information. 19 | public interface ChromeBookmark { 20 | final static int ID = 1; 21 | final static Uri URI= Uri.parse("content://com.android.chrome.browser/bookmarks"); 22 | final static String[] PROJECTION = { 23 | Browser.BookmarkColumns._ID, 24 | Browser.BookmarkColumns.TITLE, 25 | Browser.BookmarkColumns.URL 26 | }; 27 | } 28 | 29 | // AsyncQueryHandler with convenience methods for insertion and deletion of bookmarks. 30 | public static class ChromeBookmarkAsyncHandler extends AsyncQueryHandler { 31 | 32 | public ChromeBookmarkAsyncHandler(ContentResolver cr) { 33 | super(cr); 34 | } 35 | 36 | public void insert(String name, String url) { 37 | ContentValues cv = new ContentValues(); 38 | cv.put(Browser.BookmarkColumns.BOOKMARK, 1); 39 | cv.put(Browser.BookmarkColumns.TITLE, name); 40 | cv.put(Browser.BookmarkColumns.URL, url); 41 | startInsert(0, null, ChromeBookmark.URI, cv); 42 | } 43 | 44 | public void delete(String name) { 45 | String where = Browser.BookmarkColumns.TITLE + "=?"; 46 | String[] args = new String[] { name }; 47 | startDelete(0, null, ChromeBookmark.URI, where, args); 48 | } 49 | } 50 | 51 | 52 | ListView mListBookmarks; 53 | SimpleCursorAdapter mAdapter; 54 | ChromeBookmarkAsyncHandler mChromeBookmarkAsyncHandler; 55 | 56 | public void onCreate(Bundle savedInstanceState) { 57 | super.onCreate(savedInstanceState); 58 | setContentView(R.layout.activity_bookmarks); 59 | mListBookmarks = (ListView) findViewById(R.id.list_bookmarks); 60 | 61 | mChromeBookmarkAsyncHandler = new ChromeBookmarkAsyncHandler(getContentResolver()); 62 | 63 | initAdapter(); 64 | 65 | getLoaderManager().initLoader(ChromeBookmark.ID, null, this); 66 | } 67 | 68 | private void initAdapter() { 69 | mAdapter = new SimpleCursorAdapter(this, 70 | android.R.layout.simple_list_item_1, null, 71 | new String[] { Browser.BookmarkColumns.TITLE }, 72 | new int[] { android.R.id.text1}, 0); 73 | mListBookmarks.setAdapter(mAdapter); 74 | mListBookmarks.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 75 | @Override 76 | public boolean onItemLongClick(AdapterView adapterView, View view, int pos, long id) { 77 | Cursor c = ((SimpleCursorAdapter) adapterView.getAdapter()).getCursor(); 78 | c.moveToPosition(pos); 79 | int i = c.getColumnIndex(Browser.BookmarkColumns.TITLE); 80 | mChromeBookmarkAsyncHandler.delete(c.getString(i)); 81 | return true; 82 | } 83 | }); 84 | } 85 | 86 | @Override 87 | public Loader onCreateLoader(int i, Bundle bundle) { 88 | return new CursorLoader(this, ChromeBookmark.URI, 89 | ChromeBookmark.PROJECTION, null, null, 90 | Browser.BookmarkColumns.TITLE + " ASC"); 91 | } 92 | 93 | @Override 94 | public void onLoadFinished(Loader loader, Cursor newCursor) { 95 | mAdapter.swapCursor(newCursor); 96 | } 97 | 98 | @Override 99 | public void onLoaderReset(Loader loader) { 100 | mAdapter.swapCursor(null); 101 | } 102 | 103 | 104 | public void onAddBookmark(View v) { 105 | FragmentTransaction ft = getFragmentManager().beginTransaction(); 106 | Fragment prev = getFragmentManager().findFragmentByTag("dialog"); 107 | // Remove previous dialogs 108 | if (prev != null) { 109 | ft.remove(prev); 110 | } 111 | ft.addToBackStack(null); 112 | // Create and show the dialog. 113 | DialogFragment newFragment = EditBookmarkDialog.newInstance(mChromeBookmarkAsyncHandler); 114 | newFragment.show(ft, "dialog"); 115 | } 116 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter14/ContactActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter14; 2 | 3 | import android.app.ListActivity; 4 | import android.app.LoaderManager; 5 | import android.content.CursorLoader; 6 | import android.content.Loader; 7 | import android.database.Cursor; 8 | import android.os.Bundle; 9 | import android.provider.ContactsContract; 10 | import android.widget.SimpleCursorAdapter; 11 | 12 | public class ContactActivity extends ListActivity implements LoaderManager.LoaderCallbacks{ 13 | 14 | private static final int CONTACT_NAME_LOADER_ID = 0; 15 | 16 | // Projection that defines contact display name only 17 | static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { 18 | ContactsContract.Contacts._ID, 19 | ContactsContract.Contacts.DISPLAY_NAME 20 | }; 21 | 22 | SimpleCursorAdapter mAdapter; 23 | 24 | public void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | initAdapter(); 27 | getLoaderManager().initLoader(CONTACT_NAME_LOADER_ID, null, this); 28 | } 29 | 30 | private void initAdapter() { 31 | mAdapter = new SimpleCursorAdapter(this, 32 | android.R.layout.simple_list_item_1, null, 33 | new String[] { ContactsContract.Contacts.DISPLAY_NAME }, 34 | new int[] { android.R.id.text1}, 0); 35 | setListAdapter(mAdapter); 36 | } 37 | 38 | @Override 39 | public Loader onCreateLoader(int id, Bundle args) { 40 | return new CursorLoader(this, ContactsContract.Contacts.CONTENT_URI, 41 | CONTACTS_SUMMARY_PROJECTION, null, null, 42 | ContactsContract.Contacts.DISPLAY_NAME + " ASC"); 43 | } 44 | 45 | @Override 46 | public void onLoadFinished(Loader loader, Cursor c) { 47 | mAdapter.swapCursor(c); 48 | } 49 | 50 | @Override 51 | public void onLoaderReset(Loader arg0) { 52 | mAdapter.swapCursor(null); 53 | } 54 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter14/EditBookmarkDialog.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter14; 2 | 3 | import android.app.DialogFragment; 4 | import android.os.Bundle; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Button; 9 | import android.widget.EditText; 10 | 11 | import com.eat.R; 12 | 13 | public class EditBookmarkDialog extends DialogFragment { 14 | 15 | static EditBookmarkDialog newInstance(ChromeBookmarkActivity.ChromeBookmarkAsyncHandler asyncQueryHandler) { 16 | EditBookmarkDialog dialog = new EditBookmarkDialog(asyncQueryHandler); 17 | return dialog; 18 | } 19 | 20 | ChromeBookmarkActivity.ChromeBookmarkAsyncHandler mAsyncQueryHandler; 21 | 22 | public EditBookmarkDialog(ChromeBookmarkActivity.ChromeBookmarkAsyncHandler asyncQueryHandler) { 23 | mAsyncQueryHandler = asyncQueryHandler; 24 | } 25 | 26 | @Override 27 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 28 | Bundle savedInstanceState) { 29 | View v = inflater.inflate(R.layout.dialog_edit_bookmark, container, false); 30 | final EditText editName = (EditText) v.findViewById(R.id.edit_name); 31 | final EditText editUrl = (EditText) v.findViewById(R.id.edit_url); 32 | Button buttonSave = (Button) v.findViewById(R.id.button_save); 33 | 34 | buttonSave.setOnClickListener(new View.OnClickListener() { 35 | public void onClick(View v) { 36 | String name = editName.getText().toString(); 37 | String url = editUrl.getText().toString(); 38 | mAsyncQueryHandler.insert(name, url); 39 | dismiss(); 40 | } 41 | }); 42 | 43 | return v; 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter14/FileActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter14; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | 10 | import java.io.BufferedOutputStream; 11 | import java.io.File; 12 | import java.io.FileOutputStream; 13 | import java.io.OutputStream; 14 | 15 | public class FileActivity extends Activity { 16 | 17 | private static final String TAG = "FileActivity"; 18 | 19 | private static int mCount; // A count to append to file names 20 | 21 | public void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_file); 24 | } 25 | 26 | public void onAddFile(View v) { 27 | String filename = "testfile" + mCount++ + ".txt"; 28 | File file = new File(this.getFilesDir(), filename); 29 | OutputStream out = null; 30 | try { 31 | out = new BufferedOutputStream(new FileOutputStream(file)); 32 | out.write(new String("Test").getBytes("UTF-8")); 33 | out.close(); 34 | } catch (Exception e){ 35 | 36 | } 37 | Log.d(TAG, "onAddFile - path = " + file.getAbsolutePath()); 38 | 39 | } 40 | 41 | public void onRemoveFiles(View v) { 42 | removeAllFiles(); 43 | } 44 | 45 | private void removeAllFiles() { 46 | File dir = getFilesDir(); 47 | File[] files = dir.listFiles(); 48 | for (File file : files) { 49 | file.delete(); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter14/FileListFragment.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter14; 2 | 3 | import android.app.ListFragment; 4 | import android.app.LoaderManager; 5 | import android.content.Loader; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.widget.ArrayAdapter; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class FileListFragment extends ListFragment implements 14 | LoaderManager.LoaderCallbacks>{ 15 | 16 | private static final int FILE_LOADER_ID = 1; 17 | 18 | private ArrayAdapter mFileAdapter; 19 | private List mFileNames = new ArrayList(); 20 | 21 | @Override 22 | public void onActivityCreated(Bundle savedInstanceState) { 23 | super.onActivityCreated(savedInstanceState); 24 | getLoaderManager().initLoader(FILE_LOADER_ID, null, this); 25 | setEmptyText("No files in directory"); 26 | setListShown(false); 27 | 28 | mFileAdapter = new ArrayAdapter(getActivity(), 29 | android.R.layout.simple_list_item_1, android.R.id.text1, mFileNames); 30 | mFileAdapter.setNotifyOnChange(true); 31 | setListAdapter(mFileAdapter); 32 | } 33 | 34 | @Override 35 | public Loader> onCreateLoader(int i, Bundle bundle) { 36 | return new FileLoader(getActivity()); 37 | } 38 | 39 | @Override 40 | public void onLoadFinished(Loader> fileLoader, 41 | List fileNames) { 42 | mFileAdapter.clear(); 43 | mFileAdapter.addAll(fileNames); 44 | setListShown(true); 45 | } 46 | 47 | @Override 48 | public void onLoaderReset(Loader> fileLoader) { 49 | mFileNames = null; 50 | mFileAdapter.clear(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter14/FileLoader.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter14; 2 | 3 | import android.content.AsyncTaskLoader; 4 | import android.content.Context; 5 | import android.os.FileObserver; 6 | import android.util.Log; 7 | 8 | import java.io.File; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | 12 | /** 13 | * 1. Data observation 14 | * 2. Load data on background thread when the content has changed. 15 | * 3. Cache data 16 | * 4. Only deliver data when started. 17 | * 5. Release resources on reset. 18 | * 6. Cancel load. 19 | * 7. Handle deliverResult 20 | */ 21 | public class FileLoader extends AsyncTaskLoader> { 22 | // Cache the list of file names. 23 | private List mFileNames; 24 | 25 | 26 | // 1. Data observation 27 | private class SdCardObserver extends FileObserver { 28 | 29 | public SdCardObserver(String path) { 30 | super(path, FileObserver.CREATE|FileObserver.DELETE); 31 | } 32 | 33 | @Override 34 | public void onEvent(int event, String path) { 35 | // Report that a content change has occurred. 36 | // This call will force a new asynchronous data load if the loader is started 37 | // otherwise it will keep a reference that the data has changed for future loads. 38 | onContentChanged(); 39 | } 40 | } 41 | 42 | private SdCardObserver mSdCardObserver; 43 | 44 | public FileLoader(Context context) { 45 | super(context); 46 | String path = context.getFilesDir().getPath(); 47 | mSdCardObserver = new SdCardObserver(path); 48 | } 49 | 50 | 51 | 52 | /** 53 | * Decide whether a load should be initiated or not. 54 | */ 55 | @Override 56 | protected void onStartLoading() { 57 | super.onStartLoading(); 58 | mSdCardObserver.startWatching(); 59 | 60 | if (mFileNames != null) { 61 | // Return the cache 62 | deliverResult(mFileNames); 63 | } 64 | 65 | // Force a data load if there are no previous data 66 | // or if the content has been marked as changed earlier but not delivered. 67 | if (takeContentChanged() || mFileNames == null) { 68 | forceLoad(); 69 | } 70 | } 71 | 72 | @Override 73 | public List loadInBackground() { 74 | File directory = getContext().getFilesDir(); 75 | return Arrays.asList(directory.list()); 76 | } 77 | 78 | @Override 79 | public void deliverResult(List data) { 80 | if (isReset()) { 81 | return; 82 | } 83 | 84 | // Cache the data 85 | mFileNames = data; 86 | 87 | // Only deliver result if the loader is started. 88 | if (isStarted()) { 89 | super.deliverResult(data); 90 | } 91 | } 92 | 93 | @Override 94 | protected void onStopLoading() { 95 | super.onStopLoading(); 96 | cancelLoad(); 97 | } 98 | 99 | @Override 100 | protected void onReset() { 101 | super.onReset(); 102 | mSdCardObserver.stopWatching(); 103 | clearResources(); 104 | } 105 | 106 | private void clearResources() { 107 | mFileNames = null; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter2/Chapter2Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter2; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | import com.eat.R; 7 | 8 | public class Chapter2Activity extends Activity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_chapter2); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter3/Chapter3Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter3; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | import com.eat.R; 7 | 8 | public class Chapter3Activity extends Activity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_chapter3); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter4/Chapter4Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter4; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | 10 | public class Chapter4Activity extends Activity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_chapter4); 16 | } 17 | 18 | public void onPipeActivity(View v) { 19 | startActivity(new Intent(this, PipeExampleActivity.class)); 20 | } 21 | 22 | public void onLooperActivity(View v) { 23 | startActivity(new Intent(this, LooperActivity.class)); 24 | } 25 | 26 | public void onConsumeAndQuitThreadActivity(View v) { 27 | startActivity(new Intent(this, ConsumeAndQuitThreadActivity.class)); 28 | } 29 | 30 | public void onHandlerExampleActivity(View v) { 31 | startActivity(new Intent(this, HandlerExampleActivity.class)); 32 | } 33 | 34 | public void onHandlerCallbackActivity(View v) { 35 | startActivity(new Intent(this, HandlerCallbackActivity.class)); 36 | } 37 | 38 | public void onMQDebugActivity(View v) { 39 | startActivity(new Intent(this, MQDebugActivity.class)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter4/ConsumeAndQuitThreadActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter4; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | import android.os.Message; 8 | import android.os.MessageQueue; 9 | import android.os.SystemClock; 10 | 11 | import java.util.Random; 12 | 13 | 14 | public class ConsumeAndQuitThreadActivity extends Activity { 15 | 16 | 17 | public void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | 20 | final ConsumeAndQuitThread consumeAndQuitThread = new ConsumeAndQuitThread(); 21 | consumeAndQuitThread.start(); 22 | for (int i = 0; i < 10; i++) { 23 | new Thread(new Runnable() { 24 | @Override 25 | public void run() { 26 | for (int i = 0; i < 10; i++) { 27 | SystemClock.sleep(new Random().nextInt(10)); 28 | consumeAndQuitThread.enqueueData(i); 29 | } 30 | } 31 | }).start(); 32 | } 33 | } 34 | 35 | private static class ConsumeAndQuitThread extends Thread implements MessageQueue.IdleHandler { 36 | 37 | private static final String THREAD_NAME = "ConsumeAndQuitThread"; 38 | 39 | public Handler mConsumerHandler; 40 | private boolean mIsFirstIdle = true; 41 | 42 | public ConsumeAndQuitThread() { 43 | super(THREAD_NAME); 44 | } 45 | 46 | @Override 47 | public void run() { 48 | Looper.prepare(); 49 | 50 | mConsumerHandler = new Handler() { 51 | @Override 52 | public void handleMessage(Message msg) { 53 | // Consume data 54 | } 55 | }; 56 | Looper.myQueue().addIdleHandler(this); 57 | Looper.loop(); 58 | } 59 | 60 | 61 | @Override 62 | public boolean queueIdle() { 63 | if (mIsFirstIdle) { 64 | mIsFirstIdle = false; 65 | return true; 66 | } 67 | mConsumerHandler.getLooper().quit(); 68 | return false; 69 | } 70 | 71 | public void enqueueData(int i) { 72 | mConsumerHandler.sendEmptyMessage(i); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter4/HandlerCallbackActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter4; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Message; 7 | import android.view.View; 8 | 9 | import com.eat.R; 10 | 11 | 12 | public class HandlerCallbackActivity extends Activity implements Handler.Callback { 13 | 14 | @Override 15 | public void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_handler_callback); 18 | } 19 | 20 | @Override 21 | public boolean handleMessage(Message msg) { 22 | switch (msg.what) { 23 | case 1: 24 | msg.what = 11; 25 | return true; 26 | default: 27 | msg.what = 22; 28 | return false; 29 | } 30 | } 31 | 32 | public void onHandlerCallback(View v) { 33 | Handler handler = new Handler(this) { 34 | @Override 35 | public void handleMessage(Message msg) { 36 | // Process message 37 | } 38 | }; 39 | handler.sendEmptyMessage(1); 40 | handler.sendEmptyMessage(2); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter4/HandlerExampleActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter4; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | import android.os.Message; 8 | import android.os.SystemClock; 9 | import android.view.View; 10 | import android.widget.Button; 11 | import android.widget.ProgressBar; 12 | import android.widget.TextView; 13 | 14 | import com.eat.R; 15 | 16 | import java.util.Random; 17 | 18 | 19 | public class HandlerExampleActivity extends Activity { 20 | 21 | private final static int SHOW_PROGRESS_BAR = 1; 22 | private final static int HIDE_PROGRESS_BAR = 0; 23 | private BackgroundThread mBackgroundThread; 24 | 25 | private TextView mText; 26 | private Button mButton; 27 | private ProgressBar mProgressBar; 28 | 29 | @Override 30 | public void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_handler_example); 33 | 34 | mBackgroundThread = new BackgroundThread(); 35 | mBackgroundThread.start(); 36 | 37 | mText = (TextView) findViewById(R.id.text); 38 | mProgressBar = (ProgressBar) findViewById(R.id.progress); 39 | mButton = (Button) findViewById(R.id.button); 40 | mButton.setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | mBackgroundThread.doWork(); 44 | } 45 | }); 46 | } 47 | 48 | @Override 49 | protected void onDestroy() { 50 | super.onDestroy(); 51 | mBackgroundThread.exit(); 52 | } 53 | 54 | private final Handler mUiHandler = new Handler() { 55 | public void handleMessage(Message msg) { 56 | 57 | switch(msg.what) { 58 | case SHOW_PROGRESS_BAR: 59 | mProgressBar.setVisibility(View.VISIBLE); 60 | break; 61 | case HIDE_PROGRESS_BAR: 62 | mText.setText(String.valueOf(msg.arg1)); 63 | mProgressBar.setVisibility(View.INVISIBLE); 64 | break; 65 | } 66 | } 67 | }; 68 | 69 | private class BackgroundThread extends Thread { 70 | 71 | private Handler mBackgroundHandler; 72 | 73 | public void run() { 74 | Looper.prepare(); 75 | mBackgroundHandler = new Handler(); 76 | Looper.loop(); 77 | } 78 | 79 | public void doWork() { 80 | mBackgroundHandler.post(new Runnable() { 81 | @Override 82 | public void run() { 83 | Message uiMsg = mUiHandler.obtainMessage(SHOW_PROGRESS_BAR, 0, 84 | 0, null); 85 | mUiHandler.sendMessage(uiMsg); 86 | 87 | Random r = new Random(); 88 | int randomInt = r.nextInt(5000); 89 | SystemClock.sleep(randomInt); 90 | 91 | uiMsg = mUiHandler.obtainMessage(HIDE_PROGRESS_BAR, randomInt, 92 | 0, null); 93 | mUiHandler.sendMessage(uiMsg); 94 | } 95 | }); 96 | } 97 | 98 | public void exit() { 99 | mBackgroundHandler.getLooper().quit(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter4/LooperActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter4; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | import android.os.Message; 8 | import android.view.View; 9 | 10 | import com.eat.R; 11 | 12 | 13 | public class LooperActivity extends Activity { 14 | 15 | LooperThread mLooperThread; 16 | 17 | private static class LooperThread extends Thread { 18 | 19 | public Handler mHandler; 20 | 21 | public void run() { 22 | Looper.prepare(); 23 | mHandler = new Handler() { 24 | public void handleMessage(Message msg) { 25 | if(msg.what == 0) { 26 | doLongRunningOperation(); 27 | } 28 | } 29 | }; 30 | Looper.loop(); 31 | } 32 | 33 | private void doLongRunningOperation() { 34 | // Add long running operation here. 35 | } 36 | } 37 | 38 | public void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.activity_looper); 41 | mLooperThread = new LooperThread(); 42 | mLooperThread.start(); 43 | } 44 | 45 | public void onClick(View v) { 46 | if (mLooperThread.mHandler != null) { 47 | Message msg = mLooperThread.mHandler.obtainMessage(0); 48 | mLooperThread.mHandler.sendMessage(msg); 49 | } 50 | } 51 | 52 | protected void onDestroy() { 53 | super.onDestroy(); 54 | mLooperThread.mHandler.getLooper().quit(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter4/MQDebugActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter4; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | import android.os.Message; 8 | import android.util.Log; 9 | import android.util.LogPrinter; 10 | import android.view.View; 11 | 12 | import com.eat.R; 13 | 14 | 15 | public class MQDebugActivity extends Activity { 16 | 17 | private static final String TAG = "EAT"; 18 | Handler mWorkerHandler; 19 | 20 | public void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_mq_debug); 23 | 24 | Thread t = new Thread() { 25 | @Override 26 | public void run() { 27 | Looper.prepare(); 28 | mWorkerHandler = new Handler() { 29 | @Override 30 | public void handleMessage(Message msg) { 31 | Log.d(TAG, "handleMessage - what = " + msg.what); 32 | } 33 | }; 34 | Looper.loop(); 35 | } 36 | }; 37 | t.start(); 38 | } 39 | 40 | // Called on button click, i.e. from the UI thread. 41 | public void onClick(View v) { 42 | mWorkerHandler.sendEmptyMessageDelayed(1, 2000); 43 | mWorkerHandler.sendEmptyMessage(2); 44 | mWorkerHandler.obtainMessage(3, 0, 0, new Object()).sendToTarget(); 45 | mWorkerHandler.sendEmptyMessageDelayed(4, 300); 46 | mWorkerHandler.postDelayed(new Runnable() { 47 | @Override 48 | public void run() { 49 | Log.d(TAG, "Execute"); 50 | } 51 | }, 400); 52 | mWorkerHandler.sendEmptyMessage(5); 53 | 54 | mWorkerHandler.dump(new LogPrinter(Log.DEBUG, TAG), ""); 55 | } 56 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter4/PipeExampleActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter4; 2 | 3 | import android.text.Editable; 4 | 5 | 6 | import android.app.Activity; 7 | import android.os.Bundle; 8 | import android.text.TextWatcher; 9 | import android.util.Log; 10 | import android.widget.EditText; 11 | import com.eat.R; 12 | 13 | import java.io.IOException; 14 | import java.io.PipedReader; 15 | import java.io.PipedWriter; 16 | 17 | 18 | public class PipeExampleActivity extends Activity { 19 | 20 | private static final String TAG = "PipeExampleActivity"; 21 | private EditText editText; 22 | 23 | PipedReader r; 24 | PipedWriter w; 25 | 26 | private Thread workerThread; 27 | 28 | public void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | 31 | r = new PipedReader(); 32 | w = new PipedWriter(); 33 | 34 | try { 35 | w.connect(r); 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | 40 | setContentView(R.layout.activity_pipe); 41 | editText = (EditText) findViewById(R.id.edit_text); 42 | editText.addTextChangedListener(new TextWatcher() { 43 | @Override 44 | public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) { 45 | } 46 | 47 | @Override 48 | public void onTextChanged(CharSequence charSequence, int start, int before, int count) { 49 | try { 50 | // Only handle addition of characters 51 | if(count > before) { 52 | // Write the last entered character to the pipe 53 | w.write(charSequence.subSequence(before, count).toString()); 54 | } 55 | } catch (IOException e) { 56 | e.printStackTrace(); 57 | } 58 | } 59 | 60 | @Override 61 | public void afterTextChanged(Editable editable) { 62 | } 63 | }); 64 | 65 | workerThread = new Thread(new TextHandlerTask(r)); 66 | workerThread.start(); 67 | } 68 | 69 | @Override 70 | protected void onDestroy() { 71 | super.onDestroy(); 72 | workerThread.interrupt(); 73 | try { 74 | r.close(); 75 | w.close(); 76 | } catch (IOException e) { 77 | } 78 | } 79 | 80 | private static class TextHandlerTask implements Runnable { 81 | private final PipedReader reader; 82 | 83 | public TextHandlerTask(PipedReader reader){ 84 | this.reader = reader; 85 | } 86 | @Override 87 | public void run() { 88 | while(!Thread.currentThread().isInterrupted()){ 89 | try { 90 | int i; 91 | while((i = reader.read()) != -1){ 92 | char c = (char) i; 93 | //ADD TEXT PROCESSING LOGIC HERE 94 | Log.d(TAG, "char = " + c); 95 | } 96 | 97 | } catch (IOException e) { 98 | e.printStackTrace(); 99 | } 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter5/Chapter5Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter5; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | 10 | public class Chapter5Activity extends Activity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_chapter5); 16 | } 17 | 18 | public void onMessengerOnewayActivity(View v) { 19 | startActivity(new Intent(this, MessengerOnewayActivity.class)); 20 | } 21 | 22 | public void onMessengerTwowayActivity(View v) { 23 | startActivity(new Intent(this, MessengerTwowayActivity.class)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter5/MessengerOnewayActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter5; 2 | 3 | import android.app.Activity; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.ServiceConnection; 8 | import android.os.Bundle; 9 | import android.os.IBinder; 10 | import android.os.Message; 11 | import android.os.Messenger; 12 | import android.os.RemoteException; 13 | import android.view.View; 14 | 15 | import com.eat.R; 16 | 17 | 18 | /** 19 | * Activity passing messages to remote service via Messenger. 20 | */ 21 | public class MessengerOnewayActivity extends Activity { 22 | 23 | private boolean mBound = false; 24 | private Messenger mRemoteService = null; 25 | 26 | private ServiceConnection mRemoteConnection = new ServiceConnection() { 27 | 28 | public void onServiceConnected(ComponentName className, IBinder service) { 29 | mRemoteService = new Messenger(service); 30 | mBound = true; 31 | } 32 | 33 | public void onServiceDisconnected(ComponentName className) { 34 | mRemoteService = null; 35 | mBound = false; 36 | } 37 | }; 38 | 39 | public void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setContentView(R.layout.activity_messenger_client); 42 | } 43 | 44 | public void onBindClick(View v) { 45 | Intent intent = new Intent("com.eat.chapter5.ACTION_BIND"); 46 | bindService(intent, mRemoteConnection, Context.BIND_AUTO_CREATE); 47 | 48 | } 49 | 50 | public void onUnbindClick(View v) { 51 | if (mBound) { 52 | unbindService(mRemoteConnection); 53 | mBound = false; 54 | } 55 | 56 | } 57 | 58 | public void onSendClick(View v) { 59 | if (mBound) { 60 | try { 61 | mRemoteService.send(Message.obtain(null, 2, 0, 0)); 62 | } catch (RemoteException e) { 63 | // Empty 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter5/MessengerTwowayActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter5; 2 | 3 | import android.app.Activity; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.ServiceConnection; 8 | import android.os.Bundle; 9 | import android.os.Handler; 10 | import android.os.IBinder; 11 | import android.os.Message; 12 | import android.os.Messenger; 13 | import android.os.RemoteException; 14 | import android.util.Log; 15 | import android.view.View; 16 | 17 | import com.eat.R; 18 | 19 | 20 | /** 21 | * Activity passing messages to remote service via Messenger. 22 | */ 23 | public class MessengerTwowayActivity extends Activity { 24 | private static final String TAG = "MessengerTwowayActivity"; 25 | private boolean mBound = false; 26 | private Messenger mRemoteService = null; 27 | 28 | private ServiceConnection mRemoteConnection = new ServiceConnection() { 29 | 30 | public void onServiceConnected(ComponentName className, IBinder service) { 31 | mRemoteService = new Messenger(service); 32 | mBound = true; 33 | } 34 | 35 | public void onServiceDisconnected(ComponentName className) { 36 | mRemoteService = null; 37 | mBound = false; 38 | } 39 | }; 40 | 41 | public void onCreate(Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | setContentView(R.layout.activity_messenger_client); 44 | } 45 | 46 | public void onBindClick(View v) { 47 | Intent intent = new Intent("com.eat.chapter5.ACTION_BIND"); 48 | bindService(intent, mRemoteConnection, Context.BIND_AUTO_CREATE); 49 | } 50 | 51 | public void onUnbindClick(View v) { 52 | if (mBound) { 53 | unbindService(mRemoteConnection); 54 | mBound = false; 55 | } 56 | 57 | } 58 | 59 | public void onSendClick(View v) { 60 | if (mBound) { 61 | try { 62 | Message msg = Message.obtain(null, 1, 0, 0); 63 | msg.replyTo = new Messenger(new Handler() { 64 | @Override 65 | public void handleMessage(Message msg) { 66 | Log.d(TAG, "Message sent back - msg.what = " + msg.what); 67 | } 68 | }); 69 | mRemoteService.send(msg); 70 | } catch (RemoteException e) { 71 | Log.e(TAG, e.getMessage()); 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter5/WorkerThreadService.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter5; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.Handler; 6 | import android.os.IBinder; 7 | import android.os.Looper; 8 | import android.os.Message; 9 | import android.os.Messenger; 10 | import android.os.RemoteException; 11 | import android.util.Log; 12 | 13 | 14 | public class WorkerThreadService extends Service { 15 | 16 | private static final String TAG = "WorkerThreadService"; 17 | WorkerThread mWorkerThread; 18 | Messenger mWorkerMessenger; 19 | 20 | @Override 21 | public void onCreate() { 22 | super.onCreate(); 23 | mWorkerThread = new WorkerThread(); 24 | mWorkerThread.start(); 25 | } 26 | 27 | // Worker thread has prepared a looper and handler. 28 | private void onWorkerPrepared() { 29 | Log.d(TAG, "onWorkerPrepared"); 30 | mWorkerMessenger = new Messenger(mWorkerThread.mWorkerHandler); 31 | synchronized(this) { 32 | notifyAll(); 33 | } 34 | } 35 | 36 | public IBinder onBind(Intent intent) { 37 | Log.d(TAG, "onBind"); 38 | synchronized (this) { 39 | while (mWorkerMessenger == null) { 40 | try { 41 | wait(); 42 | } catch (InterruptedException e) { 43 | // Empty 44 | } 45 | } 46 | } 47 | return mWorkerMessenger.getBinder(); 48 | } 49 | 50 | @Override 51 | public void onDestroy() { 52 | super.onDestroy(); 53 | mWorkerThread.quit(); 54 | } 55 | 56 | private class WorkerThread extends Thread { 57 | 58 | Handler mWorkerHandler; 59 | 60 | @Override 61 | public void run() { 62 | Looper.prepare(); 63 | mWorkerHandler = new Handler() { 64 | @Override 65 | public void handleMessage(Message msg) { 66 | switch (msg.what) { 67 | case 1: 68 | try { 69 | msg.replyTo.send(Message.obtain(null, msg.what, 0, 0)); 70 | } catch (RemoteException e) { 71 | Log.e(TAG, e.getMessage()); 72 | } 73 | break; 74 | case 2: 75 | Log.d(TAG, "Message received"); 76 | break; 77 | } 78 | 79 | } 80 | }; 81 | onWorkerPrepared(); 82 | Looper.loop(); 83 | } 84 | 85 | public void quit() { 86 | mWorkerHandler.getLooper().quit(); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter6/Chapter6Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter6; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | import com.eat.R; 7 | 8 | public class Chapter6Activity extends Activity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_chapter6); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter7/Chapter7Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter7; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | import com.eat.chapter5.MessengerOnewayActivity; 10 | import com.eat.chapter5.MessengerTwowayActivity; 11 | 12 | public class Chapter7Activity extends Activity { 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_chapter7); 18 | } 19 | 20 | public void onThreadRetainActivity(View v) { 21 | startActivity(new Intent(this, ThreadRetainActivity.class)); 22 | } 23 | 24 | public void onThreadRetainFragment(View v) { 25 | startActivity(new Intent(this, ThreadRetainWithFragmentActivity.class)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter7/ThreadFragment.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter7; 2 | 3 | import android.app.Activity; 4 | import android.app.Fragment; 5 | import android.os.Bundle; 6 | import android.os.SystemClock; 7 | 8 | public class ThreadFragment extends Fragment { 9 | 10 | private ThreadRetainWithFragmentActivity mActivity; 11 | private MyThread t; 12 | 13 | private class MyThread extends Thread { 14 | 15 | @Override 16 | public void run() { 17 | final String text = getTextFromNetwork(); 18 | mActivity.setText(text); 19 | } 20 | 21 | // Long operation 22 | private String getTextFromNetwork() { 23 | // Simulate network operation 24 | SystemClock.sleep(5000); 25 | return "Text from network"; 26 | } 27 | } 28 | 29 | @Override 30 | public void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setRetainInstance(true); 33 | } 34 | 35 | @Override 36 | public void onAttach(Activity activity) { 37 | super.onAttach(activity); 38 | mActivity = (ThreadRetainWithFragmentActivity) activity; 39 | } 40 | 41 | @Override 42 | public void onDetach() { 43 | super.onDetach(); 44 | mActivity = null; 45 | } 46 | 47 | public void execute() { 48 | t = new MyThread(); 49 | t.start(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter7/ThreadRetainActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter7; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.SystemClock; 6 | import android.view.View; 7 | import android.widget.TextView; 8 | 9 | import com.eat.R; 10 | 11 | 12 | public class ThreadRetainActivity extends Activity { 13 | 14 | private static class MyThread extends Thread { 15 | private ThreadRetainActivity mActivity; 16 | 17 | public MyThread(ThreadRetainActivity activity) { 18 | mActivity = activity; 19 | } 20 | 21 | private void attach(ThreadRetainActivity activity) { 22 | mActivity = activity; 23 | } 24 | 25 | @Override 26 | public void run() { 27 | final String text = getTextFromNetwork(); 28 | mActivity.setText(text); 29 | } 30 | 31 | // Long operation 32 | private String getTextFromNetwork() { 33 | // Simulate network operation 34 | SystemClock.sleep(5000); 35 | return "Text from network"; 36 | } 37 | } 38 | 39 | private static MyThread t; 40 | private TextView textView; 41 | 42 | @Override 43 | public void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(R.layout.activity_retain_thread); 46 | textView = (TextView) findViewById(R.id.text_retain); 47 | Object retainedObject = getLastNonConfigurationInstance(); 48 | if (retainedObject != null) { 49 | t = (MyThread) retainedObject; 50 | t.attach(this); 51 | } 52 | } 53 | 54 | @Override 55 | 56 | public Object onRetainNonConfigurationInstance() { 57 | if (t != null && t.isAlive()) { 58 | return t; 59 | } 60 | return null; 61 | } 62 | 63 | public void onStartThread(View v) { 64 | t = new MyThread(this); 65 | t.start(); 66 | } 67 | 68 | private void setText(final String text) { 69 | runOnUiThread(new Runnable() { 70 | @Override 71 | public void run() { 72 | textView.setText(text); 73 | } 74 | }); 75 | } 76 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter7/ThreadRetainWithFragmentActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter7; 2 | 3 | import android.app.Activity; 4 | import android.app.FragmentManager; 5 | import android.app.FragmentTransaction; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.TextView; 9 | import com.eat.R; 10 | 11 | 12 | public class ThreadRetainWithFragmentActivity extends Activity { 13 | 14 | private static final String TAG = "ThreadRetainActivity"; 15 | 16 | private static final String KEY_TEXT = "key_text"; 17 | 18 | private ThreadFragment mThreadFragment; 19 | 20 | private TextView mTextView; 21 | 22 | 23 | public void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_retain_thread); 26 | mTextView = (TextView) findViewById(R.id.text_retain); 27 | 28 | FragmentManager manager = getFragmentManager(); 29 | mThreadFragment = (ThreadFragment) manager.findFragmentByTag("threadfragment"); 30 | 31 | if (mThreadFragment == null) { 32 | FragmentTransaction transaction = manager.beginTransaction(); 33 | mThreadFragment = new ThreadFragment(); 34 | transaction.add(mThreadFragment, "threadfragment"); 35 | transaction.commit(); 36 | } 37 | } 38 | 39 | @Override 40 | protected void onRestoreInstanceState(Bundle savedInstanceState) { 41 | super.onRestoreInstanceState(savedInstanceState); 42 | mTextView.setText(savedInstanceState.getString(KEY_TEXT)); 43 | } 44 | 45 | @Override 46 | protected void onSaveInstanceState(Bundle outState) { 47 | super.onSaveInstanceState(outState); 48 | outState.putString(KEY_TEXT, (String)mTextView.getText()); 49 | } 50 | 51 | // Method called to start a worker thread 52 | public void onStartThread(View v) { 53 | mThreadFragment.execute(); 54 | } 55 | 56 | public void setText(final String text) { 57 | runOnUiThread(new Runnable() { 58 | @Override 59 | public void run() { 60 | mTextView.setText(text); 61 | } 62 | }); 63 | } 64 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter8/ChainedNetworkActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter8; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.app.Dialog; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.os.HandlerThread; 9 | import android.os.Message; 10 | import android.os.Process; 11 | import android.os.SystemClock; 12 | 13 | 14 | public class ChainedNetworkActivity extends Activity { 15 | 16 | private static final int DIALOG_LOADING = 0; 17 | 18 | private static final int SHOW_LOADING = 1; 19 | private static final int DISMISS_LOADING = 2; 20 | 21 | Handler dialogHandler = new Handler() { 22 | @Override 23 | public void handleMessage(Message msg) { 24 | super.handleMessage(msg); 25 | switch (msg.what) { 26 | case SHOW_LOADING: 27 | showDialog(DIALOG_LOADING); 28 | break; 29 | case DISMISS_LOADING: 30 | dismissDialog(DIALOG_LOADING); 31 | } 32 | } 33 | }; 34 | 35 | private class NetworkHandlerThread extends HandlerThread { 36 | private static final int STATE_A = 1; 37 | private static final int STATE_B = 2; 38 | private Handler mHandler; 39 | 40 | public NetworkHandlerThread() { 41 | super("NetworkHandlerThread", Process.THREAD_PRIORITY_BACKGROUND); 42 | } 43 | 44 | @Override 45 | protected void onLooperPrepared() { 46 | super.onLooperPrepared(); 47 | mHandler = new Handler(getLooper()) { 48 | @Override 49 | public void handleMessage(Message msg) { 50 | super.handleMessage(msg); 51 | switch (msg.what) { 52 | case STATE_A: 53 | dialogHandler.sendEmptyMessage(SHOW_LOADING); 54 | String result = networkOperation1(); 55 | if (result != null) { 56 | sendMessage(obtainMessage(STATE_B, result)); 57 | } else { 58 | dialogHandler.sendEmptyMessage(DISMISS_LOADING); 59 | } 60 | break; 61 | case STATE_B: 62 | networkOperation2((String) msg.obj); 63 | dialogHandler.sendEmptyMessage(DISMISS_LOADING); 64 | break; 65 | } 66 | } 67 | }; 68 | fetchDataFromNetwork(); 69 | } 70 | 71 | private String networkOperation1() { 72 | SystemClock.sleep(2000); // Dummy 73 | return "A string"; 74 | } 75 | 76 | private void networkOperation2(String data) { 77 | // Pass data to network, e.g. with HttpPost. 78 | SystemClock.sleep(2000); // Dummy 79 | } 80 | 81 | /** 82 | * Publicly exposed network operation 83 | */ 84 | public void fetchDataFromNetwork() { 85 | mHandler.sendEmptyMessage(STATE_A); 86 | } 87 | } 88 | 89 | private NetworkHandlerThread mThread; 90 | 91 | 92 | public void onCreate(Bundle savedInstanceState) { 93 | super.onCreate(savedInstanceState); 94 | mThread = new NetworkHandlerThread(); 95 | mThread.start(); 96 | } 97 | 98 | @Override 99 | protected Dialog onCreateDialog(int id) { 100 | Dialog dialog = null; 101 | switch (id) { 102 | case DIALOG_LOADING: 103 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 104 | builder.setMessage("Loading..."); 105 | dialog = builder.create(); 106 | break; 107 | } 108 | return dialog; 109 | } 110 | 111 | /** 112 | * Ensure that the background thread is terminated with the Activity. 113 | */ 114 | @Override 115 | protected void onDestroy() { 116 | super.onDestroy(); 117 | mThread.quit(); 118 | } 119 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter8/Chapter8Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter8; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | 10 | public class Chapter8Activity extends Activity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_chapter8); 16 | } 17 | 18 | public void onSharedPreferencesActivity(View v) { 19 | startActivity(new Intent(this, SharedPreferencesActivity.class)); 20 | } 21 | 22 | public void onChainedNetworkActivity(View v) { 23 | startActivity(new Intent(this, ChainedNetworkActivity.class)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter8/MyHandlerThread.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter8; 2 | 3 | import android.os.*; 4 | import android.os.Process; 5 | 6 | public class MyHandlerThread extends HandlerThread { 7 | 8 | private Handler mHandler; 9 | 10 | public MyHandlerThread() { 11 | super("MyHandlerThread", Process.THREAD_PRIORITY_BACKGROUND); 12 | } 13 | 14 | @Override 15 | protected void onLooperPrepared() { 16 | super.onLooperPrepared(); 17 | mHandler = new Handler(getLooper()) { 18 | @Override 19 | public void handleMessage(Message msg) { 20 | switch(msg.what) { 21 | case 1: 22 | // Handle message 23 | break; 24 | case 2: 25 | // Handle message 26 | break; 27 | } 28 | } 29 | }; 30 | } 31 | 32 | public void publishedMethod1() { 33 | mHandler.sendEmptyMessage(1); 34 | } 35 | public void publishedMethod2() { 36 | mHandler.sendEmptyMessage(2); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter8/SharedPreferencesActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter8; 2 | 3 | import android.app.Activity; 4 | import android.content.SharedPreferences; 5 | import android.os.Bundle; 6 | import android.os.Handler; 7 | import android.os.HandlerThread; 8 | import android.os.Looper; 9 | import android.os.Message; 10 | import android.os.Process; 11 | import android.view.View; 12 | import android.widget.TextView; 13 | 14 | import com.eat.R; 15 | 16 | 17 | public class SharedPreferencesActivity extends Activity { 18 | 19 | TextView mTextValue; 20 | 21 | /** 22 | * Show read value in a TextView. 23 | */ 24 | private Handler mUiHandler = new Handler() { 25 | @Override 26 | public void handleMessage(Message msg) { 27 | super.handleMessage(msg); 28 | if (msg.what == 0) { 29 | Integer i = (Integer)msg.obj; 30 | mTextValue.setText(Integer.toString(i)); 31 | } 32 | } 33 | }; 34 | 35 | private class SharedPreferenceThread extends HandlerThread { 36 | 37 | private static final String KEY = "key"; 38 | private SharedPreferences mPrefs; 39 | private static final int READ = 1; 40 | private static final int WRITE = 2; 41 | 42 | private Handler mHandler; 43 | 44 | public SharedPreferenceThread() { 45 | super("SharedPreferenceThread", Process.THREAD_PRIORITY_BACKGROUND); 46 | mPrefs = getSharedPreferences("LocalPrefs", MODE_PRIVATE); 47 | } 48 | 49 | @Override 50 | protected void onLooperPrepared() { 51 | super.onLooperPrepared(); 52 | mHandler = new Handler(getLooper()) { 53 | @Override 54 | public void handleMessage(Message msg) { 55 | switch(msg.what) { 56 | case READ: 57 | mUiHandler.sendMessage(mUiHandler.obtainMessage(0, mPrefs.getInt(KEY, 0))); 58 | break; 59 | case WRITE: 60 | SharedPreferences.Editor editor = mPrefs.edit(); 61 | editor.putInt(KEY, (Integer)msg.obj); 62 | editor.commit(); 63 | break; 64 | } 65 | } 66 | }; 67 | } 68 | 69 | public void read() { 70 | mHandler.sendEmptyMessage(READ); 71 | } 72 | public void write(int i) { 73 | mHandler.sendMessage(Message.obtain(Message.obtain(mHandler, WRITE, i))); 74 | } 75 | } 76 | 77 | private int mCount; 78 | private SharedPreferenceThread mThread; 79 | 80 | 81 | @Override 82 | protected void onCreate(Bundle savedInstanceState) { 83 | super.onCreate(savedInstanceState); 84 | setContentView(R.layout.activity_shared_preferences); 85 | mTextValue = (TextView) findViewById(R.id.text_value); 86 | mThread = new SharedPreferenceThread(); 87 | mThread.start(); 88 | } 89 | 90 | /** 91 | * Write dummy value from the UI thread. 92 | */ 93 | public void onButtonClickWrite(View v) { 94 | mThread.write(mCount++); 95 | } 96 | 97 | /** 98 | * Initiate a read from the UI thread. 99 | */ 100 | public void onButtonClickRead(View v) { 101 | mThread.read(); 102 | } 103 | 104 | /** 105 | * Ensure that the background thread is terminated with the Activity. 106 | */ 107 | @Override 108 | protected void onDestroy() { 109 | super.onDestroy(); 110 | mThread.quit(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter9/Chapter9Activity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter9; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.eat.R; 9 | 10 | public class Chapter9Activity extends Activity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_chapter9); 16 | } 17 | 18 | public void onInvokeActivity(View v) { 19 | startActivity(new Intent(this, InvokeActivity.class)); 20 | } 21 | 22 | public void onECSImageDownloaderActivity(View v) { 23 | startActivity(new Intent(this, ECSImageDownloaderActivity.class)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter9/ECSImageDownloaderActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter9; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.os.Bundle; 7 | import android.os.SystemClock; 8 | import android.widget.ImageView; 9 | import android.widget.LinearLayout; 10 | 11 | import com.eat.R; 12 | 13 | import java.util.Random; 14 | import java.util.concurrent.Callable; 15 | import java.util.concurrent.ExecutionException; 16 | import java.util.concurrent.ExecutorCompletionService; 17 | import java.util.concurrent.ExecutorService; 18 | import java.util.concurrent.Executors; 19 | import java.util.concurrent.Future; 20 | import java.util.concurrent.TimeUnit; 21 | 22 | 23 | public class ECSImageDownloaderActivity extends Activity { 24 | 25 | private static final String TAG = "ECSImageDownloaderActivity"; 26 | 27 | private LinearLayout layoutImages; 28 | 29 | 30 | private class ImageDownloadTask implements Callable { 31 | 32 | @Override 33 | public Bitmap call() throws Exception { 34 | return downloadRemoteImage(); 35 | } 36 | 37 | private Bitmap downloadRemoteImage() { 38 | SystemClock.sleep((int) (5000f - new Random().nextFloat() * 5000f)); 39 | return BitmapFactory.decodeResource(ECSImageDownloaderActivity.this.getResources(), R.drawable.ic_launcher); 40 | } 41 | } 42 | 43 | private class DownloadCompletionService extends ExecutorCompletionService { 44 | 45 | private ExecutorService mExecutor; 46 | 47 | public DownloadCompletionService(ExecutorService executor) { 48 | super(executor); 49 | mExecutor = executor; 50 | } 51 | 52 | public void shutdown() { 53 | mExecutor.shutdown(); 54 | } 55 | 56 | public boolean isTerminated() { 57 | return mExecutor.isTerminated(); 58 | } 59 | } 60 | 61 | private class ConsumerThread extends Thread { 62 | 63 | private DownloadCompletionService mEcs; 64 | 65 | private ConsumerThread(DownloadCompletionService ecs) { 66 | this.mEcs = ecs; 67 | } 68 | 69 | @Override 70 | public void run() { 71 | super.run(); 72 | try { 73 | while(!mEcs.isTerminated()) { 74 | Future future = mEcs.poll(1, TimeUnit.SECONDS); 75 | if (future != null) { 76 | addImage(future.get()); 77 | } 78 | } 79 | } catch (InterruptedException e) { 80 | e.printStackTrace(); 81 | } catch (ExecutionException e) { 82 | e.printStackTrace(); 83 | } 84 | } 85 | } 86 | 87 | public void onCreate(Bundle savedInstanceState) { 88 | super.onCreate(savedInstanceState); 89 | setContentView(R.layout.activity_ecs_image_downloader); 90 | layoutImages = (LinearLayout) findViewById(R.id.layout_images); 91 | 92 | DownloadCompletionService ecs = new DownloadCompletionService(Executors.newCachedThreadPool()); 93 | new ConsumerThread(ecs).start(); 94 | 95 | for (int i = 0; i < 5; i++) { 96 | ecs.submit(new ImageDownloadTask()); 97 | } 98 | 99 | ecs.shutdown(); 100 | } 101 | 102 | 103 | private void addImage(final Bitmap image) { 104 | runOnUiThread(new Runnable() { 105 | @Override 106 | public void run() { 107 | ImageView iv = new ImageView(ECSImageDownloaderActivity.this); 108 | iv.setImageBitmap(image); 109 | layoutImages.addView(iv); 110 | } 111 | }); 112 | } 113 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter9/InvokeActivity.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter9; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.SystemClock; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.TextView; 9 | 10 | import com.eat.R; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.concurrent.Callable; 15 | import java.util.concurrent.ExecutionException; 16 | import java.util.concurrent.Executors; 17 | import java.util.concurrent.Future; 18 | import java.util.concurrent.ThreadPoolExecutor; 19 | 20 | 21 | public class InvokeActivity extends Activity { 22 | 23 | 24 | private static final String TAG = "InvokeActivity"; 25 | 26 | private TextView textStatus; 27 | 28 | public void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_invoke); 31 | textStatus = (TextView) findViewById(R.id.text_status); 32 | } 33 | 34 | 35 | public void onButtonClick(View v) { 36 | 37 | SimpleExecutor simpleExecutor = new SimpleExecutor(); 38 | simpleExecutor.execute(new Runnable() { 39 | @Override 40 | public void run() { 41 | List> tasks = new ArrayList>(); 42 | tasks.add(new Callable() { 43 | @Override 44 | public String call() throws Exception { 45 | return getFirstPartialDataFromNetwork(); 46 | } 47 | }); 48 | tasks.add(new Callable() { 49 | @Override 50 | public String call() throws Exception { 51 | return getSecondPartialDataFromNetwork(); 52 | } 53 | }); 54 | 55 | ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newFixedThreadPool(2); 56 | try { 57 | Log.d(TAG, "invokeAll"); 58 | List> futures = executor.invokeAll(tasks); 59 | Log.d(TAG, "invokeAll after"); 60 | 61 | final String mashedData = mashupResult(futures); 62 | 63 | textStatus.post(new Runnable() { 64 | @Override 65 | public void run() { 66 | textStatus.setText(mashedData); 67 | } 68 | }); 69 | Log.d(TAG, "mashedData = " + mashedData); 70 | 71 | } catch (InterruptedException e) { 72 | e.printStackTrace(); 73 | } catch (ExecutionException e) { 74 | e.printStackTrace(); 75 | } 76 | 77 | executor.shutdown(); 78 | } 79 | }); 80 | } 81 | 82 | private String getFirstPartialDataFromNetwork() { 83 | Log.d(TAG, "ProgressReportingTask 1 started"); 84 | SystemClock.sleep(10000); 85 | Log.d(TAG, "ProgressReportingTask 1 done"); 86 | return "MockA"; 87 | } 88 | 89 | private String getSecondPartialDataFromNetwork() { 90 | Log.d(TAG, "ProgressReportingTask 2 started"); 91 | SystemClock.sleep(2000); 92 | Log.d(TAG, "ProgressReportingTask 2 done"); 93 | return "MockB"; 94 | } 95 | 96 | private String mashupResult(List> futures) throws ExecutionException, InterruptedException { 97 | StringBuilder builder = new StringBuilder(); 98 | for (Future future : futures) { 99 | builder.append(future.get()); 100 | } 101 | return builder.toString(); 102 | } 103 | } -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter9/LowPriorityThreadFactory.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter9; 2 | 3 | import android.util.Log; 4 | 5 | import java.util.concurrent.ThreadFactory; 6 | 7 | class LowPriorityThreadFactory implements ThreadFactory { 8 | 9 | private static final String TAG = "LowPriorityThreadFactory"; 10 | private static int count = 1; 11 | 12 | public Thread newThread(Runnable r) { 13 | Thread t = new Thread(r); 14 | t.setName("LowPrio " + count++); 15 | t.setPriority(4); 16 | t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() 17 | { 18 | @Override 19 | public void uncaughtException(Thread t, Throwable e) 20 | { 21 | Log.d(TAG, "Thread = " + t.getName() + ", error = " + e.getMessage()); 22 | } 23 | }); 24 | return t; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter9/PrestartedCores.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter9; 2 | 3 | import android.util.Log; 4 | 5 | import java.util.concurrent.BlockingQueue; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | import java.util.concurrent.ThreadPoolExecutor; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | public class PrestartedCores { 11 | 12 | 13 | private static final String TAG = "PrestartedCores"; 14 | 15 | public void preloadedQueue() { 16 | 17 | BlockingQueue preloadedQueue = new LinkedBlockingQueue(); 18 | final String[] alphabet = {"Alpha","Beta", "Gamma","Delta","Epsilon","Zeta"}; 19 | for(int i = 0; i < alphabet.length; i++){ 20 | final int j = i; 21 | preloadedQueue.add(new Runnable() { 22 | @Override 23 | public void run() { 24 | Log.d(TAG, alphabet[j]); 25 | 26 | } 27 | }); 28 | } 29 | ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 1, TimeUnit.SECONDS, preloadedQueue); 30 | executor.prestartAllCoreThreads(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter9/SimpleExecutor.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter9; 2 | 3 | import java.util.concurrent.Executor; 4 | 5 | public class SimpleExecutor implements Executor { 6 | @Override 7 | public void execute(Runnable runnable) { 8 | new Thread(runnable).start(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/java/com/eat/chapter9/TaskTrackingThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.eat.chapter9; 2 | 3 | 4 | import android.util.Log; 5 | 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | import java.util.concurrent.ThreadPoolExecutor; 8 | import java.util.concurrent.TimeUnit; 9 | import java.util.concurrent.atomic.AtomicInteger; 10 | 11 | public class TaskTrackingThreadPool extends ThreadPoolExecutor{ 12 | 13 | private static final String TAG = "CustomThreadPool"; 14 | 15 | private AtomicInteger mTaskCount = new AtomicInteger(0); 16 | 17 | public TaskTrackingThreadPool() { 18 | super(3, 3, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue()); 19 | } 20 | 21 | @Override 22 | protected void beforeExecute(Thread t, Runnable r) { 23 | super.beforeExecute(t, r); 24 | Log.d(TAG, "beforeExecute - thread = " + t.getName()); 25 | mTaskCount.getAndIncrement(); 26 | } 27 | 28 | @Override 29 | protected void afterExecute(Runnable r, Throwable t) { 30 | super.afterExecute(r, t); 31 | Log.d(TAG, "afterExecute - thread = " + Thread.currentThread().getName() + "t = " + t); 32 | mTaskCount.getAndDecrement(); 33 | } 34 | 35 | @Override 36 | protected void terminated() { 37 | super.terminated(); 38 | Log.d(TAG, "terminated - thread = " + Thread.currentThread().getName()); 39 | } 40 | 41 | public int getNbrOfTasks() { 42 | return mTaskCount.get(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersgoransson/eatbookexamples/b6476cba9d931982b2f8c07a5fb7c529b3ba73d4/EatApplication/Eat/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersgoransson/eatbookexamples/b6476cba9d931982b2f8c07a5fb7c529b3ba73d4/EatApplication/Eat/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersgoransson/eatbookexamples/b6476cba9d931982b2f8c07a5fb7c529b3ba73d4/EatApplication/Eat/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersgoransson/eatbookexamples/b6476cba9d931982b2f8c07a5fb7c529b3ba73d4/EatApplication/Eat/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/res/layout/activity_alarm_broadcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 13 | 14 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /EatApplication/Eat/src/main/res/layout/activity_basic.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 11 | 12 |