您的位置:首页 > 移动开发 > Android开发

Android Monkey测试apk的开发

2016-08-04 09:13 525 查看
1.分享monkey测试apk的开发文档和内容。



package com.android.cw.monkeytest;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import android.R.string;

import android.annotation.SuppressLint;

import android.app.Activity;

import android.app.Service;

import android.content.Context;

import android.content.Intent;

import android.content.pm.PackageInfo;

import android.content.pm.PackageManager;

import android.os.Bundle;

import android.os.Environment;

import android.os.Handler;

import android.os.Message;

import android.text.TextUtils;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.Button;

import android.widget.CheckBox;

import android.widget.CompoundButton;

import android.widget.Toast;

import android.widget.CompoundButton.OnCheckedChangeListener;

import android.widget.EditText;

import android.widget.ListView;

import android.widget.TextView;

public class MainActivity extends Activity implements View.OnClickListener {

public static String TAG = "MonkeyRunningTest";
private PackageManager mPackageManager;
public int mIndex;
public Button mStartButton, resultButton, helpButton;
public CheckBox mSelectAllButton;
public EditText mEditText;
TextView resultTextView;
public HashMap<String, String> mCheckedModules;
private File file;
private CheckBox checkBox1, checkBox2, checkBox3, checkBox4;
private FileUtils fileUtils;
private String fileName1 = Environment.getExternalStorageDirectory()
+ "/monkey.txt";
private String whilelist = Environment.getExternalStorageDirectory()
+ "/whilelist.txt";
private static final String command1 = " logcat -v time ";
public Thread readsysLogThread;
Thread myThread;
public static boolean isreadsysLogThreadRun = false;

public static final String logfile2 = Environment
.getExternalStorageDirectory() + "/MonkeyTestResult.txt";

private boolean serviceisopen = false;// 服务是否开启
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
fileUtils = new FileUtils();

}

public void initData() {
mPackageManager = getPackageManager();
ListView listView = (ListView) findViewById(R.id.package_info_list);
mStartButton = (Button) findViewById(R.id.start_test);
resultButton = (Button) findViewById(R.id.btn_result);
helpButton = (Button) findViewById(R.id.btn_help);
resultTextView = (TextView) findViewById(R.id.tv_result);
mStartButton.setOnClickListener(this);
resultButton.setOnClickListener(this);
helpButton.setOnClickListener(this);
mSelectAllButton = (CheckBox) findViewById(R.id.select_all);
mEditText = (EditText) findViewById(R.id.time_edit);
checkBox1 = (CheckBox) findViewById(R.id.checkbox1);
checkBox2 = (CheckBox) findViewById(R.id.checkbox2);
checkBox3 = (CheckBox) findViewById(R.id.checkbox3);
checkBox4 = (CheckBox) findViewById(R.id.checkbox4);

PackageInfoAdapter adapter = new PackageInfoAdapter(this);
mCheckedModules = adapter.mCheckedMap;
listView.setAdapter(adapter);
ShellExecUtil util = new ShellExecUtil(this);

}

class PackageInfoAdapter extends BaseAdapter {
public Context mContext;
private List<PackageInfo> mPackageInfoList;
private List<CheckBox> mCheckBoxList;
public HashMap<String, String> mCheckedMap;
List<Integer> checkPosition;
PackageInfoAdapter(Context context) {
mContext = context;
mPackageInfoList = ShellExecUtil.getPakageNameList(context);
mCheckBoxList = new ArrayList<CheckBox>();
mCheckedMap = new HashMap<String, String>();
checkPosition = new ArrayList<Integer>();
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return ShellExecUtil.getPakageNameList(mContext).size();
}

@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return arg0;
}

@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}

@Override
public View getView(int index, View convertView, ViewGroup root) {
// TODO Auto-generated method stub
ViewHolder viewHolder = null;
mIndex = index;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.activity_list, root, false);
viewHolder.name = (TextView) convertView
.findViewById(R.id.name);
viewHolder.packageName = (TextView) convertView
.findViewById(R.id.package_info);
viewHolder.checkBox = (CheckBox) convertView
.findViewById(R.id.checkbox);
Log.d(TAG, "index :=" + index);
viewHolder.checkBox.setTag(index);
convertView.setTag(viewHolder);
Log.d(TAG,
"checkBox1 getTag is " + viewHolder.checkBox.getTag());
} else {

viewHolder = (ViewHolder) convertView.getTag();
viewHolder.checkBox.setTag(index);
Log.d(TAG,
"checkBox2 getTag is " + viewHolder.checkBox.getTag());
}
if (checkPosition != null) {
Log.d(TAG, "checkPosition index is " + new Integer(index));
viewHolder.checkBox
.setChecked((checkPosition.contains(viewHolder.checkBox
.getTag()) ? true : false));
} else {
viewHolder.checkBox.setChecked(false);
}

