當前位置:首頁 » 安卓系統 » android反射類

android反射類

發布時間: 2024-10-17 10:37:55

⑴ Android系統怎麼利用利用java反射技術阻止通過按鈕關閉對話框(AlertDialog)

眾所周知,AlertDialog類用於顯示對話框。關於AlertDialog的基本用法在這里就不詳細介紹了,網上有很多,讀者可以自己搜索。那麼本文要介紹的是如何隨心所欲地控制AlertDialog。
現在我們來看看第一個需求:如果某個應用需要彈出一個對話框。當單擊「確定「按鈕時完成某些工作,如果這些工作失敗,對話框不能關閉。而當成功完成工作後,則關閉對話框。當然,無論何程度情況,單擊「取消」按鈕都會關閉對話框。
這個需求並不復雜,也並不過分(雖然我們可以自己弄個Activity來完成這個工作,也可在View上自己放按鈕,但這顯示有些大炮打蚊子了,如果對話框上只有一行文本,費這么多勁太不值了)。但使用過AlertDialog的讀者都知道,無論單擊的哪個按鈕,無論按鈕單擊事件的執行情況如何,對話框是肯定要關閉的。也就是說,用戶無法控制對話框的關閉動作。實際上,關閉對話框的動作已經在Android SDK寫死了,並且未給使用者留有任何介面。但我的座右銘是「宇宙中沒有什麼是不能控制的」。
既然要控制對放框的關閉行為,首先就得分析是哪些類、哪些代碼使這個對話框關閉的。進入AlertDialog類的源代碼。在AlertDialog中只定義了一個變數:mAlert。這個變數是AlertController類型。AlertController類是Android的內部類,在com.android.internal.app包中,無法通過普通的方式訪問。也無法在Eclipse中通過按Ctrl鍵跟蹤進源代碼。但可以直接在Android源代碼中找到AlertController.java。我們再回到AlertDialog類中。AlertDialog類實際上只是一個架子。象設置按鈕、設置標題等工作都是由AlertController類完成的。因此,AlertController類才是關鍵。
找到AlertController.java文件。打開後不要感到頭暈哦,這個文件中的代碼是很多地。不過這么多代碼對本文的主題也沒什麼用處。下面就找一下控制按鈕的代碼。
在AlertController類的開頭就會看到如下的代碼: View.OnClickListener mButtonHandler = new View.OnClickListener() {
public void onClick(View v) {
Message m = null ;
if (v == mButtonPositive && mButtonPositiveMessage != null ) {
m = Message.obtain(mButtonPositiveMessage);
} else if (v == mButtonNegative && mButtonNegativeMessage != null ) {
m = Message.obtain(mButtonNegativeMessage);
} else if (v == mButtonNeutral && mButtonNeutralMessage != null ) {
m = Message.obtain(mButtonNeutralMessage);
}
if (m != null ) {
m.sendToTarget();
} // Post a message so we dismiss after the above handlers are executed
mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialogInterface)
.sendToTarget();
}
};
從這段代碼中可以猜出來,前幾行代碼用來觸發對話框中的三個按鈕( Positive 、 Negative 和 Neutral )的單擊事件,而最後的代碼則用來關閉對話框(因為我們發現了 MSG_DISMISS_DIALOG 、猜出來的)。
mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialogInterface)
.sendToTarget(); 上面的代碼並不是直接來關閉對話框的,而是通過一個 Handler 來處理,代碼如下:
private static final class ButtonHandler extends Handler {
// Button clicks have Message.what as the BUTTON{1,2,3} constant
private static final int MSG_DISMISS_DIALOG = 1 ;

private WeakReference < DialogInterface > mDialog; public ButtonHandler(DialogInterface dialog) {
mDialog = new WeakReference < DialogInterface > (dialog);
} @Override
public void handleMessage(Message msg) {
switch (msg.what) {

case DialogInterface.BUTTON_POSITIVE:
case DialogInterface.BUTTON_NEGATIVE:
case DialogInterface.BUTTON_NEUTRAL:
((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);
break ;

case MSG_DISMISS_DIALOG:
((DialogInterface) msg.obj).dismiss();
}
}
}
從上面代碼的最後可以找到 ((DialogInterface) msg.obj).dismiss();。現在看了這么多源代碼,我們來總結一下對話框按鈕單擊事件的處理過程。在AlertController處理對話框按鈕時會為每一個按鈕添加一個onclick事件。而這個事件類的對象實例就是上面的mButtonHandler。在這個單擊事件中首先會通過發送消息的方式調用為按鈕設置的單擊事件(也就是通過setPositiveButton等方法的第二個參數設置的單擊事件),在觸發完按鈕的單擊事件後,會通過發送消息的方式調用dismiss方法來關閉對話框。而在AlertController類中定義了一個全局的mHandler變數。在AlertController類中通過ButtonHandler類來對象來為mHandler賦值。因此,我們只要使用我們自己Handler對象替換ButtonHandler就可以阻止調用dismiss方法來關閉對話框。下面先在自己的程序中建立一個新的ButtonHandler類(也可叫其他的名)。
class ButtonHandler extends Handler
{ private WeakReference < DialogInterface > mDialog; public ButtonHandler(DialogInterface dialog)
{
mDialog = new WeakReference < DialogInterface > (dialog);
} @Override
public void handleMessage(Message msg)
{
switch (msg.what)
{ case DialogInterface.BUTTON_POSITIVE:
case DialogInterface.BUTTON_NEGATIVE:
case DialogInterface.BUTTON_NEUTRAL:
((DialogInterface.OnClickListener) msg.obj).onClick(mDialog
.get(), msg.what);
break ;
}
}
} 我們可以看到,上面的類和AlertController中的ButtonHandler類很像,只是支掉了switch語句的最後一個case子句(用於調用dismiss方法)和相關的代碼。
下面我們就要為AlertController中的mHandler重新賦值。由於mHandler是private變數,因此,在這里需要使用Java的反射技術來為mHandler賦值。由於在AlertDialog類中的mAlert變數同樣也是private,因此,也需要使用同樣的反射技術來獲得mAlert變數。代碼如下:
先建立一個 AlertDialog 對象
AlertDialog alertDialog = new AlertDialog.Builder( this )
.setTitle( " abc " )
.setMessage( " content " )
.setIcon(R.drawable.icon)
.setPositiveButton( 「確定」,
new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog,
int which)
{ }
}).setNegativeButton( " 取消 " , new OnClickListener()
{ @Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
}
}).create()
上面的對話框很普通,單擊哪個按鈕都會關閉對話框。下面在調用 show 方法之前來修改一個 mHandler 變數的值, OK ,下面我們就來見證奇跡的時刻。 try
{

Field field = alertDialog1.getClass().getDeclaredField( " mAlert " );
field.setAccessible( true );
// 獲得mAlert變數的值
Object obj = field.get(alertDialog1);
field = obj.getClass().getDeclaredField( " mHandler " );
field.setAccessible( true );
// 修改mHandler變數的值,使用新的ButtonHandler類
field.set(obj, new ButtonHandler(alertDialog1));
}
catch (Exception e)
{
}
// 顯示對話框
alertDialog.show(); 我們發現,如果加上try catch語句,單擊對話框中的確定按鈕不會關閉對話框(除非在代碼中調用dismiss方法),單擊取消按鈕則會關閉對話框(因為調用了dismiss方法)。如果去了try…catch代碼段,對話框又會恢復正常了。
雖然上面的代碼已經解決了問題,但需要編寫的代碼仍然比較多,為此,我們也可採用另外一種方法來阻止關閉對話框。這種方法不需要定義任何的類。
這種方法需要用點技巧。由於系統通過調用dismiss來關閉對話框,那麼我們可以在dismiss方法上做點文章。在系統調用dismiss方法時會首先判斷對話框是否已經關閉,如果對話框已經關閉了,就會退出dismiss方法而不再繼續關閉對話框了。因此,我們可以欺騙一下系統,當調用dismiss方法時我們可以讓系統以為對話框已經關閉(雖然對話框還沒有關閉),這樣dismiss方法就失效了,這樣即使系統調用了dismiss方法也無法關閉對話框了。
下面讓我們回到AlertDialog的源代碼中,再繼續跟蹤到AlertDialog的父類Dialog的源代碼中。找到dismissDialog方法。實際上,dismiss方法是通過dismissDialog方法來關閉對話框的,dismissDialog方法的代碼如下: private void dismissDialog() {
if (mDecor == null ) {
if (Config.LOGV) Log.v(LOG_TAG,
" [Dialog] dismiss: already dismissed, ignore " );
return ;
}
if ( ! mShowing) {
if (Config.LOGV) Log.v(LOG_TAG,
" [Dialog] dismiss: not showing, ignore " );
return ;
} mWindowManager.removeView(mDecor); mDecor = null ;
mWindow.closeAllPanels();
onStop();
mShowing = false ;

sendDismissMessage();
}
該方法後面的代碼不用管它,先看 if(!mShowing){ … } 這段代碼。這個 mShowing 變數就是判斷對話框是否已關閉的。因此,我們在代碼中通過設置這個變數就可以使系統認為對話框已經關閉,就不再繼續關閉對話框了。由於 mShowing 也是 private 變數,因此,也需要反射技術來設置這個變數。我們可以在對話框按鈕的單擊事件中設置 mShowing ,代碼如下:
try
{
Field field = dialog.getClass()
.getSuperclass().getDeclaredField(
" mShowing " );
field.setAccessible( true );
// 將mShowing變數設為false,表示對話框已關閉
field.set(dialog, false );
dialog.dismiss();}
catch (Exception e)
{}
將上面的代碼加到哪個按鈕的單擊事件代碼中,哪個按鈕就再也無法關閉對話框了。如果要關閉對話框,只需再將 mShowing 設為 true 即可。要注意的是,在一個按鈕里設置了 mShowing 變數,也會影響另一個按鈕的關閉對話框功能,因此,需要在每一個按鈕的單擊事件里都設置 mShowing 變數的值。 本文來自CSDN博客,轉載請標明出處: http://blog.csdn.net/nokiaguy/archive/2010/07/27/5770263.aspx

