Androidの旅--普通ではないフォームをポップアップする方法

8530 ワード

前編ではandroidでjavaコマンドを実行するとは聞いたことのない方法を紹介したが、これは非常に「高級」な技術であり、卵用はないため、ブログ園のトップページから削除された.実際には何の役にも立たないわけではないが、すぐにアンドロイドの原理に役立つ.
この文章は引き続き1種の更に“高級”の技術を紹介して、androidの中で1つの尋常ではないフォームを弾いて、このフォームは普通のフォームではありませんて、すでにandroid fragment層に通り抜けたため、SupperWindowsと呼ばれて、apkファイルがなくて、インストールを経ないで、このフォームは空で現れます!
 
このようなフォームを弾くのは、WindowManagerServiceを紹介する記事を前に見たためで、このようなフォームを通じて面WindowManagerServiceの動作メカニズムを説明する必要があります.
原文住所:http://blog.csdn.net/innost/article/details/47660193
frameworkレイヤのコードが使用されているため、本文のコードはandroidソース環境でコンパイルされています.
androidソースコードをコンパイルするのはとても面倒なことなので、他にコンパイルできる方法はないかと思っていました.前にコード注入をしたときもfragment層を使っていたので、ソースコードの環境でなくてもコンパイルでき、コードを実行する方法は私の前に使ったのと同じで、app_process.
前回の文を書いたとき、どうしてテストしないのかとふと思った.
最初はシステムディレクトリの下のjarバーを出してdex形式ではないjarパッケージを逆コンパイルしてlibに追加して、依存する関数を見つけることができます.
しかしandroid 5.0のデバイスにjarパッケージに内容がないことに気づき、出しても何の役にも立たないのでandroid 4に変えました.2のデバイス、4.2の/system/fragmentディレクトリの下でjarと同命のまだあります.odexのファイルは、odexファイルは最終的に使用可能なjarパッケージを得る.
以前は正式にこのような方法で操作されていましたが、ポップアップフォームのコードをコンパイルすることはできません.いくつかのインタフェースクラスが見つかりません.これらのクラスはaidlが生産した逆コンパイルでこれらのクラスを得ることはできません.
しかし、幸いなことに、これらのaidlファイルを検索すると、aidlが自動的に生成したインタフェースクラスを含むコンテンツの完全なfragmentレイヤコードを直接ダウンロードできるサイトが見つかりました.
http://grepcode.com/snapshot/repository.grepcode.com/java/ext/com.google.android/android/4.2_r1/
「Binary download」を選択し、ダウンロードしてlibの下に直接置くと依存の問題を解決できます.上のアドレスは4.2のソースコードです.
依存の問題を解決したら、どのようにコンパイルしますか.
Javaプロジェクトを新規作成し、SupperWindowsを構築します.JAvaクラス、packageはcomで、前のWindowManagerServiceの文章のコードをコピーします.
package com;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.*;
import android.hardware.display.IDisplayManager;
import android.os.*;
import android.view.*;

public class SuperWindows {

public static void main(String[] args) {
System.out.println("Hello SuperWindows");
try {
//SampleWindow.Run()         
new SuperWindows().Run();
} catch (Exception e) {
e.printStackTrace();
}
}
//IWindowSession      WMS           ,        
IWindowSession mSession = null;
//InputChannel               。  5            
InputChannel mInputChannel = new InputChannel();

//      Rect          。  mFrame               
//  4.4                 
Rect mInsets = new Rect();
Rect mFrame = new Rect();
Rect mVisibleInsets = new Rect();

Configuration mConfig = new Configuration();
//    Surface,  Surface                 
Surface mSurface = new Surface();
//              
Paint mPaint = new Paint();
//          , 4.2         
IBinder mToken = new Binder();

//       ,              WMS ,          
MyWindow mWindow = new MyWindow();

//WindowManager.LayoutParams          ,    、         
WindowManager.LayoutParams mLp = new WindowManager.LayoutParams();

Choreographer mChoreographer = null;
//InputHandler    InputChannel          
InputHandler mInputHandler = null;

boolean mContinueAnime = true;

public void Run() throws Exception{
Looper.prepare();
//   WMS  
IWindowManager wms = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));

//   WindowManagerGlobal       IWindowSession  。     WMS
//     。          Android  ( 4.1)  ViewRootImpl  
mSession= WindowManagerGlobal.getWindowSession(Looper.myLooper());

//        
IDisplayManager dm = IDisplayManager.Stub.asInterface(
ServiceManager.getService(Context.DISPLAY_SERVICE));
DisplayInfo di = dm.getDisplayInfo(Display.DEFAULT_DISPLAY);
Point scrnSize = new Point(di.appWidth, di.appHeight);
//    WindowManager.LayoutParams
initLayoutParams(scrnSize);

//        WMS
installWindow(wms);

