/* * Copyright (c) 2012-2013 NetEase, Inc. and other contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.netease.qa.emmagee.activity; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import java.util.Properties; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageView; import android.widget.ListView; import android.widget.RadioButton; import android.widget.TextView; import android.widget.Toast; import com.netease.qa.emmagee.service.EmmageeService; import com.netease.qa.emmagee.utils.ProcessInfo; import com.netease.qa.emmagee.utils.Programe; import com.netease.qa.emmagee.R; /** * Main Page of Emmagee * * @author andrewleo */ public class MainPageActivity extends Activity { private static final String LOG_TAG = "Emmagee-" + MainPageActivity.class.getSimpleName(); private static final int TIMEOUT = 20000; private List<Programe> processList; private ProcessInfo processInfo; private Intent monitorService; private ListView lstViProgramme; private Button btnTest; private boolean isRadioChecked = false; private int pid, uid; private String processName, packageName, settingTempFile; private boolean isServiceStop = false; private UpdateReceiver receiver; @Override public void onCreate(Bundle savedInstanceState) { Log.i(LOG_TAG, "MainActivity::onCreate"); super.onCreate(savedInstanceState); setContentView(R.layout.mainpage); makeFile(); processInfo = new ProcessInfo(); lstViProgramme = (ListView) findViewById(R.id.processList); btnTest = (Button) findViewById(R.id.test); btnTest.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { monitorService = new Intent(); monitorService.setClass(MainPageActivity.this, EmmageeService.class); if ("开始测试".equals(btnTest.getText().toString())) { if (isRadioChecked) { Intent intent = getPackageManager() .getLaunchIntentForPackage(packageName); String startActivity = ""; Log.d(LOG_TAG, packageName); // clear logcat try { Runtime.getRuntime().exec("logcat -c"); } catch (IOException e) { Log.d(LOG_TAG, e.getMessage()); } try { startActivity = intent.resolveActivity( getPackageManager()).getShortClassName(); startActivity(intent); } catch (Exception e) { Toast.makeText(MainPageActivity.this, "该程序无法启动", Toast.LENGTH_LONG).show(); return; } waitForAppStart(packageName); monitorService.putExtra("processName", processName); monitorService.putExtra("pid", pid); monitorService.putExtra("uid", uid); monitorService.putExtra("packageName", packageName); monitorService.putExtra("settingTempFile", settingTempFile); monitorService.putExtra("startActivity", startActivity); startService(monitorService); btnTest.setText("停止测试"); } else { Toast.makeText(MainPageActivity.this, "请选择需要测试的应用程序", Toast.LENGTH_LONG).show(); } } else { btnTest.setText("开始测试"); Toast.makeText(MainPageActivity.this, "测试结果文件:" + EmmageeService.resultFilePath, Toast.LENGTH_LONG).show(); stopService(monitorService); } } }); lstViProgramme.setAdapter(new ListAdapter()); } /** * customized BroadcastReceiver * * @author andrewleo */ public class UpdateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { isServiceStop = intent.getExtras().getBoolean("isServiceStop"); if (isServiceStop) { btnTest.setText("开始测试"); } } } @Override protected void onStart() { Log.d(LOG_TAG, "onStart"); receiver = new UpdateReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("com.netease.action.emmageeService"); this.registerReceiver(receiver, filter); super.onStart(); } @Override public void onResume() { super.onResume(); Log.d(LOG_TAG, "onResume"); if (EmmageeService.isStop) { btnTest.setText("开始测试"); } } /** * create new file to reserve setting data. */ private void makeFile() { Log.i(LOG_TAG, "create new file to save setting data"); settingTempFile = getBaseContext().getFilesDir().getPath() + "\\EmmageeSettings.properties"; Log.i(LOG_TAG, "settingFile = " + settingTempFile); File settingFile = new File(settingTempFile); if (!settingFile.exists()) { try { settingFile.createNewFile(); Properties properties = new Properties(); properties.setProperty("interval", "5"); properties.setProperty("isfloat", "true"); properties.setProperty("sender", ""); properties.setProperty("password", ""); properties.setProperty("recipients", ""); properties.setProperty("smtp", ""); FileOutputStream fos = new FileOutputStream(settingTempFile); properties.store(fos, "Setting Data"); fos.close(); } catch (IOException e) { Log.d(LOG_TAG, "create new file exception :" + e.getMessage()); } } } /** * wait for test application started. * * @param packageName * package name of test application */ private void waitForAppStart(String packageName) { Log.d(LOG_TAG, "wait for app start"); boolean isProcessStarted = false; long startTime = System.currentTimeMillis(); while (System.currentTimeMillis() < startTime + TIMEOUT) { processList = processInfo.getRunningProcess(getBaseContext()); for (Programe programe : processList) { if ((programe.getPackageName() != null) && (programe.getPackageName().equals(packageName))) { pid = programe.getPid(); Log.d(LOG_TAG, "pid:" + pid); uid = programe.getUid(); if (pid != 0) { isProcessStarted = true; break; } } } if (isProcessStarted) { break; } } } /** * show a dialog when click return key. * * @return Return true to prevent this event from being propagated further, * or false to indicate that you have not handled this event and it * should continue to be propagated. */ public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { showDialog(0); } return super.onKeyDown(keyCode, event); } /** * set menu options,including cancel and setting options. * * @return true */ public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, Menu.FIRST, 0, "退出").setIcon( android.R.drawable.ic_menu_delete); menu.add(0, Menu.FIRST, 1, "设置").setIcon( android.R.drawable.ic_menu_directions); return true; } /** * trigger menu options. * * @return false */ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getOrder()) { case 0: showDialog(0); break; case 1: Intent intent = new Intent(); intent.setClass(MainPageActivity.this, SettingsActivity.class); intent.putExtra("settingTempFile", settingTempFile); startActivityForResult(intent, Activity.RESULT_FIRST_USER); break; default: break; } return false; } /** * create a dialog. * * @return a dialog */ protected Dialog onCreateDialog(int id) { switch (id) { case 0: return new AlertDialog.Builder(this) .setTitle("确定退出程序?") .setPositiveButton( "确定", new android.content.DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (monitorService != null) { Log.d(LOG_TAG, "stop service"); stopService(monitorService); } Log.d(LOG_TAG, "exit Emmagee"); EmmageeService.closeOpenedStream(); finish(); System.exit(0); } }).setNegativeButton("取消", null).create(); default: return null; } } /** * customizing adapter. * * @author andrewleo */ private class ListAdapter extends BaseAdapter { List<Programe> programe; int tempPosition = -1; /** * save status of all installed processes * * @author andrewleo */ class Viewholder { TextView txtAppName; ImageView imgViAppIcon; RadioButton rdoBtnApp; } public ListAdapter() { programe = processInfo.getRunningProcess(getBaseContext()); } @Override public int getCount() { return programe.size(); } @Override public Object getItem(int position) { return programe.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { Viewholder holder = new Viewholder(); final int i = position; convertView = MainPageActivity.this.getLayoutInflater().inflate( R.layout.list_item, null); holder.imgViAppIcon = (ImageView) convertView .findViewById(R.id.image); holder.txtAppName = (TextView) convertView.findViewById(R.id.text); holder.rdoBtnApp = (RadioButton) convertView.findViewById(R.id.rb); holder.rdoBtnApp.setId(position); holder.rdoBtnApp .setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { isRadioChecked = true; // Radio function if (tempPosition != -1) { RadioButton tempButton = (RadioButton) findViewById(tempPosition); if ((tempButton != null) && (tempPosition != i)) { tempButton.setChecked(false); } } tempPosition = buttonView.getId(); packageName = programe.get(tempPosition) .getPackageName(); processName = programe.get(tempPosition) .getProcessName(); } } }); if (tempPosition == position) { if (!holder.rdoBtnApp.isChecked()) holder.rdoBtnApp.setChecked(true); } Programe pr = (Programe) programe.get(position); holder.imgViAppIcon.setImageDrawable(pr.getIcon()); holder.txtAppName.setText(pr.getProcessName()); return convertView; } } @Override public void finish() { super.finish(); } protected void onStop() { unregisterReceiver(receiver); super.onStop(); } @Override protected void onDestroy() { super.onDestroy(); } }