// mCheckBoxList.add(checkBox);
viewHolder.name
.setText(mPackageInfoList.get(mIndex).applicationInfo
.loadLabel(mPackageManager));
viewHolder.packageName
.setText(mPackageInfoList.get(mIndex).packageName);

final CheckBox finalholder = viewHolder.checkBox;
viewHolder.checkBox
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton button,
boolean isChecked) {
if (isChecked) {
if (!checkPosition.contains(finalholder
.getTag())) {
checkPosition.add((Integer) finalholder
.getTag());
}
mCheckedMap
.put(button.getTag().toString(),
mPackageInfoList.get(Integer
.parseInt(button
.getTag()
.toString())).packageName);
Log.d(TAG, "finalholder add Tag is "
+ (Integer) finalholder.getTag());
} else {
if (checkPosition.contains(finalholder.getTag())) {
checkPosition.remove(finalholder.getTag());
}
mCheckedMap.remove(button.getTag().toString());
Log.d(TAG, "finalholder remove Tag is "
+ (Integer) finalholder.getTag());
}

ShellExecUtil.setPackageNameMap(mCheckedMap);
}
});
return convertView;
}
}

class ViewHolder {
TextView name;
TextView packageName;
CheckBox checkBox;
}
private String getCheckBoxcommand() {
StringBuilder stringCheck = new StringBuilder();
if (checkBox1.isChecked()) {
stringCheck.append(" --ignore-crashes ");
}
if (checkBox2.isChecked()) {
stringCheck.append(" --ignore-timeouts ");
}
if (checkBox3.isChecked()) {
stringCheck.append(" --ignore-security-exceptions ");
}
if (checkBox4.isChecked()) {
stringCheck.append(" --ignore-native-crashes ");
}

return stringCheck.toString();

}

@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.start_test :
mStartButton.setEnabled(false);
startReadLogThread();

getCheckBoxcommand();
if ((mCheckedModules.size() == 0)
&& (!mSelectAllButton.isChecked())) {
Toast.makeText(this, "please choose test modoules",
Toast.LENGTH_LONG).show();
} else {
try {
Log.d(TAG,
"mEditText.getText() is  "
+ mEditText.getText());
if (TextUtils.isEmpty(mEditText.getText())) {
Toast.makeText(this,
"Default test time is 3000000!!!",
Toast.LENGTH_SHORT).show();
} else {
ShellExecUtil.setTestTimes(Long.parseLong(mEditText
.getText().toString()));
}

file = new File(whilelist);
if (file.exists()) {
file.delete();
file.createNewFile();
} else {
file.createNewFile();
}
OutputStream os = new FileOutputStream(file, true);
Iterator iter = mCheckedModules.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String mPackageName = (String) entry.getValue()
+ "\r\n";
os.write(mPackageName.getBytes());
}

mRunMonkeyTestCase.start();
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
break;
case R.id.btn_result :
resultButton.setEnabled(false);
if (readsysLogThread != null) {
readsysLogThread.interrupt();
}
UpdateUI();
break;

case R.id.btn_help :
Intent helpIntent = new Intent(MainActivity.this,
HelpActvity.class);
startActivity(helpIntent);
break;
}

}

public void UpdateUI() {
myThread = new Thread(new Runnable() {
@Override
public void run() {
try {
fileUtils.readFileByLines(logfile2, mHandler);

Thread.sleep(2000);
Message message = new Message();
message.what = 1;
mHandler.sendMessage(message);

} catch (Exception e) {
e.printStackTrace();
}

}
});
myThread.start();
}

public Handler mHandler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
String str = fileUtils.sBuilder.toString();
if (msg.what == 1) {
resultTextView.setText("--测试结果---" + "\n" + str);
}

};
};