⑵ Android 11 反射屏蔽機制繞過方法

Android 11 apk開發過程中。使粗脊大用 反射機制 調用方法失敗,總是報錯(blocked, reflection, denied),被拒絕,下面是解決方法

步驟一:In your root build.gradle:

步驟岩豎二野敗:In your library/build.gradle add:

⑶ android代碼混淆以及怎麼判斷一個apk代碼是否被混淆過

1、proguard原理
java代碼編譯成二進制class文件,這個class文件也可以反編譯成源代碼,除了注釋外,其他的code基本都可以看到。為了防止重要code被泄露,我們往往需要混淆,即把方法名,變數名,類名,包名等這些java元素的名稱改成讓人意想不到的名稱,這樣代碼結構就沒有變化,還可以運行,但是想弄懂代碼的架構卻很難。proguard就起到了這樣的作用:
一、它可以分析一組class的結構,根據用戶的配置,然後把這些class文件中可以混淆的java元素進行混淆

二、刪除無效的代碼

三、對代碼進行優化(使用adt插件導出的apk,還進行zipalign優化)

預設情況下,proguard會混淆所有代碼,但是下面幾種情況是不能改變java元素的名稱,否則就會導致程序出錯。
一、用到反射的地方(android中的api常用@hide注釋掉,開發者在調用相應的方法時,需要用到反射)

