編輯:關於Android編程
@Override
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity)null, intent, -1, options);
}
// 先獲取到當前的ActivityThread對象
Class activityThreadClass = Class.forName("android.app.ActivityThread");
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
currentActivityThreadMethod.setAccessible(true);
Object currentActivityThread = currentActivityThreadMethod.invoke(null);
package com.example.hookstartactivity;
import java.lang.reflect.Method;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.Instrumentation.ActivityResult;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
public class InstrumentationProxy extends Instrumentation {
public static final String TAG = "InstrumentationProxy";
public static final String EXEC_START_ACTIVITY = "execStartActivity";
// ActivityThread裡面原始的Instrumentation對象,這裡千萬不能寫成mInstrumentation,這樣寫
//拋出異常,已親測試,所以這個地方就要注意了
public Instrumentation oldInstrumentation;
//通過構造函數來傳遞對象
public InstrumentationProxy(Instrumentation mInstrumentation) {
oldInstrumentation = mInstrumentation;
}
//這個方法是由於原始方法裡面的Instrumentation有execStartActivity方法來定的
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
Log.d(TAG, "\n打印調用startActivity相關參數: \n" + "who = [" + who + "], " +
"\ncontextThread = [" + contextThread + "], \ntoken = [" + token + "], " +
"\ntarget = [" + target + "], \nintent = [" + intent +
"], \nrequestCode = [" + requestCode + "], \noptions = [" + options + "]");
Log.i(TAG, "------------hook success------------->");
Log.i(TAG, "這裡可以做你在打開StartActivity方法之前的事情");
Log.i(TAG, "------------hook success------------->");
Log.i(TAG, "");
//由於這個方法是隱藏的,所以需要反射來調用,先找到這方法
try {
Method execStartActivity = Instrumentation.class.getDeclaredMethod(
EXEC_START_ACTIVITY,
Context.class, IBinder.class, IBinder.class, Activity.class,
Intent.class, int.class, Bundle.class);
execStartActivity.setAccessible(true);
return (ActivityResult) execStartActivity.invoke(oldInstrumentation, who,
contextThread, token, target, intent, requestCode, options);
} catch (Exception e) {
//如果你在這個類的成員變量Instrumentation的實例寫錯mInstrument,代碼講會執行到這裡來
throw new RuntimeException("if Instrumentation paramerter is mInstrumentation, hook will fail");
}
}
}
package com.example.hookstartactivity;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import android.app.Application;
import android.app.Instrumentation;
import android.util.Log;
public class MyApplication extends Application {
public static final String TAG = "MyApplication";
public static final String ACTIVIT_THREAD = "android.app.ActivityThread";
public static final String CURRENT_ACTIVITY_THREAD = "currentActivityThread";
public static final String INSTRUMENTATION = "mInstrumentation";
@Override
public void onCreate() {
try {
//這個方法一般是寫在Application的oncreate函數裡面,如果你寫在activity裡面的oncrate函數裡面就已經晚了
attachContext();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void attachContext() throws Exception{
//獲取當前的ActivityThread對象
Class activityThreadClass = Class.forName(ACTIVIT_THREAD);
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod(CURRENT_ACTIVITY_THREAD);
currentActivityThreadMethod.setAccessible(true);
Object currentActivityThread = currentActivityThreadMethod.invoke(null);
//拿到在ActivityThread類裡面的原始mInstrumentation對象
Field mInstrumentationField = activityThreadClass.getDeclaredField(INSTRUMENTATION);
mInstrumentationField.setAccessible(true);
Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);
//構建我們的代理對象
Instrumentation evilInstrumentation = new InstrumentationProxy(mInstrumentation);
//通過反射,換掉字段,注意,這裡是反射的代碼,不是Instrumentation裡面的方法
mInstrumentationField.set(currentActivityThread, evilInstrumentation);
//做個標記,方便後面查看
Log.i(TAG, "has go in MyApplication attachContext method");
}
}
package com.example.hookstartactivity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
public static final String TAG = "MainActivity";
public TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.start);
tv.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
try {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
Bundle bundle = new Bundle();
Log.i(TAG, "-------------------------------->");
Log.i(TAG, "startActivity before");
Log.i(TAG, "-------------------------------->");
startActivity(intent, bundle);
Log.i(TAG, "-------------------------------->");
Log.i(TAG, "startActivity after");
Log.i(TAG, "-------------------------------->");
} catch (Exception e) {
e.printStackTrace();
}
}
} );
}
}
package com.example.hookstartactivity;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
public class SecondActivity extends ActionBarActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
}
然後我點擊圖標調用startActivity方法後ubuntu終端打印的日志圖片如下:
日志上面看到,hook success了
看到ubuntu終端日志打印,前面顯示了類,方便通過日志找bug,我用的是pidcat,下載pidcat
然後在ubuntu上面運行
pidcat.py 包名就可以非常方便看的日志找bug了。
Android 拖拽功能的使用實例
圖片的拖拉功能是處理圖片進一個有用且常用的功能,由於手機屏幕尺寸的限制,往往無法在手機上一次性的顯示一張比較大的圖片,也就是 說,我們在手機上一次性只能看到圖片的一部分,
AsyncTask的用法總結
這幾天被AsyncTask虐得不行,在此總結下 首先: AsyncTask的參數介紹 在開發Android移動客戶端的時候往往要使用多線程來進行操作,我們通常會
Android 動畫總結-補間動畫
AlphaAnimation:透明度(alpha)漸變效果,對應< alpha/>”標簽。 TranslateAnimation:位移漸變,需要
Android ColorFilter and Tint
概述關於Android ColorFilter 和 Tint之間的關系一直混淆不清。兩者均是對顯示的圖片進行著色或者過濾。 ColorFilter: 色彩過濾 Tint: