Robotium Robotium 娱乐小工具,临门一脚把我搞吐血了

渺小 · August 06, 2014 · Last by 呵呵呵呵好 replied at April 01, 2015 · 1343 hits

最近闲来无事写了一个 Robotium 的小工具,脑袋里 YY 着诸多功能的实现,没想到临门一脚把我搞吐血了,特来求一下实现思路,先阐述一下我目前实现的思路

一、项目背景:
一个 android 应用市场 APK
一个已经打包封装成 APK 的 robotium 脚本

二、各组件:
1.一个功能类似于 Monkey 的 robotium 脚本,动态获取当前设备屏幕宽,高,去掉信号栏高度,然后随机数生成一个坐标进行点击

2.由于有下载应用功能,下载应用后会自动弹出系统的应用安装界面,会导致脚本挂掉,所以添加了一个 Service,在程序启动时启动 Service 进行监听 Activity,判断当前 Activity 为系统安装界面或系统卸载界面,则唤醒被测程序 Activity

3.APK 首页是一个 ListView,想法是启动程序,首先展示当前手机上所有非系统的应用,然后点击某个被测程序条目,取得该条目对应应用的 mainActivity,传入到 robotium 脚本中,做到动态启动脚本(命令行启动)

三、目前遇到的问题:

以上各组件功能都已实现,唯独剩最后一步,将点击取到的对应 APK 条目的 mainActivity 字符串传给 Robotium Test 类出现问题,在脚本中打印 mainActivity 这个变量,脚本都会报空指针错误,好像 Robotium 启动后就把我这个变量销毁了一样,尝试过各种传值方法,以及使用 Service 进行传值,都没得到解决,特来求一解决思路

PS:已经解决了,证明 Robotium 封装成 APK,是和 APK 进程分进程的,尝试跨进程传值,使用 Handler 传值失败,最后用了最 SB 的方式,在 oncItemClick 的时候写 SD 卡文件,然后在 Robotium 脚本启动时读文件将 MainActivity 读出来

附代码(demo,未优化):

Robotium 脚本的:

package baih.Monkey;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;

import android.graphics.Rect;
import android.test.ActivityInstrumentationTestCase2;
import android.util.DisplayMetrics;
import android.util.Log;

import com.robotium.solo.Solo;

public class BaihMonkey extends ActivityInstrumentationTestCase2 {
    public static String LAUNCHER_ACTIVITY_FULL_CLASSNAME ;
    private static Class launcherActivityClass;

    static{
        File file=new File("/mnt/sdcard", "activityName.txt");

        try {           
            BufferedReader  fileReader = new BufferedReader (new FileReader(file));
            String activityName = fileReader.readLine();
            System.out.println(activityName);
            LAUNCHER_ACTIVITY_FULL_CLASSNAME=activityName;          
            fileReader.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

  public BaihMonkey() throws ClassNotFoundException {
          super(Class.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME));
         }

  private Solo solo;
  String logtag="LikeMonkey_log";

  @Override
  protected void setUp() throws Exception {
          solo = new Solo(getInstrumentation(), getActivity());

         }
public void testMonkey() throws InterruptedException{
          Thread.sleep(6000);
          DisplayMetrics ty=new DisplayMetrics();
          //getActivity().getWindowManager().getDefaultDisplay().getMetrics(ty);
          Rect frame=new Rect();
          solo.getCurrentActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
          int statusBarHeight=frame.top;
          solo.getCurrentActivity().getWindowManager().getDefaultDisplay().getMetrics(ty);
          int x2=ty.widthPixels;
          int y2=ty.heightPixels;
          Log.e("baih", "x="+x2);
          Log.e("baih", "y="+y2);
          while(true)
          {
              Thread.sleep(2000);
              Random setindex=new Random();
              int setId=setindex.nextInt(20);
              Log.e(logtag, "==="+setId);
              switch (setId) {
            case 2:
                Log.e(logtag, "操作左滑动");
                solo.scrollToSide(solo.LEFT, (float) 0.8);     //左滑动
                break;              
            case 5:
                Log.e(logtag, "操作右滑动");
                solo.scrollToSide(solo.RIGHT, (float) 0.8);   //右滑动
                break;              
            case 10:
                Log.e(logtag, "操作返回");
                solo.goBack();       //返回
                break;
            }
              Random x=new Random();
              int Rxindex=x.nextInt(x2);
              int xIndex=Rxindex+10;
              Random y=new Random();
              int Ryindex=y.nextInt(y2);
              int yIndex=Ryindex+statusBarHeight+5;
              if(yIndex>=y2 ||  xIndex>=x2)
              {
                  continue;
              }
              else
              {
                solo.clickOnScreen(xIndex, yIndex);
              }
          }
 }


@Override
  public void tearDown() throws Exception {
          solo.finishOpenedActivities();
         }
}

APK 首页,第三方应用列表的:

package baih.Monkey;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;

public class AppListActivity extends Activity {
    /** Called when the activity is first created. */
    ListView lv;
    AppInfo adapter;
    public static String LAUNCHER_ACTIVITY_FULL_CLASSNAME;
    ArrayList<HashMap<String, Object>> items=new ArrayList<HashMap<String, Object>>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.newfile);
        Intent serviceIntent =new Intent(this,StartService.class);
        startService(serviceIntent);
        lv = (ListView) findViewById(R.id.lv);
        final PackageManager  pm= getPackageManager();
        //得到PackageManager对象
        final List<PackageInfo> packs = pm.getInstalledPackages(0);
        //得到系统 安装的所有程序包的PackageInfo对象

        Intent mainIntent =new Intent(Intent.ACTION_MAIN,null);
        mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        List<ResolveInfo> res=pm.queryIntentActivities(mainIntent, PackageManager.GET_ACTIVITIES);
        for(ResolveInfo resolveInfo : res){

            HashMap<String, Object> map = new HashMap<String, Object>();
            map.put("icon", resolveInfo.loadIcon(pm));
            map.put("appName", resolveInfo.loadLabel(pm));
            map.put("packageName", resolveInfo.activityInfo.packageName);
            map.put("activityName", resolveInfo.activityInfo.name);

            try {
                ApplicationInfo itemApplicationInfo = pm.getApplicationInfo(resolveInfo.activityInfo.packageName, 0);
                if((itemApplicationInfo.flags&ApplicationInfo.FLAG_SYSTEM)==0)
                {
                items.add(map);
            }
            } catch (NameNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } 
        adapter =  new AppInfo(this, items, R.layout.applist_activity, new String[] {
                "icon", "appName", "packageName" }, new int[] { R.id.icon,
                R.id.appName, R.id.packageName });
        //参数:Context,ArrayList(item的集合),item的layout,包含ArrayList中Hashmap的key的数组,key所对应的值相对应的控件id
                lv.setAdapter(adapter);

                lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                // TODO Auto-generated method stub
                //TARGET_PACKAGE_ID =(String) items.get(position).get("packageName");
                LAUNCHER_ACTIVITY_FULL_CLASSNAME = (String) items.get(position).get("activityName");                
                File file=new File("/mnt/sdcard", "activityName.txt");              
                try {
                    if(!file.exists()){
                        boolean creatFile = file.createNewFile();
                        System.out.println("创建文件:" + creatFile);
                    }   
                    BufferedWriter mWriter  = new BufferedWriter(new FileWriter(file));
                    mWriter.write(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
                    mWriter.flush();
                    mWriter.close();

                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }               
                Log.e("baih", "==activityName===="+LAUNCHER_ACTIVITY_FULL_CLASSNAME);
                Runtime run=Runtime.getRuntime();
                try {
                    Log.e("baih", "开始执行");
                    run.exec("am instrument -w baih.Monkey/android.test.InstrumentationTestRunner");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 
            }       
        });

    }


}

Service 监听的:

package baih.Monkey;

import java.io.IOException;
import java.util.List;

import baih.Monkey.BaihMonkey;
import android.app.Activity;
import android.app.ActivityGroup;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Instrumentation;
import android.app.KeyguardManager;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

public class StartService extends Service {

    public static String activityName;
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    public void onCreate(){
        IntentFilter intent =new IntentFilter("android.intent.action.VIEW");
        //intent.addAction(Intent.ACTION_VIEW);
        intent.setPriority(Integer.MAX_VALUE);
        Toast.makeText(getApplicationContext(), "service已启动", 3000).show();
        Log.e("baih", "===================service已启动");
        final ActivityManager ActivityList=(ActivityManager)getApplicationContext().getSystemService(ACTIVITY_SERVICE);
        new Thread(){
            public void run(){
                while(true)
                {
                 List<RunningTaskInfo> acList=ActivityList.getRunningTasks(1);
                 RunningTaskInfo mTaskInfo;
                 mTaskInfo=acList.get(0);
                 String name=mTaskInfo.topActivity.getClassName();
                // String setup="com.android.packageinstaller.PackageInstallerActivity";
                 String setup="com.android.packageinstaller.PackageInstallerActivity";
                 String uninstall="com.android.packageinstaller.UninstallerActivity";
                 Log.e("baih", name);   
                 if(name.equals(setup) || name.equals(uninstall) )
                 {
                     List<RunningTaskInfo> ac1=ActivityList.getRunningTasks(2);
                     RunningTaskInfo ra1;
                     ra1=ac1.get(1);
                     String name1=ra1.topActivity.getClassName();

                     ComponentName componentName =  ra1.topActivity;
                     Intent intent = new Intent();
                     //intent.setComponent(componentName);
                     intent.setClassName("com.stnts.suileyoo.gamecenter", "com.android.haoyouduo.StartupActivity");
                     intent.setAction(Intent.ACTION_MAIN);
                     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                     startActivity(intent);
                     Log.e("baih", "===========操作返回");
                     Log.e("baih", "==========="+name1);                     
                 }
                    try {
                        Thread.sleep(4000);
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }   
                }
            }

        }.start();
    }

    public void onStart(){
        final ActivityManager ma=(ActivityManager)getApplicationContext().getSystemService(ACTIVITY_SERVICE);
        List<RunningTaskInfo> ac=ma.getRunningTasks(1);
        RunningTaskInfo ra;
        ra=ac.get(0);
        String name=ra.topActivity.getClassName();
        Log.e("baih", name);   
        if(name=="com.android.packageinstaller.PackageInstallerActivity")
        {
            Runtime run=Runtime.getRuntime();
            try {
                run.exec("input keyevent 4");

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
         }


}
共收到 6 条回复 时间 点赞

哟。。。

渺小 #3 · August 07, 2014 Author

@qddegtya @monkey 感谢给出的思路建议

楼主的想法不错,赞一个,同时学习下,哈哈

拜读一下

测试用例运行在目标进程空间,需要传值需要使用 aidl 跨进程通信

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up