二、當app的代碼要依賴於系統的介面時,如被系統代碼調用的回調方法,這種方法比較復雜

三、java元素名稱是配置文件中配置好的

所以在使用proguard時,我們需要有個配置文件告訴proguard,哪些java元素是不能混淆的。

2、proguard配置

-dontwarn預設proguard會檢查每一個引用是否正確,但是第三方庫里往往有些不會用到的類,沒有正確引用,如果不配置的話,系統就會報錯。

-keep指定的類和類成員被保留作為入口

-keepclassmembes指定的類成員被保留。

-keepclasswithmembers指定的類和類成員被保留,假如指定的類成員存在的話。

⑷ android 什麼是反射

-什麼是反射機制?

反射機制是在運行狀態中,對於任意一個類(Class),都能夠知道這個類的所有屬性和方法(Method);對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。

-反射機制能做什麼?

主要功能:調用隱藏API,即標注了 @hide 的方法。

其他:

在運行時判斷任意一個對象所屬的類;

在運行時構造任意一個類的對象;

在運行時判斷任意一個類所具有的成員變數和方法;

在運行時調用任意一個對象的方法;

生成動態代理。

-注意事項?

Google之所以要將一些API隱藏(指加上@hide標記的public類、方法或常量)是有原因的。其中很大的原因就是Android系統本身還在不斷的進化發展中。從1.0、1.1到現在即將問世的Android2.3.4。這些隱藏的API本身可能是不穩定的,所以,使用隱藏API,意味著程序更差的兼容性。

