diff options
author | Svetoslav <svetoslavganov@google.com> | 2013-03-07 18:19:37 -0800 |
---|---|---|
committer | Svetoslav Ganov <svetoslavganov@google.com> | 2013-06-21 17:28:03 -0700 |
commit | 0fb6959ad364ee84e83c435d671228fb365f2084 (patch) | |
tree | c42238cf41c351aa7550599e13f308e7b9f0fae3 | |
parent | c861cbe15d3f6cf28aede372e81cb19fd46e3114 (diff) | |
download | experimental-0fb6959ad364ee84e83c435d671228fb365f2084.tar.gz |
Print - print services
Change-Id: Iaf7cd0b49797721420a28fbecfd3f6557c35e64d
60 files changed, 1632 insertions, 0 deletions
diff --git a/PrintApp/.classpath b/PrintApp/.classpath new file mode 100644 index 0000000..a4763d1 --- /dev/null +++ b/PrintApp/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath> diff --git a/PrintApp/.project b/PrintApp/.project new file mode 100644 index 0000000..507c2e2 --- /dev/null +++ b/PrintApp/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>TestBack</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/PrintApp/Android.mk b/PrintApp/Android.mk new file mode 100644 index 0000000..7cea0ab --- /dev/null +++ b/PrintApp/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := Print + +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) diff --git a/PrintApp/AndroidManifest.xml b/PrintApp/AndroidManifest.xml new file mode 100644 index 0000000..7528f28 --- /dev/null +++ b/PrintApp/AndroidManifest.xml @@ -0,0 +1,24 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="foo.bar.print" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk + android:minSdkVersion="KeyLimePie" + android:targetSdkVersion="KeyLimePie" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:allowBackup="false" > + <activity + android:name=".PrintActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/PrintApp/res/drawable-hdpi/ic_launcher.png b/PrintApp/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..a301d57 --- /dev/null +++ b/PrintApp/res/drawable-hdpi/ic_launcher.png diff --git a/PrintApp/res/drawable-ldpi/ic_launcher.png b/PrintApp/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..2c2a58b --- /dev/null +++ b/PrintApp/res/drawable-ldpi/ic_launcher.png diff --git a/PrintApp/res/drawable-mdpi/ic_launcher.png b/PrintApp/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..f91f736 --- /dev/null +++ b/PrintApp/res/drawable-mdpi/ic_launcher.png diff --git a/PrintApp/res/drawable-xhdpi/ic_launcher.png b/PrintApp/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..96095ec --- /dev/null +++ b/PrintApp/res/drawable-xhdpi/ic_launcher.png diff --git a/PrintApp/res/layout/activity_main.xml b/PrintApp/res/layout/activity_main.xml new file mode 100644 index 0000000..8a3c72a --- /dev/null +++ b/PrintApp/res/layout/activity_main.xml @@ -0,0 +1,124 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/content" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MainActivity" + android:orientation="vertical" > + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/name"> + </TextView> + + <EditText + android:layout_width="1150dip" + android:layout_height="wrap_content" + android:hint="@string/enter_name"> + </EditText> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/done"/> + + </LinearLayout> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/name"> + </TextView> + + <EditText + android:layout_width="1150dip" + android:layout_height="wrap_content" + android:hint="@string/enter_name"> + </EditText> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/done"/> + + </LinearLayout> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/name"> + </TextView> + + <EditText + android:layout_width="1150dip" + android:layout_height="wrap_content" + android:hint="@string/enter_name"> + </EditText> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/done"/> + + </LinearLayout> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/name"> + </TextView> + + <EditText + android:layout_width="1150dip" + android:layout_height="wrap_content" + android:hint="@string/enter_name"> + </EditText> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/done"/> + + </LinearLayout> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/name"> + </TextView> + + <EditText + android:layout_width="1150dip" + android:layout_height="wrap_content" + android:hint="@string/enter_name"> + </EditText> + + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/done"/> + + </LinearLayout> + +</LinearLayout> diff --git a/PrintApp/res/menu/activity_main.xml b/PrintApp/res/menu/activity_main.xml new file mode 100644 index 0000000..31bb883 --- /dev/null +++ b/PrintApp/res/menu/activity_main.xml @@ -0,0 +1,10 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_settings" + android:title="@string/menu_settings" + android:orderInCategory="100" + android:showAsAction="never" /> + <item android:id="@+id/menu_print" + android:title="@string/print" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> diff --git a/PrintApp/res/values/strings.xml b/PrintApp/res/values/strings.xml new file mode 100644 index 0000000..352494a --- /dev/null +++ b/PrintApp/res/values/strings.xml @@ -0,0 +1,11 @@ +<resources> + + <string name="app_name">Print</string> + <string name="menu_settings">Settings</string> + <string name="title_activity_main">MainActivity</string> + <string name="print">Print</string> + <string name="name">Name</string> + <string name="enter_name">Enter your name</string> + <string name="done">Done</string> + +</resources>
\ No newline at end of file diff --git a/PrintApp/src/foo/bar/print/PrintActivity.java b/PrintApp/src/foo/bar/print/PrintActivity.java new file mode 100644 index 0000000..02046d4 --- /dev/null +++ b/PrintApp/src/foo/bar/print/PrintActivity.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package foo.bar.print; + +import android.app.Activity; +import android.content.Context; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.CancellationSignal; +import android.os.CancellationSignal.OnCancelListener; +import android.print.PageRange; +import android.print.PrintAdapter; +import android.print.PrintAdapterInfo; +import android.print.PrintAttributes; +import android.print.PrintJob; +import android.print.PrintManager; +import android.print.pdf.PdfDocument.Page; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +import libcore.io.IoUtils; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.util.List; + +/** + * Simple sample of how to use the print APIs. + */ +public class PrintActivity extends Activity { + + public static final String LOG_TAG = "PrintActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + getMenuInflater().inflate(R.menu.activity_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (!super.onOptionsItemSelected(item)) { + if (item.getItemId() == R.id.menu_print) { + printView(); + return true; + } + } + return false; + } + + public void printFileSimple() { + PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE); + + PrintJob printJob = printManager.print("My Print Job", new File("foo.pdf"), null); + + if (printJob != null) { + /* Yay, we scheduled something to be printed!!! */ + } + } + + private void printView() { + PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE); + + final View view = findViewById(R.id.content); + + PrintJob printJob = printManager.print("Print_View", + new PrintAdapter() { + private PrintedPdfDocument mPdfDocument; + + @Override + public void onStarted() { + Log.i(LOG_TAG, "onStarted"); + super.onStarted(); + } + + @Override + public boolean onPrintAttributesChanged(PrintAttributes attributes) { + Log.i(LOG_TAG, "onPrintAttributesChanged"); + mPdfDocument = new PrintedPdfDocument(PrintActivity.this, attributes); + Page page = mPdfDocument.startPage(); + view.draw(page.getCanvas()); + mPdfDocument.finishPage(page); + return true; + } + + @Override + public void onPrint(final List<PageRange> pages, + final FileDescriptor destination, + final CancellationSignal canclleationSignal, + final PrintProgressListener progressListener) { + Log.i(LOG_TAG, "onPrint"); + final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + try { + mPdfDocument.writeTo(new FileOutputStream(destination)); + } finally { + mPdfDocument.close(); + IoUtils.closeQuietly(destination); + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + progressListener.onWriteFinished(pages); + } + + @Override + protected void onCancelled(Void result) { + progressListener.onWriteFailed("Cancelled"); + } + }; + + canclleationSignal.setOnCancelListener(new OnCancelListener() { + @Override + public void onCancel() { + task.cancel(true); + } + }); + + task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); + } + + @Override + public void onFinished() { + Log.i(LOG_TAG, "onFinished"); + super.onFinished(); + } + + @Override + public PrintAdapterInfo getInfo() { + Log.i(LOG_TAG, "getInfo"); + return new PrintAdapterInfo.Builder().setPageCount(1).create(); + } + }, new PrintAttributes.Builder().create()); + + if (printJob != null) { + /* Yay, we scheduled something to be printed!!! */ + } + } +} diff --git a/PrintApp/src/foo/bar/print/PrintedPdfDocument.java b/PrintApp/src/foo/bar/print/PrintedPdfDocument.java new file mode 100644 index 0000000..f6cdb4a --- /dev/null +++ b/PrintApp/src/foo/bar/print/PrintedPdfDocument.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package foo.bar.print; + +import android.content.Context; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.hardware.display.DisplayManager; +import android.print.PrintAttributes; +import android.print.PrintAttributes.Margins; +import android.print.PrintAttributes.MediaSize; +import android.print.PrintAttributes.Resolution; +import android.print.pdf.PdfDocument; +import android.print.pdf.PdfDocument.Page; +import android.print.pdf.PdfDocument.PageInfo; +import android.util.DisplayMetrics; +import android.view.Display; + +import java.io.OutputStream; + +/** + * This class is a helper for printing content to a different media + * size. The printed content will be as large as it would be on the + * screen. + * + * THIS IS A TEST CODE AND IS HIDDEN + * + * @hide + */ +public final class PrintedPdfDocument { + private static final int MILS_PER_INCH = 1000; + + /** + * Maximum bitmap size as defined in Skia's native code (see SkCanvas.cpp, + * SkDraw.cpp) + */ + private static final int MAXMIMUM_BITMAP_SIZE = 32766; + + private final PdfDocument mDocument = PdfDocument.open(); + private final Rect mPageSize = new Rect(); + private final Rect mContentSize = new Rect(); + + private final int mCanvasDensityDpi; + private final Matrix mContentToPageTransform; + + private Matrix mTempMatrix; + + /** + * Creates a new instance. + * + * @param context Context instance for accessing resources and services. + * @param attributes The {@link PrintAttributes} to user. + */ + public PrintedPdfDocument(Context context, PrintAttributes attributes) { + MediaSize mediaSize = attributes.getMediaSize(); + Resolution resolution = attributes.getResolution(); + + // TODO: What to do if horizontal and vertical DPI differ? + mCanvasDensityDpi = Math.max(attributes.getResolution().getHorizontalDpi(), attributes + .getResolution().getVerticalDpi()); + + // Figure out the scale since the content and the target DPI may differ. + DisplayMetrics metrics = new DisplayMetrics(); + DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); + dm.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(metrics); + final float scaleFactor = ((float) mCanvasDensityDpi) / metrics.densityDpi; + mContentToPageTransform = new Matrix(); + mContentToPageTransform.setScale(scaleFactor, scaleFactor); + + // Compute the size of the target canvas from the attributes. + final int pageWidth = (mediaSize.getWidthMils() / MILS_PER_INCH) + * resolution.getHorizontalDpi(); + final int pageHeight = (mediaSize.getHeightMils() / MILS_PER_INCH) + * resolution.getVerticalDpi(); + mPageSize.set(0, 0, pageWidth, pageHeight); + + // Compute the content size from the attributes. + Margins margins = attributes.getMargins(); + final int marginLeft = (margins.getLeftMils() / MILS_PER_INCH) + * resolution.getHorizontalDpi(); + final int marginTop = (margins.getTopMils() / MILS_PER_INCH) * resolution.getVerticalDpi(); + final int marginRight = (margins.getRightMils() / MILS_PER_INCH) + * resolution.getHorizontalDpi(); + final int marginBottom = (margins.getBottomMils() / MILS_PER_INCH) + * resolution.getVerticalDpi(); + mContentSize.set(mPageSize.left + marginLeft, mPageSize.top + marginTop, mPageSize.right + - marginRight, mPageSize.bottom - marginBottom); + } + + /** + * Starts a new page. + * + * @return The started page. + */ + public Page startPage() { + return startPage(null); + } + + /** + * Starts a new page. + * + * @param additionalTransform Additional initial transform. + * @return The started page. + */ + public Page startPage(Matrix additionalTransform) { + Matrix transform = null; + if (additionalTransform != null) { + if (mTempMatrix == null) { + transform = mTempMatrix = new Matrix(); + } + transform.set(mContentToPageTransform); + transform.postConcat(additionalTransform); + } else { + transform = mContentToPageTransform; + } + PageInfo pageInfo = new PageInfo.Builder(mPageSize, 0, mCanvasDensityDpi).create(); + Page page = mDocument.startPage(pageInfo); + return page; + } + + /** + * Finishes a page. + * + * @param page The page to finish. + */ + public void finishPage(Page page) { + mDocument.finishPage(page); + } + + /** + * Writes the document to a stream. + * + * @param out The destination stream. + */ + public void writeTo(OutputStream out) { + mDocument.writeTo(out); + } + + /** + * Closes the document. + */ + public void close() { + mDocument.close(); + } +} diff --git a/PrintService/.classpath b/PrintService/.classpath new file mode 100644 index 0000000..a4763d1 --- /dev/null +++ b/PrintService/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath> diff --git a/PrintService/.project b/PrintService/.project new file mode 100644 index 0000000..507c2e2 --- /dev/null +++ b/PrintService/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>TestBack</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/PrintService/Android.mk b/PrintService/Android.mk new file mode 100644 index 0000000..7c5d5fa --- /dev/null +++ b/PrintService/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := PrintService + +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) diff --git a/PrintService/AndroidManifest.xml b/PrintService/AndroidManifest.xml new file mode 100644 index 0000000..096e7cd --- /dev/null +++ b/PrintService/AndroidManifest.xml @@ -0,0 +1,37 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="foo.bar.printservice" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk + android:minSdkVersion="KeyLimePie" + android:targetSdkVersion="KeyLimePie" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:allowBackup="false" > + <service + android:name=".MyPrintService" + android:permission="android.permission.BIND_PRINT_SERVICE"> + <intent-filter> + <action android:name="android.printservice.PrintService" /> + </intent-filter> + <meta-data + android:name="android.printservice" + android:resource="@xml/printservice"> + </meta-data> + </service> + <activity + android:name=".SettingsActivity" + android:label="@string/settings_activity_label" + android:permission="android.permission.BIND_PRINT_SERVICE"> + </activity> + <activity + android:name=".AddPrintersActivity" + android:label="@string/add_pritners_activity_label" + android:permission="android.permission.BIND_PRINT_SERVICE"> + </activity> + </application> + +</manifest> diff --git a/PrintService/res/drawable-hdpi/ic_launcher.png b/PrintService/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..a301d57 --- /dev/null +++ b/PrintService/res/drawable-hdpi/ic_launcher.png diff --git a/PrintService/res/drawable-ldpi/ic_launcher.png b/PrintService/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..2c2a58b --- /dev/null +++ b/PrintService/res/drawable-ldpi/ic_launcher.png diff --git a/PrintService/res/drawable-mdpi/ic_launcher.png b/PrintService/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..f91f736 --- /dev/null +++ b/PrintService/res/drawable-mdpi/ic_launcher.png diff --git a/PrintService/res/drawable-xhdpi/ic_launcher.png b/PrintService/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..96095ec --- /dev/null +++ b/PrintService/res/drawable-xhdpi/ic_launcher.png diff --git a/PrintService/res/layout/activity_main.xml b/PrintService/res/layout/activity_main.xml new file mode 100644 index 0000000..78184ea --- /dev/null +++ b/PrintService/res/layout/activity_main.xml @@ -0,0 +1,13 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MainActivity" > + + <TextView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:text="@string/settings"> + </TextView> + +</LinearLayout> diff --git a/PrintService/res/values/strings.xml b/PrintService/res/values/strings.xml new file mode 100644 index 0000000..7a4b0b1 --- /dev/null +++ b/PrintService/res/values/strings.xml @@ -0,0 +1,18 @@ +<resources> + + <string name="app_name">Print Service</string> + <string name="description">This print serivice exposes one fake printer and + on print sends an email to svetoslavganov@google.com</string> + <string name="settings">This is an activitiy with some print service settings.</string> + <string name="settings_activity_label">Settings activity</string> + <string name="add_pritners_activity_label">Add printers activity</string> + + <string name="resolution_200x200">200x200</string> + <string name="resolution_300x300">300x300</string> + <string name="resolution_600x600">600x600</string> + <string name="input_tray_first">First input tray</string> + <string name="input_tray_second">Second input tray</string> + <string name="output_tray_first">First output tray</string> + <string name="output_tray_second">Second output tray</string> + +</resources> diff --git a/PrintService/res/xml/printservice.xml b/PrintService/res/xml/printservice.xml new file mode 100644 index 0000000..667bef7 --- /dev/null +++ b/PrintService/res/xml/printservice.xml @@ -0,0 +1,3 @@ +<print-service xmlns:android="http://schemas.android.com/apk/res/android" + android:settingsActivity="foo.bar.printservice.SettingsActivity" + android:addPrintersActivity="foo.bar.printservice.AddPrintersActivity"/> diff --git a/PrintService/src/foo/bar/printservice/AddPrintersActivity.java b/PrintService/src/foo/bar/printservice/AddPrintersActivity.java new file mode 100644 index 0000000..1a0bc18 --- /dev/null +++ b/PrintService/src/foo/bar/printservice/AddPrintersActivity.java @@ -0,0 +1,13 @@ +package foo.bar.printservice; + +import android.app.Activity; +import android.os.Bundle; + +public class AddPrintersActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } +} diff --git a/PrintService/src/foo/bar/printservice/MyPrintService.java b/PrintService/src/foo/bar/printservice/MyPrintService.java new file mode 100644 index 0000000..010c987 --- /dev/null +++ b/PrintService/src/foo/bar/printservice/MyPrintService.java @@ -0,0 +1,231 @@ +package foo.bar.printservice; + +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.print.PrintAttributes; +import android.print.PrintAttributes.Margins; +import android.print.PrintAttributes.Resolution; +import android.print.PrintAttributes.Tray; +import android.print.PrintJobInfo; +import android.print.PrinterId; +import android.print.PrinterInfo; +import android.printservice.PrintJob; +import android.printservice.PrintService; +import android.util.Log; +import android.widget.Toast; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class MyPrintService extends PrintService { + + private static final String LOG_TAG = MyPrintService.class.getSimpleName(); + + private Handler mHandler; + + @Override + protected void onConnected() { + mHandler = new MyHandler(getMainLooper()); + Log.i(LOG_TAG, "#onConnected()"); + } + + @Override + protected void onDisconnected() { + Log.i(LOG_TAG, "#onDisconnected()"); + } + + @Override + protected void onStartPrinterDiscovery() { + Log.i(LOG_TAG, "#onStartDiscoverPrinters()"); + Message message1 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_FIRST_FAKE_PRINTER); + mHandler.sendMessageDelayed(message1, 0); + + Message message2 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_SECOND_FAKE_PRINTER); + mHandler.sendMessageDelayed(message2, 10000); + } + + @Override + protected void onStopPrinterDiscovery() { + Log.i(LOG_TAG, "#onStopDiscoverPrinters()"); + } + + @Override + public void onPrintJobQueued(final PrintJob printJob) { + Log.i(LOG_TAG, "#onPrintJobPending()"); + PrintJobInfo info = printJob.getInfo(); + final File file = new File(getFilesDir(), info.getLabel() + ".pdf"); + if (file.exists()) { + file.delete(); + } + AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + InputStream in = new BufferedInputStream( + new FileInputStream(printJob.getData())); + OutputStream out = null; + try { + out = new BufferedOutputStream(new FileOutputStream(file)); + final byte[] buffer = new byte[8192]; + while (true) { + final int readByteCount = in.read(buffer); + if (readByteCount < 0) { + break; + } + out.write(buffer, 0, readByteCount); + } + } catch (IOException ioe) { + /* ignore */ + } finally { + try { + in.close(); + } catch (IOException ioe) { + /* ignore */ + } + if (out != null) { + try { + out.close(); + } catch (IOException ioe) { + /* ignore */ + } + } + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + file.setExecutable(true, false); + file.setWritable(true, false); + file.setReadable(true, false); + + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setDataAndType(Uri.fromFile(file), "application/pdf"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent, null); + + if (printJob.isQueued()) { + printJob.start(); + } + + PrintJobInfo info = printJob.getInfo(); + Toast.makeText(MyPrintService.this, + "Printer: " + info.getPrinterId().getLocalId() + + " copies: " + info.getAttributes().getCopies(), + Toast.LENGTH_SHORT).show(); + + if (printJob.isStarted()) { + printJob.complete(); + } + } + }; + task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); + } + + private void addFirstFakePrinter() { + PrinterId printerId = generatePrinterId("1"); + PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 1") + .setStatus(PrinterInfo.STATUS_READY) + .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0)) + .addMediaSize(PrintAttributes.MediaSize.ISO_A2, false) + .addMediaSize(PrintAttributes.MediaSize.ISO_A3, false) + .addMediaSize(PrintAttributes.MediaSize.ISO_A4, false) + .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false) + .addMediaSize(PrintAttributes.MediaSize.ISO_A6, false) + .addMediaSize(PrintAttributes.MediaSize.NA_LETTER, true) + .addResolution(new Resolution("R1", getPackageName(), + R.string.resolution_600x600, 600, 600), true) + .addInputTray(new Tray("FirstInputTray", getPackageName(), + R.string.input_tray_first), false) + .addOutputTray(new Tray("FirstOutputTray", getPackageName(), + R.string.output_tray_first), false) + .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE + | PrintAttributes.DUPLEX_MODE_LONG_EDGE + | PrintAttributes.DUPLEX_MODE_SHORT_EDGE, + PrintAttributes.DUPLEX_MODE_NONE) + .setColorModes(PrintAttributes.COLOR_MODE_COLOR + | PrintAttributes.COLOR_MODE_MONOCHROME, + PrintAttributes.COLOR_MODE_COLOR) + .setFittingModes(PrintAttributes.FITTING_MODE_NONE + | PrintAttributes.FITTING_MODE_FIT_TO_PAGE, + PrintAttributes.FITTING_MODE_NONE) + .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT + | PrintAttributes.ORIENTATION_LANDSCAPE, + PrintAttributes.ORIENTATION_PORTRAIT) + .create(); + List<PrinterInfo> printers = new ArrayList<PrinterInfo>(); + printers.add(printer); + addDiscoveredPrinters(printers); + } + + private void addSecondFakePrinter() { + PrinterId printerId = generatePrinterId("2"); + PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 2") + .setStatus(PrinterInfo.STATUS_READY) + .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0)) + .addMediaSize(PrintAttributes.MediaSize.ISO_A4, true) + .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false) + .addResolution(new Resolution("R1", getPackageName(), + R.string.resolution_200x200, 200, 200), true) + .addResolution(new Resolution("R2", getPackageName(), + R.string.resolution_300x300, 300, 300), false) + .addInputTray(new Tray("FirstInputTray", getPackageName(), + R.string.input_tray_first), false) + .addInputTray(new Tray("SecondInputTray", getPackageName(), + R.string.input_tray_second), true) + .addOutputTray(new Tray("FirstOutputTray", getPackageName(), + R.string.output_tray_first), false) + .addOutputTray(new Tray("SecondOutputTray", getPackageName(), + R.string.output_tray_second), true) + .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE + | PrintAttributes.DUPLEX_MODE_LONG_EDGE + | PrintAttributes.DUPLEX_MODE_SHORT_EDGE, + PrintAttributes.DUPLEX_MODE_SHORT_EDGE) + .setColorModes(PrintAttributes.COLOR_MODE_COLOR + | PrintAttributes.COLOR_MODE_MONOCHROME, + PrintAttributes.COLOR_MODE_MONOCHROME) + .setFittingModes(PrintAttributes.FITTING_MODE_FIT_TO_PAGE + | PrintAttributes.FITTING_MODE_NONE, + PrintAttributes.FITTING_MODE_FIT_TO_PAGE) + .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT + | PrintAttributes.ORIENTATION_LANDSCAPE, + PrintAttributes.ORIENTATION_LANDSCAPE) + .create(); + List<PrinterInfo> printers = new ArrayList<PrinterInfo>(); + printers.add(printer); + addDiscoveredPrinters(printers); + } + + private final class MyHandler extends Handler { + + public static final int MESSAGE_ADD_FIRST_FAKE_PRINTER = 1; + public static final int MESSAGE_ADD_SECOND_FAKE_PRINTER = 2; + + public MyHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message message) { + switch (message.what) { + case MESSAGE_ADD_FIRST_FAKE_PRINTER: { + addFirstFakePrinter(); + } break; + case MESSAGE_ADD_SECOND_FAKE_PRINTER: { + addSecondFakePrinter(); + } break; + } + } + } +} diff --git a/PrintService/src/foo/bar/printservice/SettingsActivity.java b/PrintService/src/foo/bar/printservice/SettingsActivity.java new file mode 100644 index 0000000..21ab419 --- /dev/null +++ b/PrintService/src/foo/bar/printservice/SettingsActivity.java @@ -0,0 +1,13 @@ +package foo.bar.printservice; + +import android.app.Activity; +import android.os.Bundle; + +public class SettingsActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } +} diff --git a/PrintService2/.classpath b/PrintService2/.classpath new file mode 100644 index 0000000..a4763d1 --- /dev/null +++ b/PrintService2/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath> diff --git a/PrintService2/.project b/PrintService2/.project new file mode 100644 index 0000000..507c2e2 --- /dev/null +++ b/PrintService2/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>TestBack</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/PrintService2/Android.mk b/PrintService2/Android.mk new file mode 100644 index 0000000..3dda6c8 --- /dev/null +++ b/PrintService2/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := PrintService2 + +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) diff --git a/PrintService2/AndroidManifest.xml b/PrintService2/AndroidManifest.xml new file mode 100644 index 0000000..e92d635 --- /dev/null +++ b/PrintService2/AndroidManifest.xml @@ -0,0 +1,35 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="foo.bar.printservice2" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk + android:minSdkVersion="KeyLimePie" + android:targetSdkVersion="KeyLimePie" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:allowBackup="false" > + <service + android:name=".MyPrintService" + android:permission="android.permission.BIND_PRINT_SERVICE"> + <intent-filter> + <action android:name="android.printservice.PrintService" /> + </intent-filter> + <meta-data + android:name="android.printservice" + android:resource="@xml/printservice"> + </meta-data> + </service> + <activity + android:name=".SettingsActivity" + android:label="@string/app_name" + android:permission="android.permission.BIND_PRINT_SERVICE"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + </intent-filter> + </activity> + </application> + +</manifest> diff --git a/PrintService2/res/drawable-hdpi/ic_launcher.png b/PrintService2/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..a301d57 --- /dev/null +++ b/PrintService2/res/drawable-hdpi/ic_launcher.png diff --git a/PrintService2/res/drawable-ldpi/ic_launcher.png b/PrintService2/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..2c2a58b --- /dev/null +++ b/PrintService2/res/drawable-ldpi/ic_launcher.png diff --git a/PrintService2/res/drawable-mdpi/ic_launcher.png b/PrintService2/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..f91f736 --- /dev/null +++ b/PrintService2/res/drawable-mdpi/ic_launcher.png diff --git a/PrintService2/res/drawable-xhdpi/ic_launcher.png b/PrintService2/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..96095ec --- /dev/null +++ b/PrintService2/res/drawable-xhdpi/ic_launcher.png diff --git a/PrintService2/res/layout/activity_main.xml b/PrintService2/res/layout/activity_main.xml new file mode 100644 index 0000000..78184ea --- /dev/null +++ b/PrintService2/res/layout/activity_main.xml @@ -0,0 +1,13 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MainActivity" > + + <TextView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:text="@string/settings"> + </TextView> + +</LinearLayout> diff --git a/PrintService2/res/values/strings.xml b/PrintService2/res/values/strings.xml new file mode 100644 index 0000000..6fb171b --- /dev/null +++ b/PrintService2/res/values/strings.xml @@ -0,0 +1,16 @@ +<resources> + + <string name="app_name">Print Service 2</string> + <string name="description">This print serivice exposes one fake printer and + on print sends an email to svetoslavganov@google.com</string> + <string name="settings">This is an activitiy with some print service settings.</string> + + <string name="resolution_200x200">200x200</string> + <string name="resolution_300x300">300x300</string> + <string name="resolution_600x600">600x600</string> + <string name="input_tray_first">First input tray</string> + <string name="input_tray_second">Second input tray</string> + <string name="output_tray_first">First output tray</string> + <string name="output_tray_second">Second output tray</string> + +</resources> diff --git a/PrintService2/res/xml/printservice.xml b/PrintService2/res/xml/printservice.xml new file mode 100644 index 0000000..44fa285 --- /dev/null +++ b/PrintService2/res/xml/printservice.xml @@ -0,0 +1,3 @@ +<print-service xmlns:android="http://schemas.android.com/apk/res/android" + android:settingsActivity="foo.bar.printservice2.SettingsActivity" + android:description="@string/description"/> diff --git a/PrintService2/src/foo/bar/printservice2/MyPrintService.java b/PrintService2/src/foo/bar/printservice2/MyPrintService.java new file mode 100644 index 0000000..8a4227a --- /dev/null +++ b/PrintService2/src/foo/bar/printservice2/MyPrintService.java @@ -0,0 +1,231 @@ +package foo.bar.printservice2; + +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.print.PrintAttributes; +import android.print.PrintAttributes.Margins; +import android.print.PrintAttributes.Resolution; +import android.print.PrintAttributes.Tray; +import android.print.PrintJobInfo; +import android.print.PrinterId; +import android.print.PrinterInfo; +import android.printservice.PrintJob; +import android.printservice.PrintService; +import android.util.Log; +import android.widget.Toast; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +public class MyPrintService extends PrintService { + + private static final String LOG_TAG = MyPrintService.class.getSimpleName(); + + private Handler mHandler; + + @Override + protected void onConnected() { + mHandler = new MyHandler(getMainLooper()); + Log.i(LOG_TAG, "#onConnected()"); + } + + @Override + protected void onDisconnected() { + Log.i(LOG_TAG, "#onDisconnected()"); + } + + @Override + protected void onStartPrinterDiscovery() { + Log.i(LOG_TAG, "#onStartDiscoverPrinters()"); + Message message1 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_FIRST_FAKE_PRINTER); + mHandler.sendMessageDelayed(message1, 0); + + Message message2 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_SECOND_FAKE_PRINTER); + mHandler.sendMessageDelayed(message2, 10000); + } + + @Override + protected void onStopPrinterDiscovery() { + Log.i(LOG_TAG, "#onStopDiscoverPrinters()"); + } + + @Override + public void onPrintJobQueued(final PrintJob printJob) { + Log.i(LOG_TAG, "#onPrintJobPending()"); + PrintJobInfo info = printJob.getInfo(); + final File file = new File(getFilesDir(), info.getLabel() + ".pdf"); + if (file.exists()) { + file.delete(); + } + AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + InputStream in = new BufferedInputStream( + new FileInputStream(printJob.getData())); + OutputStream out = null; + try { + out = new BufferedOutputStream(new FileOutputStream(file)); + final byte[] buffer = new byte[8192]; + while (true) { + final int readByteCount = in.read(buffer); + if (readByteCount < 0) { + break; + } + out.write(buffer, 0, readByteCount); + } + } catch (IOException ioe) { + /* ignore */ + } finally { + try { + in.close(); + } catch (IOException ioe) { + /* ignore */ + } + if (out != null) { + try { + out.close(); + } catch (IOException ioe) { + /* ignore */ + } + } + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + file.setExecutable(true, false); + file.setWritable(true, false); + file.setReadable(true, false); + + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setDataAndType(Uri.fromFile(file), "application/pdf"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent, null); + + if (printJob.isQueued()) { + printJob.start(); + } + + PrintJobInfo info = printJob.getInfo(); + Toast.makeText(MyPrintService.this, + "Printer: " + info.getPrinterId().getLocalId() + + " copies: " + info.getAttributes().getCopies(), + Toast.LENGTH_SHORT).show(); + + if (printJob.isStarted()) { + printJob.complete(); + } + } + }; + task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); + } + + private void addFirstFakePrinter() { + PrinterId printerId = generatePrinterId("1"); + PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 1") + .setStatus(PrinterInfo.STATUS_READY) + .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0)) + .addMediaSize(PrintAttributes.MediaSize.ISO_A2, false) + .addMediaSize(PrintAttributes.MediaSize.ISO_A3, false) + .addMediaSize(PrintAttributes.MediaSize.ISO_A4, false) + .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false) + .addMediaSize(PrintAttributes.MediaSize.ISO_A6, false) + .addMediaSize(PrintAttributes.MediaSize.NA_LETTER, true) + .addResolution(new Resolution("R1", getPackageName(), + R.string.resolution_600x600, 600, 600), true) + .addInputTray(new Tray("FirstInputTray", getPackageName(), + R.string.input_tray_first), false) + .addOutputTray(new Tray("FirstOutputTray", getPackageName(), + R.string.output_tray_first), false) + .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE + | PrintAttributes.DUPLEX_MODE_LONG_EDGE + | PrintAttributes.DUPLEX_MODE_SHORT_EDGE, + PrintAttributes.DUPLEX_MODE_NONE) + .setColorModes(PrintAttributes.COLOR_MODE_COLOR + | PrintAttributes.COLOR_MODE_MONOCHROME, + PrintAttributes.COLOR_MODE_COLOR) + .setFittingModes(PrintAttributes.FITTING_MODE_NONE + | PrintAttributes.FITTING_MODE_FIT_TO_PAGE, + PrintAttributes.FITTING_MODE_NONE) + .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT + | PrintAttributes.ORIENTATION_LANDSCAPE, + PrintAttributes.ORIENTATION_PORTRAIT) + .create(); + List<PrinterInfo> printers = new ArrayList<PrinterInfo>(); + printers.add(printer); + addDiscoveredPrinters(printers); + } + + private void addSecondFakePrinter() { + PrinterId printerId = generatePrinterId("2"); + PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 2") + .setStatus(PrinterInfo.STATUS_READY) + .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0)) + .addMediaSize(PrintAttributes.MediaSize.ISO_A4, true) + .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false) + .addResolution(new Resolution("R1", getPackageName(), + R.string.resolution_200x200, 200, 200), true) + .addResolution(new Resolution("R2", getPackageName(), + R.string.resolution_300x300, 300, 300), false) + .addInputTray(new Tray("FirstInputTray", getPackageName(), + R.string.input_tray_first), false) + .addInputTray(new Tray("SecondInputTray", getPackageName(), + R.string.input_tray_second), true) + .addOutputTray(new Tray("FirstOutputTray", getPackageName(), + R.string.output_tray_first), false) + .addOutputTray(new Tray("SecondOutputTray", getPackageName(), + R.string.output_tray_second), true) + .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE + | PrintAttributes.DUPLEX_MODE_LONG_EDGE + | PrintAttributes.DUPLEX_MODE_SHORT_EDGE, + PrintAttributes.DUPLEX_MODE_SHORT_EDGE) + .setColorModes(PrintAttributes.COLOR_MODE_COLOR + | PrintAttributes.COLOR_MODE_MONOCHROME, + PrintAttributes.COLOR_MODE_MONOCHROME) + .setFittingModes(PrintAttributes.FITTING_MODE_FIT_TO_PAGE + | PrintAttributes.FITTING_MODE_NONE, + PrintAttributes.FITTING_MODE_FIT_TO_PAGE) + .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT + | PrintAttributes.ORIENTATION_LANDSCAPE, + PrintAttributes.ORIENTATION_LANDSCAPE) + .create(); + List<PrinterInfo> printers = new ArrayList<PrinterInfo>(); + printers.add(printer); + addDiscoveredPrinters(printers); + } + + private final class MyHandler extends Handler { + + public static final int MESSAGE_ADD_FIRST_FAKE_PRINTER = 1; + public static final int MESSAGE_ADD_SECOND_FAKE_PRINTER = 2; + + public MyHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message message) { + switch (message.what) { + case MESSAGE_ADD_FIRST_FAKE_PRINTER: { + addFirstFakePrinter(); + } break; + case MESSAGE_ADD_SECOND_FAKE_PRINTER: { + addSecondFakePrinter(); + } break; + } + } + } +} diff --git a/PrintService2/src/foo/bar/printservice2/SettingsActivity.java b/PrintService2/src/foo/bar/printservice2/SettingsActivity.java new file mode 100644 index 0000000..cc197a8 --- /dev/null +++ b/PrintService2/src/foo/bar/printservice2/SettingsActivity.java @@ -0,0 +1,15 @@ +package foo.bar.printservice2; + +import android.app.Activity; +import android.os.Bundle; + +import foo.bar.printservice2.R; + +public class SettingsActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } +} diff --git a/TestBack/.classpath b/TestBack/.classpath new file mode 100644 index 0000000..a4763d1 --- /dev/null +++ b/TestBack/.classpath @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="gen"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> + <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> + <classpathentry kind="output" path="bin/classes"/> +</classpath> diff --git a/TestBack/.project b/TestBack/.project new file mode 100644 index 0000000..507c2e2 --- /dev/null +++ b/TestBack/.project @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>TestBack</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>com.android.ide.eclipse.adt.ApkBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>com.android.ide.eclipse.adt.AndroidNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/TestBack/Android.mk b/TestBack/Android.mk new file mode 100644 index 0000000..e8f14e6 --- /dev/null +++ b/TestBack/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := TestBack + +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) diff --git a/TestBack/AndroidManifest.xml b/TestBack/AndroidManifest.xml new file mode 100644 index 0000000..672f70b --- /dev/null +++ b/TestBack/AndroidManifest.xml @@ -0,0 +1,38 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="foo.bar.testback" + android:versionCode="1" + android:versionName="1.0" > + + <uses-permission android:name="android.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE"/> + <uses-permission android:name="android.permission.CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY"/> + + <uses-sdk + android:minSdkVersion="JellyBeanMR2" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:allowBackup="false" > + <service + android:name=".TestBackService" + android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> + <intent-filter> + <action android:name="android.accessibilityservice.AccessibilityService" /> + </intent-filter> + <meta-data + android:name="android.accessibilityservice" + android:resource="@xml/accessibilityservice" /> + </service> + <receiver + android:enabled="true" + android:exported="true" + android:name=".IdleMaintenanceReceiver"> + <intent-filter> + <action android:name="FOO" /> + <action android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" /> + <action android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_END" /> + </intent-filter> + </receiver> + </application> + +</manifest> diff --git a/TestBack/res/drawable-hdpi/ic_action_search.png b/TestBack/res/drawable-hdpi/ic_action_search.png Binary files differnew file mode 100644 index 0000000..67de12d --- /dev/null +++ b/TestBack/res/drawable-hdpi/ic_action_search.png diff --git a/TestBack/res/drawable-hdpi/ic_launcher.png b/TestBack/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..a301d57 --- /dev/null +++ b/TestBack/res/drawable-hdpi/ic_launcher.png diff --git a/TestBack/res/drawable-ldpi/ic_launcher.png b/TestBack/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..2c2a58b --- /dev/null +++ b/TestBack/res/drawable-ldpi/ic_launcher.png diff --git a/TestBack/res/drawable-mdpi/ic_action_search.png b/TestBack/res/drawable-mdpi/ic_action_search.png Binary files differnew file mode 100644 index 0000000..134d549 --- /dev/null +++ b/TestBack/res/drawable-mdpi/ic_action_search.png diff --git a/TestBack/res/drawable-mdpi/ic_launcher.png b/TestBack/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..f91f736 --- /dev/null +++ b/TestBack/res/drawable-mdpi/ic_launcher.png diff --git a/TestBack/res/drawable-xhdpi/ic_action_search.png b/TestBack/res/drawable-xhdpi/ic_action_search.png Binary files differnew file mode 100644 index 0000000..d699c6b --- /dev/null +++ b/TestBack/res/drawable-xhdpi/ic_action_search.png diff --git a/TestBack/res/drawable-xhdpi/ic_launcher.png b/TestBack/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..96095ec --- /dev/null +++ b/TestBack/res/drawable-xhdpi/ic_launcher.png diff --git a/TestBack/res/menu/activity_main.xml b/TestBack/res/menu/activity_main.xml new file mode 100644 index 0000000..cfc10fd --- /dev/null +++ b/TestBack/res/menu/activity_main.xml @@ -0,0 +1,6 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_settings" + android:title="@string/menu_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> diff --git a/TestBack/res/values-v11/styles.xml b/TestBack/res/values-v11/styles.xml new file mode 100644 index 0000000..d408cbc --- /dev/null +++ b/TestBack/res/values-v11/styles.xml @@ -0,0 +1,5 @@ +<resources> + + <style name="AppTheme" parent="android:Theme.Holo.Light" /> + +</resources>
\ No newline at end of file diff --git a/TestBack/res/values-v14/styles.xml b/TestBack/res/values-v14/styles.xml new file mode 100644 index 0000000..1c089a7 --- /dev/null +++ b/TestBack/res/values-v14/styles.xml @@ -0,0 +1,5 @@ +<resources> + + <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" /> + +</resources>
\ No newline at end of file diff --git a/TestBack/res/values/strings.xml b/TestBack/res/values/strings.xml new file mode 100644 index 0000000..eefd9b0 --- /dev/null +++ b/TestBack/res/values/strings.xml @@ -0,0 +1,8 @@ +<resources> + + <string name="app_name">TestBack</string> + <string name="hello_world">Hello world!</string> + <string name="menu_settings">Settings</string> + <string name="title_activity_main">MainActivity</string> + +</resources>
\ No newline at end of file diff --git a/TestBack/res/values/styles.xml b/TestBack/res/values/styles.xml new file mode 100644 index 0000000..4dba0d0 --- /dev/null +++ b/TestBack/res/values/styles.xml @@ -0,0 +1,5 @@ +<resources> + + <style name="AppTheme" parent="android:Theme.Light" /> + +</resources>
\ No newline at end of file diff --git a/TestBack/res/xml/accessibilityservice.xml b/TestBack/res/xml/accessibilityservice.xml new file mode 100644 index 0000000..de0613d --- /dev/null +++ b/TestBack/res/xml/accessibilityservice.xml @@ -0,0 +1,5 @@ +<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" + android:accessibilityFeedbackType="feedbackHaptic" + android:accessibilityEventTypes="typeAllMask" + android:canRetrieveWindowContent="true" +/> diff --git a/TestBack/src/foo/bar/testback/Foo.java b/TestBack/src/foo/bar/testback/Foo.java new file mode 100644 index 0000000..6fcbf1a --- /dev/null +++ b/TestBack/src/foo/bar/testback/Foo.java @@ -0,0 +1,45 @@ +package foo.bar.testback; + +public class Foo { + + private Object mValue; + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((mValue == null) ? 0 : mValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Foo other = (Foo) obj; + if (mValue == null) { + if (other.mValue != null) + return false; + } else if (!mValue.equals(other.mValue)) + return false; + return true; + } + + + private class Bar { + protected void doSomething() { + + } + } + + private class Baz extends Bar { + @Override + protected void doSomething() { + + } + } +} diff --git a/TestBack/src/foo/bar/testback/IdleMaintenanceReceiver.java b/TestBack/src/foo/bar/testback/IdleMaintenanceReceiver.java new file mode 100644 index 0000000..d3f1266 --- /dev/null +++ b/TestBack/src/foo/bar/testback/IdleMaintenanceReceiver.java @@ -0,0 +1,18 @@ +package foo.bar.testback; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Debug; +import android.util.Log; + +public class IdleMaintenanceReceiver extends BroadcastReceiver { + + private static final String LOG_TAG = IdleMaintenanceReceiver.class.getSimpleName(); + + @Override + public void onReceive(Context context, Intent intent) { + Debug.waitForDebugger(); + Log.i(LOG_TAG, (intent.getAction() != null) ? intent.getAction() : "null"); + } +} diff --git a/TestBack/src/foo/bar/testback/TestBackService.java b/TestBack/src/foo/bar/testback/TestBackService.java new file mode 100644 index 0000000..bb47621 --- /dev/null +++ b/TestBack/src/foo/bar/testback/TestBackService.java @@ -0,0 +1,145 @@ +package foo.bar.testback; + +import android.accessibilityservice.AccessibilityService; +import android.accessibilityservice.AccessibilityServiceInfo; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.KeyEvent; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; + +public class TestBackService extends AccessibilityService { + + private static final String LOG_TAG = TestBackService.class.getSimpleName(); + + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + AccessibilityManager am = (AccessibilityManager) + getSystemService(ACCESSIBILITY_SERVICE); + Log.i(LOG_TAG, "accessibilityEnabled: " + am.isEnabled() + + " touchExplorationEnabled: " + am.isTouchExplorationEnabled()); +// AccessibilityServiceInfo info = getServiceInfo(); +// if ((info.flags & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) == 0) { +// info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE; +// } else { +// info.flags &= ~AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE; +// } +// setServiceInfo(info); + sendEmptyMessageDelayed(0, 20000); + } + }; + + @Override + public void onAccessibilityEvent(AccessibilityEvent event) { +// Log.i(LOG_TAG, AccessibilityEvent.eventTypeToString(event.getEventType())); + } + + @Override + protected boolean onGesture(int gestureId) { + switch (gestureId) { + case AccessibilityService.GESTURE_SWIPE_DOWN: { + dumpIdResNames(getRootInActiveWindow()); + } break; + // COPY + case AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT: { + AccessibilityNodeInfo root = getRootInActiveWindow(); + if (root != null) { + AccessibilityNodeInfo focus = root.findFocus( + AccessibilityNodeInfo.FOCUS_INPUT); + if (focus != null) { + if ((focus.getActions() & 0x00004000) /* COPY*/ != 0) { + final boolean performed = focus.performAction(0x00004000); + Log.i(LOG_TAG, "Performed: " + performed); + } + focus.recycle(); + } + root.recycle(); + } + } break; + // PASTE + case AccessibilityService.GESTURE_SWIPE_UP: { + AccessibilityNodeInfo root = getRootInActiveWindow(); + if (root != null) { + AccessibilityNodeInfo focus = root.findFocus( + AccessibilityNodeInfo.FOCUS_INPUT); + if (focus != null) { + if ((focus.getActions() & 0x00008000) /* PASTE*/ != 0) { + final boolean performed = focus.performAction(0x00008000); + Log.i(LOG_TAG, "Performed: " + performed); + } + focus.recycle(); + } + root.recycle(); + } + } break; + // CUT + case AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT: { + AccessibilityNodeInfo root = getRootInActiveWindow(); + if (root != null) { + AccessibilityNodeInfo focus = root.findFocus( + AccessibilityNodeInfo.FOCUS_INPUT); + if (focus != null) { + if ((focus.getActions() & 0x00010000) /* CUT*/ != 0) { + final boolean performed = focus.performAction(0x00010000); + Log.i(LOG_TAG, "Performed: " + performed); + } + focus.recycle(); + } + root.recycle(); + } + } break; + // SELECT_ALL + case AccessibilityService.GESTURE_SWIPE_RIGHT_AND_UP: { + AccessibilityNodeInfo root = getRootInActiveWindow(); + if (root != null) { + AccessibilityNodeInfo focus = root.findFocus( + AccessibilityNodeInfo.FOCUS_INPUT); + if (focus != null) { + if ((focus.getActions() & 0x00020000) /* SELECT ALL*/ != 0) { + final boolean performed = focus.performAction(0x00020000); + Log.i(LOG_TAG, "Performed: " + performed); + } + focus.recycle(); + } + root.recycle(); + } + } break; + } + return super.onGesture(gestureId); + } + + @Override + public boolean onKeyEvent(KeyEvent event) { + Log.i(LOG_TAG, "onKeyEvent: " + event); + boolean result = false; + return result; + } + + private void dumpIdResNames(AccessibilityNodeInfo root) { + if (root == null) { + return; + } + if (root.getViewIdResourceName() != null) { + Log.i(LOG_TAG, root.getViewIdResourceName().toString()); + } + final int childCount = root.getChildCount(); + for (int i = 0; i < childCount; i++) { + dumpIdResNames(root.getChild(i)); + } + } + + @Override + public void onInterrupt() { + /* ignore */ + } + + @Override + public void onServiceConnected() { +// AccessibilityServiceInfo info = getServiceInfo(); +// info.flags |= AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS; +// setServiceInfo(info); + } +} |