初心

何期自性,本自具足

使用FFMpeg2和SDL2在android播放音频

| Comments

准备工作

编译环境 Ubuntu12.04 64位。

  1. 下载对应环境的 ndk9 :http://developer.android.com/tools/sdk/ndk/index.html

  2. 下载 FFMpeg,网上的资源,使用0.11版本的较多,使用2.0及以后的较少,api中函数名称和传入参数略有不同。

    下载地址 https://github.com/FFmpeg/FFmpeg,下载master或其他分支,这里下载的2.0版本。

     git clone -b release/2.0 https://github.com/FFmpeg/FFmpeg.git
    
  3. 下载SDL,网上的资源,使用1.2及以下的资源很多,关于2.0的资料非常少,但据说效率有提高。

下载地址 http://www.libsdl.org/download-2.0.php

Android隐藏下方系统栏statusbar

| Comments

最近修复了一个BUG是定制SetupWizard时,下面的系统栏会出现。

SetupWizard是一台安卓设备第一次运行时的设置程序,可以设置Google帐号,姓名什么的,所以不允许用户点击返回、Home或最近运行三个虚拟按键。

当设置Google帐号时,会打开GoogleLoginService的Activity,所以用网上的有些方法不好用。一进入输入状态时,StatusBar还会显示出来。

源码Launcher编译,使用mdpi的资源

| Comments

4.2.2的源码,进行对Launcher2的修改,之后使用mm或mmm编译,使用adb push安装到平板中。

因为使用的一代nexus7,所以一般程序调用资源的是drawable_sw600dp_hdpi下的图片资源,但是按照上面方法编译出的Launcher使用drawable_sw600dp_mdpi的图片资源。

在网上搜索后,解决方法是

默认编译mdpi的apk,如果要编译hdpi,需要在./build/target/product/full.mk文件中添加:

1
2
PRODUCT_AAPT_CONFIG := normal hdpi 
PRODUCT_AAPT_PREF_CONFIG := hdpi

经过测试,

PRODUCT_AAPT_CONFIG指定了hdpi的话,就会使用hdpi的资源,而不使用mdpi资源!指定xhdpi的话,就不会使用hdpi的资源!

PRODUCT_AAPT_PREF_CONFIG指定hdpi,编译出的APK中会有hdpi、mdpi等等,没有xhdpi和xxhdpi,默认是mdpi,所以编译出的APK中就没有hdpi。

aapt 是android assert packaging tool的缩写,即安卓打包工具。

加上这两句以后,会影响其参数,只为一种设备匹配文件。而eclipse生成的程序可以为多种设备匹配。

自定义widget上的字体类型

| Comments

对于Activity中的TextView之类的现实文字的控件,如果我们要使用自定义的字体,不能在XML里定义,只能在代码中实现。

一般的做法是将字体文件保存在assets/fonts/目录下,然后使用代码

1
2
3
TextView textView = (TextView) findViewById(R.id.textview);
Typeface typeFace = Typeface.createFromAsset(getAssets(),"fonts/Cambira.ttf");
textView.setTypeface(typeFace);

而widget使用RemoteView更新界面,无法使用这种方法设置自定义字体。

可以使用以下方法

参见 http://stackoverflow.com/questions/4318572/how-to-use-a-custom-typeface-in-a-widget

即使用ImageView代替TextView,自己绘制自定义字体的图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public Bitmap buildUpdate(String time) 
{
    Bitmap myBitmap = Bitmap.createBitmap(160, 84, Bitmap.Config.ARGB_4444);
    Canvas myCanvas = new Canvas(myBitmap);
    Paint paint = new Paint();
    Typeface clock = Typeface.createFromAsset(this.getAssets(),"Clockopia.ttf");
    paint.setAntiAlias(true);
    paint.setSubpixelText(true);
    paint.setTypeface(clock);
    paint.setStyle(Paint.Style.FILL);
    paint.setColor(Color.WHITE);
    paint.setTextSize(65);
    paint.setTextAlign(Align.CENTER);
    myCanvas.drawText(time, 80, 60, paint);
    return myBitmap;
}
1
2
3
String time = (String) DateFormat.format(mTimeFormat, mCalendar);
RemoteViews views = new RemoteViews(getPackageName(), R.layout.main);
views.setImageViewBitmap(R.id.TimeView, buildUpdate(time));