/**
* 开启抓log线程
*/
private void startReadLogThread() {
readsysLogThread = new Thread(new Runnable() {
public void run() {
// 设置开关让他停止
try {
ShellExecUtil.execCommand(command1);

} catch (Exception e) {
e.printStackTrace();
}

}
});
readsysLogThread.start();
}

public Thread mRunMonkeyTestCase = new Thread(new Runnable() {

@Override
public void run() {
try {

ShellExecUtil.execCommand(ShellExecUtil.getCommond(file,
getCheckBoxcommand(), mSelectAllButton.isChecked()));
// ShellExecUtil.execCommand("monkey --throttle 1000 --ignore-crashes --ignore-timeouts --ignore-security-exceptions --ignore-native-crashes --monitor-native-crashes --kill-process-after-error -v -v -v 1000 > /storage/sdcard0/monkey.txt");

} catch (Exception e) {
e.printStackTrace();
}

}
});

protected void onDestroy() {
super.onDestroy();

if (mRunMonkeyTestCase != null) {
mRunMonkeyTestCase.interrupt();
}
if (readsysLogThread != null) {
readsysLogThread.interrupt();
}
if (myThread != null) {
myThread.interrupt();
}
};

}

第二个类:

package com.android.cw.monkeytest;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.HashMap;

import java.util.List;

import android.R.integer;

import android.annotation.SuppressLint;

import android.content.Context;

import android.content.pm.PackageInfo;

import android.content.pm.PackageManager;

import android.net.wifi.WifiInfo;

import android.net.wifi.WifiManager;

import android.nfc.Tag;

import android.os.Environment;

import android.telephony.TelephonyManager;

import android.util.Log;

public class ShellExecUtil {

public static HashMap<String, String> mPackageName;
public static long mTimes = 3000000;
public static Context mContext;
 public static final String logcatfile= Environment.getExternalStorageDirectory()+"/MonkeyTestResult.txt";
public static  StringBuilder sBuilder=null;
public ShellExecUtil(Context context) {
// TODO Auto-generated constructor stub
mContext = context;
}
public static void setPackageNameMap(HashMap<String, String> packageName) {
mPackageName = packageName;
}

public static void setTestTimes(long times) {
mTimes = times;
}

@SuppressLint("SdCardPath")
public static String getCommond(File whilelist, String stringcommand,
boolean isAllModules) {
StringBuilder commond = new StringBuilder();
if (isAllModules) {
commond.append("monkey");
} else {
commond.append("monkey --pkg-whitelist-file ").append(
whilelist.getPath());
}
commond.append(" --throttle 1000 ")
.append(stringcommand)
// .append("--ignore-crashes --ignore-timeouts --ignore-security-exceptions --ignore-native-crashes")
.append(" --monitor-native-crashes --kill-process-after-error -v -v -v ")
.append(Long.toString(mTimes));
//Log.i("", "----commond->" + commond.toString());
return commond.toString();
}

public static void execCommand(String command) {
sBuilder = new StringBuilder();
int count = 1;// 次数
Process proc = null;
try {
Runtime runtime = Runtime.getRuntime();
proc = runtime.exec(command);
BufferedReader in = new BufferedReader(new InputStreamReader(
proc.getInputStream()));
StringBuffer stringBuffer = new StringBuffer();
String line = null;
File file=new File(logcatfile);

FileWriter fr = new FileWriter(file);

while ((line = in.readLine()) != null) {

fr.write(line+"\r\n");
}

fr.close();

} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(proc!=null){
proc.destroy();
}

} catch (Exception e2) {
e2.printStackTrace();
}
}
}

public static List<PackageInfo> getPakageNameList(Context context) {
PackageManager packageManager = context.getPackageManager();

List<PackageInfo> list = packageManager
.getInstalledPackages(PackageManager.GET_PERMISSIONS);
return list;
}

public static String getIMEI() {
String im = "";
TelephonyManager mTelephonyManager = (TelephonyManager) mContext
.getSystemService(Context.TELEPHONY_SERVICE);
im = mTelephonyManager.getDeviceId();
if (im == null || im.trim().length() == 0) {
im = getMacAddress();
}
return im;
}

/**
* 获取mac地址
* @return
*/
public static String getMacAddress() {
WifiManager wifi = (WifiManager) mContext
.getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
String mac = "";
try {
if (info != null) {
mac = info.getMacAddress();
mac = mac.replaceAll(":", "-");
}
} catch (Exception e) {
// TODO: handle exception
}

return mac;
}

}

