Budapest University of Technology and Economics培训Android技术已经有8年多的时间。公司里有个传统就是每周进行技术分享,这里将介绍一些Android平台上有意思的API。

当前Android已经有了非常多可用的依赖库(Library),但其实Android platform的一些API有些鲜为人知,但非常有用的方法和类,去研究一下这些API是非常有意思的。

我们知道Android API依赖的Java SE API也非常庞大,根据统计,Java SE 8有217个package,4240个方法,而java SE 7有209个package,4024个方法。


source: Java 8 Pocket Guide book by Robert Liguori, Patricia Liguor

在这个系列文章中,我们将从不同角度展示一些鲜为人知的Android API,并使用这些API写了demo

demo App中给出的每个API的使用都是在不同的Activity中,从App首页可以进入到不同的API demoActivity。


拼写检查

Android从level 14开始有一个检查拼写的API,可以通过 TextServicesManager使用,从level16开始已经可以甚至可以检查一个完整的句子了。

使用方法非常简单,通过 TextServicesManager可以创建SpellCheckerSession:


  1. TextServicesManager tsm = (TextServicesManager) getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);  
  2. SpellCheckerSession spellCheckerSession = tsm.newSpellCheckerSession(null, null, this, true


可以通过实现SpellCheckerSessionListener接口得到检查结果:


  1. onGetSuggestions(SentenceSuggestionsInfo[] sentenceSuggestionsInfos)
  2. onGetSentenceSuggestions(SentenceSuggestionsInfo[] sentenceSuggestionsInfos));


SentenceSuggestionsInfo数据中保存了正确的文字、偏移量以及所有相关的信息。

demo地址SpellCheckerActivity

文字识别

Google Play Services Vision API中提供的功能,可以通过gradle dependency非常简单的引入到project中,需要注意的是不要引入整个Play Services,因为Play Services非常大,而我们需要的只是其中的一小部分,https://developers.google.com/android/guides/setup中可以找到相关的帮助。

Vision API中包含的服务有:

  • 人脸识别
  • 条形码扫描
  • 文字识别

使用 Text Recognizer API非常简单:

首先,在build.gradle中引入依赖:

  1. compile 'com.google.android.gms:play-services-vision:10.0.1'

然后创建TextRecognizer对象:

  1. TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build();

之后实现 Detector.Processor 接口接口监听结果,得到的结果是TextBlock 数组。

1. public class OcrDetectorProcessor implements Detector.Processor<TextBlock> {
2.  
3.     @Override
4.     public void receiveDetections(Detector.Detections<TextBlock> detections) {
5.         ...
6.         SparseArray<TextBlock> items = detections.getDetectedItems();
7.         ...
8.     }
9.  
10.     @Override
11.     public void release() {
12.     }
13. }

合理地使用 TextRecognizer,一般要自定义包含SurfaceView的View用于在屏幕显示结果。demo地址 OCRActivity , ocr中有一些帮助类。

TimingLogger

TimingLogger可以很容易地计算两个log信息之间的时间差,如下所示:

D/TAG_MYJOB: MyJob: begin D/TAG_MYJOB: MyJob:      2002 ms, Phase 1 ready D/TAG_MYJOB: MyJob:      2002 ms, Phase 2 ready D/TAG_MYJOB: MyJob:      2001 ms, Phase 3 ready D/TAG_MYJOB: MyJob: end, 6005 ms

使用TimingLogger:

  1. TimingLogger timings = new TimingLogger("TAG_MYJOB", "MyJob");

addSplit(...)

  1. timings.addSplit("Phase 1 ready");

dumpToLog()后,log信息就会打印出来:

  1. timings.dumpToLog();

注意要使用TimingLogger, 要设置adb命令是Tag可用:

  1. setprop log.tag.TAG_MYJOB VERBOSE

demo地址:TimingLoggerActivity.

截屏

在某些情况下,截屏非常有用。也有一些第三方库如 Falcon实现这个功能,从level 21开始 MediaProjection可以实时获取屏幕内容和系统声音信息流。

getWindow()非常简单地把屏幕内容保存为Bitmap:

  1. View viewRoot = getWindow().getDecorView().getRootView();  
  2. viewRoot.setDrawingCacheEnabled(true);  
  3. Bitmap screenShotAsBitmap = Bitmap.createBitmap(viewRoot.getDrawingCache());  
  4. viewRoot.setDrawingCacheEnabled(false);  
  5. // use screenShotAsBitmap as you need

demo地址:ScreenCaptureActivity.

PDF创建

从level 19开始Android支持本地内容生成PDF文件。

new PdfDocument.PageInfo.Builder(w,h,pageNum).create() ;,然后使用PDFDocument中的startPage([pageInfo])就可以创建一个PDF文件了。

以下的代码创建了一个demo.pdf文件:

1. public void createPdfFromCurrentScreen() {  
2.     new Thread() {
3.         public void run() {
4.             // Get the directory for the app's private pictures directory.
5.             final File file = new File(
6.                     Environment.getExternalStorageDirectory(), "demo.pdf");
7.  
8.             if (file.exists ()) {
9.                 file.delete ();
10.             }
11.  
12.             FileOutputStream out = null;
13.             try {
14.                 out = new FileOutputStream(file);
15.  
16.                 PdfDocument document = new PdfDocument();
17.                 Point windowSize = new Point();
18.                 getWindowManager().getDefaultDisplay().getSize(windowSize);
19.                 PdfDocument.PageInfo pageInfo =
20.                         new PdfDocument.PageInfo.Builder(
21.                         windowSize.x, windowSize.y, 1).create();
22.                 PdfDocument.Page page = document.startPage(pageInfo);
23.                 View content = getWindow().getDecorView();
24.                 content.draw(page.getCanvas());
25.                 document.finishPage(page);
26.                 document.writeTo(out);
27.                 document.close();
28.                 out.flush();
29.  
30.                 runOnUiThread(new Runnable() {
31.                     @Override
32.                     public void run() {
33.                         Toast.makeText(PDFCreateActivity.this, "File created: "+file.getAbsolutePath(), Toast.LENGTH_LONG).show();
34.                     }
35.                 });
36.             } catch (Exception e) {
37.                 Log.d("TAG_PDF", "File was not created: "+e.getMessage());
38.             } finally {
39.                 try {
40.                     out.close();
41.                 } catch (IOException e) {
42.                     e.printStackTrace();
43.                 }
44.             }
45.         }
46.     }.start();
47. }

感谢阅读。