Git Add . 无法添加文件夹下的文件

| Comments

今天提交版本时遇到了git目录无法添加文件夹下的文件。比如要提交A文件夹,而程序代码在A/B文件夹下。使用git add . 只能加入一个空的B文件夹。这个原因是B文件夹是从别的git库拉下来的,只要把B下的隐藏文件.git删掉就可以了。

对Bitmap进行缩放

| Comments

使用以下方法对Bitmap进行缩放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
         if (bitmap == null) {
             return null;
         }

         int w = bitmap.getWidth();
         int h = bitmap.getHeight();
         Matrix matrix = new Matrix();
         float scaleWidth = ((float) width / w);
         float scaleHeight = ((float) height / h);
         matrix.postScale(scaleWidth, scaleHeight);
         Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
         return newbmp;
    }

或者直接使用

1
2
3
import android.media.ThumbnailUtils;
//... ...
ThumbnailUtils.extractThumbnail(Bitmap bitmap, int width, int height)方法

Launcher中锁定图标位置

| Comments

一、使图标不能被挤开

在Launcher中,AllAppsButton的图标是在Hotseat.java加载的,并且设置了对应的layoutparams的属性 canReorder = false;

如字面上的意思,设置了此属性为false的layoutparams中的图标不能被重新排序,即不能被直接或间接挤开。但是可以移动(AllApps按钮不能移动,使因为在hotseat.java单独加载时,没有绑定长按监听器)。当拖动其他图标到此处时,可以形成文件夹。所以如果对此有需求,还要更改其他对应的代码。

通过对源码的搜索,发现只有两处用到了这个属性。

一处是在rearrangementExists方法

1
2
3
4
5
6
if (Rect.intersects(r0, r1)) {
    if (!lp.canReorder) {
        return false;
    }
    mIntersectingViews.add(child);
}

注释掉此处后,图标可以被直接挤开。

另一处是pushViewsToTempLocation方法

1
2
3
4
5
6
7
8
9
if (!cluster.views.contains(v) && v != dragView) {
    if (cluster.isViewTouchingEdge(v, whichEdge)) {
        LayoutParams lp = (LayoutParams) v.getLayoutParams();
        if (!lp.canReorder) {
            // The push solution includes the all apps button,  
            // this is not viable.  
            fail = true;
            break;
        }

注释掉此处后,图标可以被间接挤开,也就是挤压相邻的另一个图标。

launcher2的Folder布局相关

| Comments

这里只写文件图标相关,主要是FolderIcon.java控制。可以看到,FolderIcon是LinearLayout的子类。

观察/res/layout-land(port)/folder_icon.xml,FolderIcon是由一个ImageView和一个BubbleTextView组成,这个ImageView是FolderIcon的背景。

在这里可以调整文件夹图标的大小。在BubbleTextView对应的的style里调整padding、字体大小、文字与图标间距等。

再看FolderIcon.java。

有一些final的属性,比如显示preview的图标的个数,默认是3个。以及相关动画显示的时间等。

Folder的加载可以参考这篇博客 http://blog.csdn.net/wdaming1986/article/details/7748738

显示的程序图标预览在computePreviewItemDrawingParams()方法,之后通过drawPreviewItem()绘制在屏幕上。

当拖动图标移动到一个文件夹上时,会调用CellLayout的onDraw方法,显示蓝色的外框和内部背景。

当点击Hotseat上FolderIcon,打开文件夹后,Hotseat上会显示表示文件夹位置的一个小篮圈,这个也是在CellLayout的onDraw方法里实现的。在growAndFadeOutFolderIcon()方法判断是不是位于Hotseat。

调用顺序依次是onClick【Launcher.java】 -> handleFolderClick【Launcher.java】 -> openFolder【Launcher.java】 -> growAndFadeOutFolderIcon【Launcher.java】 -> setFolderLeaveBehindCell【CellLayout.java】 -> invalidate【CellLayout.java】