下面给出3个简单的Activity,并在它们之间跳转,如果想点击某个Activity的返回键时就退出所有Activity,就只需监听该Activity的返回键即可。所有Activity都存放在一个集合里面,退出应用时,只需遍历该集合并逐一finish掉。代码如下:
MyAppalication:存放所有activity,提供添加activity和退出所有activity的方法
package com.home.exitapp; import java.util.ArrayList; import android.app.Activity; import android.app.Application; public class MyAppalication extends Application { // 存放activity的集合 private ArrayList<Activity> list = new ArrayList<Activity>(); private static MyAppalication instance; public MyAppalication() { } /** * 利用单例模式获取MyAppalication实例 * * @return */ public static MyAppalication getInstance() { if (null == instance) { instance = new MyAppalication(); } return instance; } /** * 添加activity到list集合 * * @param activity */ public void addActivity(Activity activity) { list.add(activity); } /** * 退出集合所有的activity */ public void exit() { try { for (Activity activity : list) { activity.finish(); } } catch (Exception e) { e.printStackTrace(); } finally { System.exit(0); } } @Override public void onLowMemory() { super.onLowMemory(); System.gc(); } }
BaseActivity:抽象出添加activity的方法
package com.home.exitapp; import android.app.Activity; import android.os.Bundle; public class BaseActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyAppalication.getInstance().addActivity(BaseActivity.this); } }
MyActivity1:
package com.home.exitapp; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MyActivity1 extends BaseActivity { private Button btn_1_2; private Button btn_1_3; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main1); // MyAppalication.getInstance().addActivity(MyActivity1.this); btn_1_2 = (Button) findViewById(R.id.main1_btn_1_2); btn_1_3 = (Button) findViewById(R.id.main1_btn_1_3); btn_1_2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MyActivity1.this, MyActivity2.class); startActivity(intent); } }); btn_1_3.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MyActivity1.this, MyActivity3.class); startActivity(intent); } }); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { // return true;//返回真表示返回键被屏蔽掉 creatDialog();// 创建弹出的Dialog } return super.onKeyDown(keyCode, event); } /** * 弹出提示退出对话框 */ private void creatDialog() { new AlertDialog.Builder(this) .setMessage("确定退出app?") .setPositiveButton("YES", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { MyAppalication.getInstance().exit(); } }) .setNegativeButton("NO", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).show(); } }
MyActivity2:
package com.home.exitapp; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MyActivity2 extends BaseActivity { private Button btn_2_1; private Button btn_2_3; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main2); btn_2_1 = (Button) findViewById(R.id.main2_btn_2_1); btn_2_3 = (Button) findViewById(R.id.main2_btn_2_3); btn_2_1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MyActivity2.this, MyActivity1.class); startActivity(intent); } }); btn_2_3.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MyActivity2.this, MyActivity3.class); startActivity(intent); } }); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { // return true;//返回真表示返回键被屏蔽掉 creatDialog();// 创建弹出的Dialog } return super.onKeyDown(keyCode, event); } /** * 弹出提示退出对话框 */ private void creatDialog() { new AlertDialog.Builder(this) .setMessage("确定退出app?") .setPositiveButton("YES", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { MyAppalication.getInstance().exit(); } }) .setNegativeButton("NO", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).show(); } }
MyActivity3:
package com.home.exitapp; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MyActivity3 extends BaseActivity { private Button btn_3_2; private Button btn_3_1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main3); btn_3_2 = (Button) findViewById(R.id.main3_btn_3_2); btn_3_1 = (Button) findViewById(R.id.main3_btn_3_1); btn_3_2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MyActivity3.this, MyActivity2.class); startActivity(intent); } }); btn_3_1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MyActivity3.this, MyActivity1.class); startActivity(intent); } }); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { // return true;//返回真表示返回键被屏蔽掉 creatDialog();// 创建弹出的Dialog } return super.onKeyDown(keyCode, event); } /** * 弹出提示退出对话框 */ private void creatDialog() { new AlertDialog.Builder(this) .setMessage("确定退出app?") .setPositiveButton("YES", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { MyAppalication.getInstance().exit(); } }) .setNegativeButton("NO", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).show(); } }
main1.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="I am the first activity" android:textSize="25sp" /> <Button android:id="@+id/main1_btn_1_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="跳到2" /> <Button android:id="@+id/main1_btn_1_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="跳到3" /> </LinearLayout>
main2.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#f000f0" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="I am the second activity" android:textSize="25sp" /> <Button android:id="@+id/main2_btn_2_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="跳到1" /> <Button android:id="@+id/main2_btn_2_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="跳到3" /> </LinearLayout>
main3.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#00f0ff" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="I am the third activity" android:textSize="25sp" /> <Button android:id="@+id/main3_btn_3_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="跳到2" /> <Button android:id="@+id/main3_btn_3_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="跳到1" /> </LinearLayout>
这只是一个简单的Demo,功能是调用豆瓣的接口发送图文广播。功能并不齐全,只是为网络编程练练手而已。
首先强调,这里没有用到第三方类库,也没有使用豆瓣的iOS SDK,都是直接用iOS给出的类和接口写的,只有代码是自己的,才真正有一种踏实的感觉。
当然第三方类库也非常好用,而且我也非常尊敬开发者开源共享的精神。
该广播接口的主要内容如下:
URL
shuo/v2/statuses/
HTTP请求方式
POST ’我说‘类型的广播中如果需要附带图片,注意采用multipart/form-data编码方式上传,上传图片大小限制为<3M,仅支持JPEG,GIF,PNG图片,name 是 image
请求参数
必选 类型及范围 说明 source true string appkey text true string 广播文本内容 image false bytes 我说的图 rec_title false string 推荐网址的标题 rec_url false string 推荐网址的href rec_desc false string 推荐网址的描述 rec_image false string 推荐网址的附图url调用示例
curl "https://api.douban.com/shuo/v2/statuses/" -H "Authorization: Bearer TOKEN" -F "text=TestText" -F "image=@upload.png"分析:
接口:https://api.douban.com/shuo/v2/statuses/
请求方式:POST
请求参数:source(必须,NSString),text(必须,NSString),image(可选,二进制数据)。
请求头:Authorization : Bearer ACCESS_TOKEN
首先是认证授权,不多说。
接着来到发广播界面:
对应SayViewController,下面看看该ViewController的接口部分:
#import <UIKit/UIKit.h> @interface SayViewController : UIViewController <UITextViewDelegate, NSURLConnectionDataDelegate, NSURLConnectionDelegate> @property (weak, nonatomic) IBOutlet UITextView *myWords_textView; // 广播内容编辑框 @property (weak, nonatomic) IBOutlet UIBarButtonItem *send_buttonItem; // 发送按钮 - (IBAction)sendMyWords:(id)sender; // 发送广播 @property (strong, nonatomic) NSMutableData *responseData; // 发送广播后返回的数据 @end
如果是单纯的发送文字内容则非常简单:
- (IBAction)sendMyWords:(id)sender { [myWords_textView resignFirstResponder]; if ([myWords_textView.text isEqualToString:@""]) { UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"发表广播失败" message:@"你输入的广播内容为空" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [av show]; } else { // -- 建立URL请求对象 -- NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:SEND_BROADCAST_URL] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:20.0]; // -- 设置HTTP请求方式为POST -- [request setHTTPMethod:@"POST"]; // -- 设置HTTP请求的BODY数据 -- NSString *paramSource = [NSString stringWithFormat:@"source=%@", API_KEY]; NSString *paramText = [NSString stringWithFormat:@"text=%@", myWords_textView.text]; NSString *parameters = [NSString stringWithFormat:@"%@&%@", paramSource, paramText]; NSMutableData *postData = [[NSMutableData alloc] init]; [postData appendData:[parameters dataUsingEncoding:NSUTF8StringEncoding]]; [request setHTTPBody:postData]; // -- 设置HTTP请求头部分 -- NSString *bearerToken = [NSString stringWithFormat:@"Bearer %@", [OAuthViewController getAccessToken]]; [request setValue:bearerToken forHTTPHeaderField:@"Authorization"]; // -- 建立URL连接 -- NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; if (connection) { [connection start]; } } }
首先以接口网址初始化请求。
然后设置参数,并编码成二进制数据:
NSString *parameters = [NSString stringWithFormat:@"%@&%@", paramSource, paramText]; [parameters dataUsingEncoding:NSUTF8StringEncoding]
再将其编码好的二进制数据设置为HTTP请求的BODY。
在设置好请求头后,建立URL连接,start即可。
利用NSURLConnection和NSURLConnectionData的委托可以获取返回的数据:
#pragma mark - #pragma mark NSURLConnection or NSURLConnectionData delegate - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { if (response) { responseData = [[NSMutableData alloc] initWithLength:0]; } } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { if (data) { [responseData appendData:data]; } } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSError *error = nil; NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error]; NSLog(@"dic = %@", dic); UIAlertView *av = nil; if (!dic || dic[@"code"]) { av = [[UIAlertView alloc] initWithTitle:@"发送失败" message:@"未知错误" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; } else { av = [[UIAlertView alloc] initWithTitle:@"发送成功" message:@"Congratulations" delegate:nil cancelButtonTitle:@"Good" otherButtonTitles:nil, nil]; } [av show]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"发生错误" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [av show]; }
其中使用responseData来接收返回的数据。
注意responseData是NSMutableData类型,首先如果收到服务器的响应就调用DidReceiveResponse就初始化该变量,但长度为0。
随着服务器不断返回数据,在DidReceiveData的不断调用中补全接收到的数据。
在接收数据完成后调用DidFinishLoading进行处理,如果接收数据失败就调用DidFailWithError作出错处理。
Run一下:
点击发送后,在我的豆瓣中的我的广播中可以看到结果:
真正麻烦的是要实现图文广播,注意这里强调的是不使用第三方类库或者豆瓣给出的SDK。
先看看文档的说明:
’我说‘类型的广播中如果需要附带图片,注意采用multipart/form-data编码方式上传,上传图片大小限制为<3M,仅支持JPEG,GIF,PNG图片,name 是 imagemultipart/form-data编码方式,也就是要把各个字段分开分别编码,然后将合起来的二进制数据设置为请求的BODY再POST到服务器。
好吧,我对HTTP协议,报文内容什么的的确了解不多,看来专业课的理论知识还是非常重要的。
在参考了网上一些文章后才大致明白其编码的工作方式,最后参考一下豆瓣SDK中的代码还是解决了该部分的内容。
先给出两篇挺有价值的参考文章:
IOS Post form(data and pic)I
【原】iOS通过http post上传图片(头像是个帅哥来的,感谢这位帅哥的分享)
在参考了豆瓣的SDK的源码后,我大致假设HTTP请求报文内容如下:
Content-type: multipart/form-data, charset=utf-8, boundary=KhTmLbOuNdArY, Authorization=Bearer access_token --KhTmLbOuNdArY Content-disposition: form-data; name="source" AppKey对应的内容 --KhTmLbOuNdArY Content-disposition: form-data; name="text" 要发送的广播内容 --KhTmLbOuNdArY content-disposition: form-data; name="image"; filename="WW.jpg" Content-Type: image/png ... contents of WW.jpg ... --KhTmLbOuNdArY--
其中WW.jpg就是我要POST的一张图片。
下面逐段贴上代码吧:
首先设置好请求头内容(Content-type: multipart/form-data, charset=utf-8, boundary=KhTmLbOuNdArY, Authorization=Bearer access_token)和请求方式为POST。
// -- 设置HTTP请求方式和请求头 -- // 请求头的内容: // Content-type: multipart/form-data, charset=utf-8, boundary=KhTmLbOuNdArY, Authorization=Bearer access_token NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)); CFUUIDRef uuid = CFUUIDCreate(nil); NSString *uuidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(nil, uuid)); CFRelease(uuid); NSString *stringBoundary = [NSString stringWithFormat:@"0xKhTmLbOuNdArY-%@",uuidString]; NSString *endItemBoundary = [NSString stringWithFormat:@"\r\n--%@\r\n",stringBoundary]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:SEND_BROADCAST_URL]]; [request setHTTPMethod:@"POST"]; [request setValue:[NSString stringWithFormat:@"multipart/form-data; charset=%@; boundary=%@", charset, stringBoundary] forHTTPHeaderField:@"Content-Type"]; NSString *bearerToken = [NSString stringWithFormat:@"Bearer %@", [OAuthViewController getAccessToken]]; [request setValue:bearerToken forHTTPHeaderField:@"Authorization"];
然后开始对BODY的内容进行逐段二进制编码:
// -- 对要POST的数据进行编码并设置HTTP请求的BODY -- // 开头的boundary: // --KhTmLbOuNdArY NSMutableData *postData = [[NSMutableData alloc] init]; [postData appendData:[[NSString stringWithFormat:@"--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; // source参数对应的key和内容: // Content-disposition: form-data; name="source" // // AppKey对应的内容 NSString *kSource = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"source\"\r\n\r\n"]; [postData appendData:[kSource dataUsingEncoding:NSUTF8StringEncoding]]; NSString *vSource = [NSString stringWithFormat:@"source=%@", API_KEY]; [postData appendData:[vSource dataUsingEncoding:NSUTF8StringEncoding]]; // 分割字段内容的boundary: // --KhTmLbOuNdArY [postData appendData:[endItemBoundary dataUsingEncoding:NSUTF8StringEncoding]]; // text参数对应的key和内容: // Content-disposition: form-data; name="text" // // 要发送的广播内容 NSString *kText = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"text\"\r\n\r\n"]; [postData appendData:[kText dataUsingEncoding:NSUTF8StringEncoding]]; NSString *vText = myWords_textView.text; [postData appendData:[vText dataUsingEncoding:NSUTF8StringEncoding]]; // 分割字段内容的boundary: // --KhTmLbOuNdArY [postData appendData:[endItemBoundary dataUsingEncoding:NSUTF8StringEncoding]]; // image参数对应的key和内容: // content-disposition: form-data; name="image"; filename="WW.jpg" // Content-Type: image/png // // ... contents of WW.jpg ... NSString *kImage = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"image\"; filename=\"WW.jpg\"\r\n"]; [postData appendData:[kImage dataUsingEncoding:NSUTF8StringEncoding]]; NSString *tImage = [NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", @"image/jpeg"]; [postData appendData:[tImage dataUsingEncoding:NSUTF8StringEncoding]]; UIImage *pickedImage = [UIImage imageNamed:@"WW.jpg"]; // NSData *imageData = UIImagePNGRepresentation(pickedImage); // png格式 NSData *imageData = UIImageJPEGRepresentation(pickedImage, 0.0); // jpg格式,1.0表示最大压缩,0.0表示图像无压缩 [postData appendData:imageData]; // 结尾的boundary // --KhTmLbOuNdArY-- [postData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; // -- 设置HTTP的BODY和请求头中的Content-Length -- NSString *length = [NSString stringWithFormat:@"%d", [postData length]]; [request setValue:length forHTTPHeaderField:@"Content-Length"]; [request setHTTPBody:postData];最后建立URL连接,并通过委托获取服务器回调的数据,代码和上面的发文字广播相同,不再重复。
还是Run一下:
点了发送后,我的广播内容也更新了:
老白出现了,就是WW.jpg对应的图片内容。(看到老白最后倒在实验室含笑而终,Baby Blue音乐一直在唱,既感到欣慰又是心痛啊,永别了,我的老白)
该博客对应的Demo已经上传,欢迎下载交流。由于豆瓣应用的机制:只有添加为该应用的测试用户才可以授权给该应用并登录,所以如果你想运行该应用,可以自己新建一个豆瓣应用,再替换Demo中的DBAPIURL.h中的API_KEY,SECRET_KEY和REDIRECT_URI。或者你留下你豆瓣的uid,让我添加你为该应用的测试用户就可以使用了。
好了,最后小结一下。
主要说说POST数据的方法(不使用第三方类库,尽管它们非常好用)。
如果单纯是POST一些NSString等类型的数据,直接设置参数,再编码为NSData就可以了,例如获取token时:
NSString *paramClinetID = [NSString stringWithFormat:@"client_id=%@", API_KEY]; NSString *paramClientSecret = [NSString stringWithFormat:@"client_secret=%@", SECRET_KEY]; NSString *paramRedirectURI = [NSString stringWithFormat:@"redirect_uri=%@", REDIRECT_URI]; NSString *paramGrantType = @"grant_type=authorization_code"; NSString *paramCode = [NSString stringWithFormat:@"code=%@", authorization_code]; NSString *parameters = [NSString stringWithFormat:@"%@&%@&%@&%@&%@", paramClinetID, paramClientSecret, paramRedirectURI, paramGrantType, paramCode]; NSMutableData *postData = [[NSMutableData alloc] init]; [postData appendData:[parameters dataUsingEncoding:NSUTF8StringEncoding]];
最近要做一个将文件POST到服务器的功能,很简单地用ASI实现了,但是始终觉得代码不是自己的心里就不踏实,所以就回来写下豆瓣练练手,最终还是实现了豆瓣POST图片的功能。
另外,我对HTTP协议的了解不多(课程还没讲,而自己又很懒还没去看),所以难免会有许多错漏,希望大家指出错误,让我改正。
---------------------------------------------- 我是分割线 ------------------------------------------------------
昨晚看完了最后一集的绝命毒师,思绪万千,今天就忍不住在博客里写了下来,看代码的人可以忽略。
老白始终让我有一种很亲切的感觉,他的结局我感觉还算欣慰吧,起码他成功地反击了杰克军团,就走了小粉,安排好了家人的一切,并且死在了他最爱的实验室里,最后很安详地倒在了地上,含笑而终。
看见他在摸着实验室的仪器,流露出不舍的表情的时候,相信各位老白的粉丝心里都酸酸的。
好吧,最后仅以一句简单的豆瓣广播向我亲爱的老白说声再见吧。
效果图:
代码实现:
1、MainActivity
package com.njupt.testpermission; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.widget.LinearLayout; public class MainActivity extends Activity { private LinearLayout ll_list_permission; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ll_list_permission = (LinearLayout) findViewById(R.id.ll_list_permission); } public void get(View v){ try { //android.widget.AppSecurityPermissions //AppSecurityPermissions asp = new AppSecurityPermissions(this, packageName); //asp.getPermissionsView() Class clazz = Class.forName("android.widget.AppSecurityPermissions"); Constructor[] constructors = clazz.getConstructors(); for(Constructor c:constructors){ Class[] parameterTypes = c.getParameterTypes(); for(Class cls:parameterTypes){ System.out.println(cls.getName()); } System.out.println("*******************************************************"); } Constructor c = constructors[1]; //第二个参数为你所想要查询的应用的名字 Object obj = c.newInstance(new Object[]{this,"com.njupt.safe"}); Method method = clazz.getMethod("getPermissionsView", null); View view = (View) method.invoke(obj, null); ll_list_permission.addView(view); } catch (Exception e) { e.printStackTrace(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
2、main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@android:color/background_dark" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="get" android:text="获取权限" /> <ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:id="@+id/ll_list_permission" android:layout_width="fill_parent" android:layout_height="fill_parent" > </LinearLayout> </ScrollView> </LinearLayout>
3、这个应用本身不需要任何权限,主要是用来查看其他应用的权限。。