如果要我給出建議的話,最好還是不要使用隱藏的API。不過有時為了實現Android應用某些特殊的功能或者效果,隱藏的API往往能發揮意想不到的作用。這些API具體能做些什麼事,我就不在這里舉例了。正好,如果你不知道隱藏API能做什麼的話,那麼還是盡早放棄使用它們吧……

引用內容自:

ke.xsoftlab.net/view/209.html

blog.sina.com.cn/s/blog_5da93c8f0101e1yj.html

⑸ android 可以反射到另一個應用裡面的類么

一個app不可以直接訪問另一個app的類。如果非要實現進程間通信,可以通過aidl做。可以考慮採用jar包的方式,將app B 打成jar文件 導入到 app A 中 就可以實現了。在應用中可以反射到類似framework裡面的 diaolog activity這些類,是因為import了這些類,所以在這些包以jar的形式編譯到應用。相反,是因為以jar的形式編譯到了應用,才有了import。如果沒有jar,就import不了。

⑹ android.telephony.telephonymanager怎麼反射調用

TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
/**
* 返回電話狀態
*
* CALL_STATE_IDLE 無任何狀態時
* CALL_STATE_OFFHOOK 接起電話時
* CALL_STATE_RINGING 電話進來時
*/
tm.getCallState();
//返回當前移動終端的位置
CellLocation location=tm.getCellLocation();
//請求位置更新,如果更新將產生廣播,接收對象為注冊LISTEN_CELL_LOCATION的對象,需要的permission名稱為ACCESS_COARSE_LOCATION。
location.requestLocationUpdate();

熱點內容
安卓生態軟體有什麼好處 發布:2024-10-17 12:24:09 瀏覽:670
安卓8有什麼區別 發布:2024-10-17 12:21:20 瀏覽:664
temp文件夾是什麼 發布:2024-10-17 12:15:35 瀏覽:613
存儲數據安全最好是什麼硬碟 發布:2024-10-17 12:05:53 瀏覽:532
android獲取當前語言 發布:2024-10-17 11:46:09 瀏覽:30
高通驍龍晶元什麼型號配置最高 發布:2024-10-17 11:40:56 瀏覽:235
手機與電腦代理伺服器 發布:2024-10-17 11:36:28 瀏覽:562
自動telnet腳本 發布:2024-10-17 11:34:46 瀏覽:502
中小型資料庫 發布:2024-10-17 11:33:36 瀏覽:164
騰訊雲伺服器跨賬號鏡像遷移 發布:2024-10-17 11:12:56 瀏覽:421