第三个类:文件操作类

package com.android.cw.monkeytest;

import android.R.integer;

import android.content.Context;

import android.os.Environment;

import android.os.Handler;

import android.os.Message;

import android.util.Log;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.IOException;

import java.io.OutputStreamWriter;

public class FileUtils {
public static StringBuilder sBuilder;

public FileUtils() {
super();

}
public static void writeLogFile(Context mcontext, String fileName,
String content, Boolean flag) {
File file = new File(mcontext.getExternalFilesDir("log"), fileName);// getExternalCacheDir()
if (file.exists() && flag) {
file.delete();
}
FileOutputStream fos;
try {
fos = new FileOutputStream(file, true);
fos.write((content).getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void writeLogFile(Context mcontext, String fileName,
String content) {
writeLogFile(mcontext, fileName, content, false);
}

public static String getSDPath() {
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED); // 判断sd卡是否存在
if (sdCardExist) {
sdDir = Environment.getExternalStorageDirectory();// 获取跟目录
}
return sdDir.toString();
}
public static void method4(Context context, String file, String content) {
// 每次写入文件前先删除原有的文件
File file1 = new File(file);
if (file1.exists()) {
file1.delete();
}
FileOutputStream fos;
try {
fos = new FileOutputStream(file, true);
fos.write((content).getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 以行为单位读取文件,常用于读面向行的格式化文件
*/
public void readFileByLines(String fileName, Handler mHandler) {

sBuilder=new StringBuilder();
File file = new File(fileName);
if (!file.exists()) {
Log.i("", "---文件未找到---");
return;
}
BufferedReader reader = null;
try {
System.out.println("---以行为单位读取文件内容,一次读一整行:");
reader = new BufferedReader(new FileReader(file));
String tempString = null;
int line = 1;
int count=0;
int count1 = 0;// 次数
int count2 = 0;// 次数
int count3 = 0;// 次数
int count4 = 0;// 次数
int count5 = 0;// 次数
int count6 = 0;// 次数
int count7 = 0;// 次数
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null) {
// 显示行号
//System.out.println("--line " + line + ": " + tempString);
// line++;

if (tempString.contains("Crash")|| (tempString.contains("crash"))) {
count1++;
sBuilder.append("crash出现的次数:" + count1 + "\n" + tempString
+ "\n");

}
if (tempString.contains("anr") || tempString.contains("ANR")||tempString.contains("Anr")) {
count2++;
sBuilder.append("anr出现的次数:" + count2 + "\n" + tempString
+ "\n");
}
if (tempString.contains("Tombstone")) {
count3++;
sBuilder.append("tombstone出现的次数:" + count3 + "\n"
+ tempString + "\n");
}
if (tempString.contains("Fatal")) {
count4++;
sBuilder.append("Fatal出现的次数:" + count4 + "\n" + tempString
+ "\n");
}

if (tempString.contains("Watchdog")||tempString.contains("watchdog")) {
count5++;
sBuilder.append("Watchdog出现的次数:" + count5 + "\n"
+ tempString + "\n");
}
if (tempString.contains("vmreboot")
|| tempString.contains("VmReboot")) {
count6++;
sBuilder.append("vmreboot出现的次数:" + count6 + "\n"
+ tempString + "\n");
}
if (tempString.contains("powercollapse")
|| tempString.contains("PowerCollapse")) {
count7++;
sBuilder.append("powercollapse出现的次数:" + count7 + "\n"
+ tempString + "\n");
}
// Log.i("", "-----读完------>" + sBuilder.toString());
//return sBuilder.toString();
}
//UpdateUI(mHandler);
// Log.i("", "-----结果分析------>" + sBuilder.toString());
reader.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
public void UpdateUI(final Handler mHandler) {
Thread myThread = new Thread(new Runnable() {

@Override
public void run() {
try {

Message message = new Message();
message.what = 1;
mHandler.sendMessage(message);

} catch (Exception e) {
e.printStackTrace();
}

}
});
myThread.start();
}

}



main布局文件:

<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"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

   >

    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal" >

        <Button

            android:id="@+id/start_test"

            android:layout_width="0dip"

            android:layout_height="50dp"

            android:layout_alignParentBottom="true"

            android:layout_weight="1"

            android:text="@string/start_test"

            android:textColor="#f00" />

        <Button

            android:id="@+id/btn_result"

            android:layout_width="0dp"

            android:layout_height="50dp"

            android:layout_alignParentBottom="true"

            android:layout_weight="1"

            android:text="结果"

            android:textColor="#f00" />

        <Button

            android:id="@+id/btn_help"

            android:layout_width="0dp"

            android:layout_height="50dp"

            android:layout_alignParentBottom="true"

            android:layout_weight="1"

            android:text="帮助"

            android:textColor="#f00" />

    </LinearLayout>

    <ScrollView

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:scrollbars="vertical" >

        <TextView

            android:id="@+id/tv_result"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="@string/tv_result" />

    </ScrollView>

    <CheckBox

        android:id="@+id/checkbox1"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:checked="false"

        android:text="@string/checkbox1" />

    <CheckBox

        android:id="@+id/checkbox2"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/checkbox2" />

    <CheckBox

        android:id="@+id/checkbox3"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/checkbox3" />

    <CheckBox

        android:id="@+id/checkbox4"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="@string/checkbox4" />

    <LinearLayout

        android:id="@+id/printitle"

        android:layout_width="match_parent"

        android:layout_height="20dp"

        android:layout_alignParentTop="true" >

        <TextView

            android:id="@+id/modoule_name"

            android:layout_width="80dp"

            android:layout_height="wrap_content"

            android:layout_centerVertical="true"

            android:ellipsize="marquee"

            android:layout_weight="1"

            android:focusableInTouchMode="true"

            android:marqueeRepeatLimit="marquee_forever"

            android:singleLine="true"

            android:text="@string/modoule_name" />

        <View

            android:id="@+id/sepline"

            android:layout_width="20dp"

            android:layout_height="match_parent"

            android:layout_toRightOf="@id/modoule_name" />

        <TextView

            android:id="@+id/package_name"

            android:layout_width="100dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:layout_centerVertical="true"

            android:layout_toRightOf="@id/sepline"

            android:ellipsize="marquee"

            android:focusableInTouchMode="true"

            android:marqueeRepeatLimit="marquee_forever"

            android:singleLine="true"

            android:text="@string/package_name" />

        <TextView

            android:id="@+id/select_state"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_gravity="right"

            android:layout_weight="1"

            android:layout_marginRight="2dp"

            android:text="@string/select_state" />

    </LinearLayout>

    <LinearLayout

        android:id="@+id/times_containner"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_marginBottom="1dip" >

        <TextView

            android:id="@+id/title"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_centerVertical="true"

            android:layout_weight="1"

            android:text="@string/test_times" />

        <EditText

            android:id="@+id/time_edit"

            android:layout_width="100dp"

            android:layout_height="wrap_content"

            android:layout_weight="3"

            android:text="@null" />

        <CheckBox

            android:id="@+id/select_all"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_gravity="right"

            android:layout_alignParentRight="true"

            android:layout_marginRight="0dp"

            android:text="@string/select_all"

          />

    </LinearLayout>

    <!-- android:background="@drawable/button" -->

    <ListView

        android:id="@+id/package_info_list"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_above="@id/times_containner"

        android:layout_below="@id/printitle" >

    </ListView>

</LinearLayout>

list.xml文件:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent" >

    <TextView

        android:id="@+id/name"

        android:layout_width="80dp"

        android:layout_height="wrap_content"

        android:layout_centerVertical="true" 

        android:ellipsize="marquee"    

        android:marqueeRepeatLimit="marquee_forever" 

        android:focusableInTouchMode="true"

       />

    <View

        android:id="@+id/sep_line"

        android:layout_width="20dp"

        android:layout_height="match_parent"

        android:layout_toRightOf="@id/name" />

    <TextView

        android:id="@+id/package_info"

        android:layout_width="250dp"

        android:layout_height="wrap_content"

        android:singleLine="true" 

        android:ellipsize="marquee"    

        android:focusableInTouchMode="true"

        android:marqueeRepeatLimit="marquee_forever" 

        android:layout_centerVertical="true"

        android:layout_toRightOf="@id/sep_line" />

    <CheckBox

        android:id="@+id/checkbox"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_alignParentRight="true"

        android:layout_centerVertical="true"

        android:layout_marginRight="0dp" />

</RelativeLayout>

需要添加权限:

android:sharedUserId="android.uid.system"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息