Android 一种用于临时打开和关闭屏幕自动旋转的方法

这种方法的前提是你需要能编译Android framework。如果不能,可以试试 这个

其实在frameworks/base/services/java/com/android/server/wm/WindowManagerService.java中有下面两个方法:

    /**
     * Temporarily pauses rotation changes until resumed.
     *
     * This can be used to prevent rotation changes from occurring while the user is
     * performing certain operations, such as drag and drop.
     *
     * This call nests and must be matched by an equal number of calls to
     * {@link #resumeRotationLocked}.
     */
    void pauseRotationLocked() {
        mDeferredRotationPauseCount += 1;
    }
    /**
     * Resumes normal rotation changes after being paused.
     */
    void resumeRotationLocked() {
        if (mDeferredRotationPauseCount > 0) {
            mDeferredRotationPauseCount -= 1;
            if (mDeferredRotationPauseCount == 0) {
                boolean changed = updateRotationUncheckedLocked(false);
                if (changed) {
                    mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
                }
            }
        }
    }

代码注释很清楚的说明了这两个方法的功能,但是这两个方法的访问权限并没有把他们提供给外界。

我们在这里添加两个自己的方法:

    public void myPauseRotationLocked() {
        pauseRotationLocked();
    }
    public void myResumeRotationLocked() {
        resumeRotationLocked();
    }

WindowsManagerService通过AIDL与外界通信,这里我们需要添加AIDL接口定义。 在framework/base/core/java/android/view/IWindowManager.aidl中添加两个接口:

void myPauseRotationLocked();
void myResumeRotationLocked()

我们希望最后能通过getSystemService(Context.WINDOW_SERVICE)的方式来方便的调取这两个方法,所以我们还需要做一些事情。 首先在framework/core/java/android/view/WindowManagerGlobal.java中加入:

     public void myPauseRotationLocked() {
         try {
             sWindowManagerService.myPauseRotationLocked();
         } catch (RemoteException e) {
             Log.e(TAG, "myPauseRotationLocked ERROR!", e);
         }
     }
 
     public void myResumeRotationLocked() {
         try {
             sWindowManagerService.myResumeRotationLocked();
         } catch(RemoteException e) {
             Log.e(TAG, "myPauseRotationLocked ERROR!", e);
         }
     }

这里的sWindowManagerService为IWindowManager的实例。

然后在framework/basecore/java/android/view/WindowManager.java中加入:

public void myPauseRotationLocked();
public void myResumeRotationLocked();

WindowManager的具体实现在: framework/base/core/java/android/view/WindowManagerImpl.java 添加下面两个方法:

      @Override
      public void myPauseRotationLocked() {
          mGlobal.myPauseRotationLocked();
      }
  
     @Override
      public void myResumeRotationLocked() {
         mGlobal.myReresumeRotationLocked();
     }

查看一下mGlobal的类型为WindowManagerGlobal。

至此,大部分工作都已经完成了,由于我们这里变更了framework的API,所以需要

make update-api

最后编译android framework和service即大功告成 !

使用方法

WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
//关闭自动旋转
wm.myPauseRotationLocked();

//打开自动旋转
wm.myResumeRotationLocked();

特别注意这两个方法需要成对使用,否则容易造成状态混乱。

Android 获取StatusBar和NavigationBar的高度

在Activity中

int getStatusBarHeight {
    Rect frame = new Rect();
    getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    return frame.top;
}

在View中

int getStatusBarHeight {
    Rect frame = new Rect();
    (Activity(mContext)).getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    return frame.top;
}

这种基于Window的方法可能不适用对话框窗口。

还有一种简单直接的方法:

 private int getStatusBarHeight() {
       return mContext.getResources().getDimensionPixelSize(
              com.android.internal.R.dimen.status_bar_height);
 }

或者:

static final int mStatusBarHeight = (int) Resources.getSystem().getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
static final int mNavigationBarHeight = (int) Resources.getSystem().getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);                                                                                                   

使用反射

        Class c;
        try {
            c = Class.forName("com.android.internal.R$dimen");
            Object obj = c.newInstance();
            Field field = c.getField("status_bar_height");
            int dim = Integer.parseInt(field.get(obj).toString());
            statusBarHeight = getResources().getDimensionPixelSize(dim);
        } catch (Exception e) {
            e.printStackTrace();
        }

在 FrameLayout 中使用 marginBottom

想把一个控件放到FrameLayout的底部位置,尝试了好久layout_marginBottom属性,居然毫无作用。但是layout_marginTop又是可以正确显示的。

现象如下:

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="50dp"
            android:text="This text should be at bottom"
            android:textSize="20dp" />
    </FrameLayout>

显示如下图(错误): 1

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            android:text="This text should be at bottom"
            android:textSize="20dp" />
    </FrameLayout>

显示如下图(正确): 1

解决方案:

需要在做layout_marginBottom前设置layout_gravity为bottom

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"

            android:layout_gravity="bottom"

            android:layout_marginBottom="50dp"
            android:text="This text should be at bottom"
            android:textSize="20dp" />
    </FrameLayout>

显示如下图(正确): 1

Android 使用比例布局

当你在设计屏幕布局的时候,不想写死各子控件的位置大小,又不想在代码里动态布局,可以试试使用layout_weight,通过保持各子控件占据屏幕的比例来自适应屏幕。

基本思路:设置各子控件的layout_weight(改控件所占的比例),然后设置高度为0

<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"
    android:orientation="vertical" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#FFFF0000"
        android:text="This is TextView 1" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:background="#FF00FF00"
        android:text="This is TextView 2" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="3"
        android:background="#FF0000FF"
        android:text="This is TextView 3" />

</LinearLayout>

获取 Android 内存和进程信息

   ActivityManager mAm = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);

    private  int getAppsRunning() {
        List<RunningAppProcessInfo> runningApps = mAm.getRunningAppProcesses();
        return runningApps.size();
    }
    
    private long getFreeMemory() {
        MemoryInfo mi = new MemoryInfo();
        mAm.getMemoryInfo(mi);
       return mi.availMem;
    }