//    Choreographer   ,        。       Handler
//   ,      VSYC     ,   Handler          [1]
mChoreographer= Choreographer.getInstance();

//           
scheduleNextFrame();

//           ,  Looper.quit()
Looper.loop();

//            
mContinueAnime= false;

//     Window
uninstallWindow(wms);
}

public void initLayoutParams(Point screenSize) {
//             SYSTEM_ALERT,       ZOrder      
mLp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
mLp.setTitle("SampleWindow");
//                  
mLp.gravity = Gravity.LEFT | Gravity.TOP;
mLp.x = screenSize.x / 4;
mLp.y = screenSize.y / 4;
mLp.width = screenSize.x / 2;
mLp.height = screenSize.y / 2;
//         Flag,                ,             
mLp.flags = mLp.flags | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
}

public void installWindow(IWindowManager wms) throws Exception {
//    WMS    Token,    Window             Token
wms.addWindowToken(mToken,WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
//         Token
mLp.token = mToken;
//   IWindowSession      WMS,  ,        WMS,   Window
//          Surface。  ,       ,mInputChannel        
//      
mSession.add(mWindow,0, mLp, View.VISIBLE, mInsets, mInputChannel);
/*  IWindowSession  WMS          ,       ,WMS     
         Surface      mSurface 。  ,  Surface WMS   
LayoutParams        */
mSession.relayout(mWindow,0, mLp, mLp.width, mLp.height, View.VISIBLE,
0, mFrame, mInsets,mVisibleInsets, mConfig, mSurface);
if(!mSurface.isValid()) {
throw new RuntimeException("Failed creating Surface.");
}
//   WMS   InputChannel    Handler,        
//mInputHandler     ,           
mInputHandler= new InputHandler(mInputChannel, Looper.myLooper());
}

public void uninstallWindow(IWindowManager wms) throws Exception {
//  WMS     
mSession.remove(mWindow);
//  WMS        Token
wms.removeWindowToken(mToken);
}

public void scheduleNextFrame() {
//                mFrameRender,  ,     
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION
, mFrameRender, null);
}

//   Runnable            
public Runnable mFrameRender = new Runnable() {
@Override
public void run() {
try{
//        
long time = mChoreographer.getFrameTime() % 1000;

//   
if (mSurface.isValid()) {
Canvas canvas = mSurface.lockCanvas(null);
canvas.drawColor(Color.WHITE);
canvas.drawRect(2 * mLp.width / 1000
- mLp.width, 0, 2 *mLp.width
/ 1000, mLp.height,mPaint);
String text = "              !";
canvas.drawText(text, 0, text.length(), 10, 20, mPaint);
mSurface.unlockCanvasAndPost(canvas);
mSession.finishDrawing(mWindow);
}

if(mContinueAnime)
scheduleNextFrame();
} catch (Exception e) {
e.printStackTrace();
}
}
};

//        InputEventReceiver,    onInputEvent()            
class InputHandler extends InputEventReceiver {
Looper mLooper = null;
public InputHandler(InputChannel inputChannel, Looper looper) {
super(inputChannel,looper);
mLooper= looper;
}
@Override
public void onInputEvent(InputEvent event) {
if(event instanceof MotionEvent) {
MotionEvent me = (MotionEvent)event;
if (me.getAction() ==MotionEvent.ACTION_UP) {
//     
mLooper.quit();
}
}
super.onInputEvent(event);
}
}

//        IWindow.Stub  MyWindow。
class MyWindow extends IWindow.Stub {
//          
}
}

  
上記android-4.2_をインポートr1.JAr依存パッケージは、依存問題を解決し、コンパイルすればsuperwindowsを得ることができる.jarファイル.
もちろん原始的です.JArはandroidでは実行できません.dexに移行するには、sdkのdxコマンドを使用してsuperwindowsを使用します.义齿dex.dxプログラムはsdkのbuild-toolディレクトリの下にあります.
dx --dex --output=superwindows.dex superwindows.jar
Androidデバイスにdexを転送:adb push SupperWindows.dex/data/local/tmp/
suコマンドを実行するとroot権限が得られ、rootが次のコマンドを実行しない場合は権限がないことがプロンプトされます.
実行app_process -Djava.class.path=/data/local/tmp/superwindows.dex/system/bin com.SuperWindows、SuperWindowsを実行します.app_プロセスのコードはapp_main.cppで見ました.
最初に実行したときに何が原因でプログラムがクラッシュしたのか分からず、再び命令を実行すれば問題なく、他に問題がなければポップアップしたSupperWindowsフォームを見ることができます.
suを実行してroot権限を取得した後、app_を使用します.プロセスがロードしたコードは同じようにroot権限を感じているので、テロリストに見られないでほしい.
詳細は私の微信の公衆番号に注目してください:zhaojieTec