GVKun编程网logo

如何为Android自动化生成报告(android 自动化)

24

在这里,我们将给大家分享关于如何为Android自动化生成报告的知识,让您更了解android自动化的本质,同时也会涉及到如何更有效地Android国际化资源文件自动化生成工具、Android屏幕适配

在这里,我们将给大家分享关于如何为Android自动化生成报告的知识,让您更了解android 自动化的本质,同时也会涉及到如何更有效地Android国际化资源文件自动化生成工具、Android屏幕适配工具类 Android自动生成不同分辨率的值、Android自动化与持续集成实践、Android自动化性能收集的内容。

本文目录一览:

如何为Android自动化生成报告(android 自动化)

如何为Android自动化生成报告(android 自动化)

我有一个Robotium测试用例我希望每晚使用自动化工具运行,但是我不确定是否可以在没有首先通过 Eclipse手动运行它的情况下完成.是否有一个构建脚本可以让我每晚自动运行Robotium测试用例.理想情况下,此测试用例将直接在设备上运行,因为我们希望测试不同 Android OS平台之间的兼容性.

如何自动运行测试用例?是否有适用于Android的构建脚本可以让我做我需要做的事情?“

解决方法

不,您必须使用java io生成报告并将其存储在android中,并且在生成报告之后,您只需将文件拉出来.

Android国际化资源文件自动化生成工具

Android国际化资源文件自动化生成工具

一、工具起源

       

       如果在做一个产品的过程当中,可能会涉及到多个apk的开发,而且要求实现多国语言。而这些apk可能会由多人分工共同完成。但如果这样的话,每个人都需要整理各自apk所要显示的文字交给专人来翻译。专人负责收集和翻译文字,翻译完了之后再交给每个开发者。比如这个产品中的所有apk都需要支持10国语言,也就是说每个开发人员,要拿着翻译好的文字,在各自负责的项目中创建这10个语种的资源文件,并且将这10个语种的文字依次放入到不同语种目录下的资源文件中。而且当apk写完后,后续有修改,并在界面上添加了新的文字显示,又需要翻译,并要修改各国语言的资源文件。可想而知这是一件多么烦锁的事情。。。(负责翻译的人要收集所有文字,整理并翻译,开发人拿到翻译后的文字之后,要修改各个语言下的资源文件抓狂)!所以为了管理方便,由一个人负责收集所有apk中需要翻译的所有文字,并统一交给负责翻译的人。最后拿到翻译后的文字,用一个工具来统一管理并生成所有apk所需要的各国语言的资源文件,这样是不是很爽呢??那是肯定的。不但能减少团队成员之间的工作量,还能提高工作效率。下面将介绍一下这个工具的使用,希望日后你也遇到类似的项目,对你有所有帮助。


二、国际化实现方式


实现Android国际化,分为两步:

1、在工程的res目录下创建不同国家和语种的资源目录(values或drawable),系统会根据设备当前的语言环境自动选择相应的资源文件。

2、翻译各国语言的文字,放入不同国家和语句的资源目录,即strings.xml或arrays.xml。


三、工具实现原理介绍


1、准备一个存放各个apk各国语言文字的excel模板文件。模板数据格式说明:

1> 每个sheet代表一个apk

2> sheet中的第一列存放strings.xml或arrays.xml文件中的id

          3> 第二列存放默认文字(当设备找不到当前语言的文字时,使用默认的)

          4> 第三列存放各个国家的语言缩写(列名使用语言缩写,比如中文:cn)



5>   sheet命名注意:

a、生成strings.xml文件:直接用模块名即可,如:MusicPlayer

b、生成arrays.xml文件:用模块名+_arrays,如:MusicPlayer_arrays

2、使用Apache的开源框架POI解析excel读取各个apk的语言文字,并通过dom4j生成strings.xml和arrays.xml


四、工具类源代码


1、生成资源文件工具类

package com.i18n.i18nbuilder;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

import com.mltsagem.i18nbuilder.model.ArrayEntity;
import com.mltsagem.i18nbuilder.model.StringEntity;

/**
 * 读取EXCEL语言模板文件,生成各个国家语言的资源文件
 * @author yangxin
 */
public class ResourcesBuilder {
	
	public static final String DEFAULT_LANGUAGE_FLAG = "values";
	
	/**
	 * 各个国家的语言
	 */
	public static final String[] LANGUAGE = {
		DEFAULT_LANGUAGE_FLAG,
		"en-rGB","de-rDE","fr-rFR","es-rES","it-rIT","pt-rPT","nl-rNL","sv-rSE","no-rNO",
		"fi-rFI","da-rDK","hu-rHU","pl-rPL","cs-rCZ","tr-rTR","ru-rRU","el-rGR","ro-rRO"
	}; 
	
	// 读取需要生成strings.xml的sheet
	public static final String[] STRINGS_SHEETS = {
		"MusicPlayer",
		"VideoPlayer"
	};
	
	// 读取需要生成arrays.xml的sheet
	public static final String[] ARRAYS_SHEETS = {
		"MusicPlayer",	// 读取MusicPlayer_arrays sheet中的数据
		//"VideoPlayer"
	};
	
	/**
	 * 资源文件生成的临时目录
	 */
	public static final String I18N_TEMP_DIR = "/tmp/i18n/";
	
	/**
	 * 语言文件夹前缀
	 */
	public static final String RESOURCES_DIR_PREFIX = "values-";
	
	/**
	 * 资源文件名
	 */
	public static final String STRING_RESOURCES_FILE_NAME = "strings.xml";
	public static final String ARRAY_RESOURCES_FILE_NAME = "arrays.xml";

	public static void main(String[] args) {
		try {
			String file = "/Users/yangxin/Desktop/language.xls";
			// 清除以前生成的文件和目录
			clearDir(new File(I18N_TEMP_DIR));
			// 创建语言文件夹
			createI18nDir();
			// 生成各个模块中各个国家的strings.xml语言资源文件
			builderStringResources(new FileInputStream(file));
			// 生成各个模块中各个国家的arrays.xml语言资源文件
			builderArrayResources(new FileInputStream(file));
			System.out.println("全部生成成功:" + I18N_TEMP_DIR);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 创建语言文件夹
	 */
	public static void createI18nDir() {
		for (int i = 0; i < STRINGS_SHEETS.length; i++) {
			// 创建模块所对应的目录
			File parent = new File(I18N_TEMP_DIR,STRINGS_SHEETS[i]);
			parent.mkdirs();
			// 创建各个国家语言的资源目录
			for (int j = 0; j < LANGUAGE.length; j++) {
				String language = null;
				if (j == 0) {
					language = LANGUAGE[j];
				} else {
					language = RESOURCES_DIR_PREFIX + LANGUAGE[j];
				}
				File file = new File(parent,language);
				if (!file.exists()) {
					file.mkdirs();
				}
			}
		}
	}
	
	/**
	 * 生成strings.xml资源文件
	 */
	public static void builderStringResources(InputStream is) throws Exception {
		HSSFWorkbook book = new HSSFWorkbook(is);
		for (int i = 0; i < STRINGS_SHEETS.length; i++) {
			HSSFSheet sheet = book.getSheetAt(book.getSheetIndex(STRINGS_SHEETS[i]));
			System.out.println("build strings for " + sheet.getSheetName());
			int rowNum = sheet.getLastRowNum();
			for (int j = 0; j < LANGUAGE.length; j++) {
				String language = LANGUAGE[j];
				ArrayList<StringEntity> stringEntitys = new ArrayList<StringEntity>();
				File dir = null;
				if (DEFAULT_LANGUAGE_FLAG.equals(language)) {	// 创建默认语言
					dir = new File(I18N_TEMP_DIR + STRINGS_SHEETS[i] + File.separator + language);
				} else {
					dir = new File(I18N_TEMP_DIR + STRINGS_SHEETS[i] + File.separator + RESOURCES_DIR_PREFIX + language);
				}
				File file = new File(dir,STRING_RESOURCES_FILE_NAME);
				for (int k = 1; k <= rowNum; k++) {
					HSSFRow row = sheet.getRow(k);
					if (row.getLastCellNum() < 1)
						continue;
					String resId = row.getCell(0).getStringCellValue().trim();			// resId
					HSSFCell cell = row.getCell(j+1);
					String value = null;
					if (cell != null) {
						value = cell.getStringCellValue(); 			// 某一个国家的语言
						if (value == null || "".equals(value.trim())) {
							continue;
						}
						StringEntity entity = new StringEntity(resId, value.trim());
						stringEntitys.add(entity);
					}
				}
				// 创建资源文件
				builderStringResources(stringEntitys,file);
			}
		}
		is.close();
		System.out.println("------------------strings.xml资源文件生成成功!------------------");
	}
	
	private static void builderStringResources(List<StringEntity> stringEntitys,File file) throws Exception {
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("utf-8");
		XMLWriter writer = new XMLWriter(new FileOutputStream(file),format);
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("resources");
		for (StringEntity stringEntity : stringEntitys) {
			Element stringElement = root.addElement("string");
			stringElement.addAttribute("name", stringEntity.getResId());
			stringElement.setText(stringEntity.getValue());
		}
		writer.write(document);
		writer.close();
	}
	
	/**
	 * 生成arrays.xml资源文件
	 */
	public static void builderArrayResources(InputStream is) throws Exception {
		HSSFWorkbook book = new HSSFWorkbook(is);
		for (int i = 0; i < ARRAYS_SHEETS.length; i++) {	// 功能模块
			HSSFSheet sheet = book.getSheetAt(book.getSheetIndex(ARRAYS_SHEETS[i]+"_arrays"));
			System.out.println("build arrays for " + sheet.getSheetName());
			int rowNum = sheet.getNumMergedRegions();	// sheet.getLastRowNum();
			for (int j = 0; j < LANGUAGE.length; j++) {		// 语言
				String language = LANGUAGE[j];
				ArrayList<ArrayEntity> arrayEntities = new ArrayList<ArrayEntity>();
				File dir = null;
				if (DEFAULT_LANGUAGE_FLAG.equals(language)) {	// 创建默认语言
					dir = new File(I18N_TEMP_DIR + ARRAYS_SHEETS[i] + File.separator + language);
				} else {
					dir = new File(I18N_TEMP_DIR + ARRAYS_SHEETS[i] + File.separator + RESOURCES_DIR_PREFIX + language);
				}
				File file = new File(dir,ARRAY_RESOURCES_FILE_NAME);
				for (int k = 1; k <= rowNum; k++) {
					CellRangeAddress range = sheet.getMergedRegion(k-1);
					int mergedRows = range.getNumberOfCells();
					int lastRow = range.getLastRow();
					int rowIndex = (lastRow - mergedRows) + 1;
					String resId = sheet.getRow(rowIndex).getCell(0).getStringCellValue().trim();			// resId
					ArrayEntity entity = new ArrayEntity(resId);
					ArrayList<String> items = new ArrayList<String>();
					for (int z = rowIndex; z <= lastRow; z++) {
						HSSFCell cell = sheet.getRow(z).getCell(j+1);
						String value = getValue(cell);
						
						if (value == null || "".equals(value.trim())) {	// 如果该语言没有对应的翻译,默认使用英语
							HSSFCell defaultCell = sheet.getRow(z).getCell(1);
							value = getValue(defaultCell);
						}
						
						if ("temp".equalsIgnoreCase(value.trim())) {
							continue;
						}
						
						items.add(value);
					}
					entity.setItems(items);
					arrayEntities.add(entity);
				}
				// 创建资源文件
				builderArrayResources(arrayEntities,file);
			}
		}
		System.out.println("------------------arrays.xml资源文件生成成功!------------------");
	}
	
	/**
	 * 获取单元格的值
	 * @param cell 单元格
	 * @return 单元格对应的值
	 */
	private static String getValue(HSSFCell cell) {
		String value = "";
		if (cell != null) {
			switch (cell.getCellType()) {
			case Cell.CELL_TYPE_NUMERIC:
				value = String.valueOf((int)cell.getNumericCellValue()).trim();
				break;
			case Cell.CELL_TYPE_STRING:
				value = cell.getStringCellValue().trim(); 
				break;
			case Cell.CELL_TYPE_BOOLEAN:
				value = String.valueOf(cell.getBooleanCellValue()).trim();
				break;
			default:
				value = cell.getStringCellValue().trim(); 
				break;
			}
		}
		return value;
	}
	
	private static void builderArrayResources(ArrayList<ArrayEntity> arrayEntities, File file) throws Exception {
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("utf-8");
		XMLWriter writer = new XMLWriter(new FileOutputStream(file),format);
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("resources");
		for (ArrayEntity arrayEntity : arrayEntities) {
			Element arrayElement = root.addElement("string-array");
			arrayElement.addAttribute("name", arrayEntity.getName());
			List<String> items = arrayEntity.getItems();
			for (String item : items) {
				Element itemElement = arrayElement.addElement("item");
				itemElement.setText(item);
			}
		}
		writer.write(document);
		writer.close();
	}

	/**
	 * 清除以前生成的文件和目录
	 */
	public static void clearDir(File dir) {
		if (!dir.exists()) return;
		File[] files = dir.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				clearDir(file);
			} else {
				file.delete();
			}
		}
		dir.delete();
	}
}

package com.i18n.i18nbuilder.model;

import java.util.List;

public class ArrayEntity {

	private String name;
	private List<String> items;
	
	public ArrayEntity() {
		super();
	}
	public ArrayEntity(String name) {
		super();
		this.name = name;
	}
	public ArrayEntity(String name, List<String> items) {
		super();
		this.name = name;
		this.items = items;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<String> getItems() {
		return items;
	}
	public void setItems(List<String> items) {
		this.items = items;
	}
	
}
package com.i18n.i18nbuilder.model;

public class StringEntity {
	
	private String resId;
	private String value;
	public StringEntity() {
		super();
	}
	public StringEntity(String resId, String value) {
		super();
		this.resId = resId;
		this.value = value;
	}
	public String getResId() {
		return resId;
	}
	public void setResId(String resId) {
		this.resId = resId;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
}

2、解析资源文件(strings.xml/arrays.xml)中ID和value的工具类(解决手工复制id和value到excel模板中的问题)

package com.i18n.i18nbuilder;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 解析strings.xml和array.xml字符串资源文件,获取资源文件中的键和值
 * @author yangxin
 */
public class ParseStringResources {
	
	public static void main(String[] args) {
		try {
			getStringsIds();
			getArraysIds();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void getStringsIds() throws Exception {
		System.out.println("-------------------MusicPlayer----------------------------");
		ParseStringResources.parseStringsResourcesKey(new FileInputStream("musicplayer_strings.xml"));		// 解析id
		ParseStringResources.parseStringsResourcesValue(new FileInputStream("musicplayer_strings.xml"));	// 解析value
		
		System.out.println("-------------------VideoPlayer----------------------------");
		ParseStringResources.parseStringsResourcesKey(new FileInputStream("video_strings.xml"));
		ParseStringResources.parseStringsResourcesValue(new FileInputStream("video_strings.xml"));
	}
	
	public static void getArraysIds() throws Exception {
		InputStream is = null;
		is = new FileInputStream("musicplayer_arrays.xml");
		ParseStringResources.parseArraysResources(is);
	}
	
	/**
	 * 解析strings.xml中的key
	 */
	public static void parseStringsResourcesKey(InputStream is) throws Exception {
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(is);
		Element rootElement = document.getRootElement();
		List<Element> elements = rootElement.elements();
		for (Element element : elements) {
			String resid = element.attribute("name").getValue();
			System.out.println(resid);
		}
		System.out.println("-----------------------------------key解析完成---------------------------------");
	}
	
	/**
	 * 解析strings.xml中的value
	 */
	public static void parseStringsResourcesValue(InputStream is) throws Exception {
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(is);
		Element rootElement = document.getRootElement();
		List<Element> elements = rootElement.elements();
		for (Element element : elements) {
			String text = element.getTextTrim();
			System.out.println(text);
		}
		System.out.println("-----------------------------------value解析完成---------------------------------");
	}
	
	/**
	 * 解析arrays.xml文件
	 */
	public static void parseArraysResources(InputStream is) throws Exception {
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(is);
		Element rootElement = document.getRootElement();
		List<Element> elements = rootElement.elements();
		for (Element element : elements) {
			Attribute attribute = element.attribute("name");
			if (attribute == null) continue;
			String resid = attribute.getValue();
			System.out.println(resid);
			List<Element> items = element.elements();
			for (Element item : items) {
				String text = item.getTextTrim();
				System.out.println("      " + text);
			}
		}
	}
}
3、各国语言缩写映射关系

<?xml version="1.0" encoding="UTF-8"?>
<date_formats>
    <date_format>
        <language>cs</language>
        <format>dd.M.yyyy</format>
        <english>Czech</english>
        <chinese>捷克文</chinese>
    </date_format>
    <date_format>
        <language>da</language>
        <format>dd-MM-yyyy</format>
        <english>Deutsch</english>
        <chinese>丹麦文</chinese>
    </date_format>
    <date_format>
        <language>de</language>
        <format>dd.MM.yyyy</format>
        <english>German</english>
        <chinese>德文</chinese>
    </date_format>
    <date_format>
        <language>en</language>
        <format>dd/MM/yyyy</format>
        <english>English</english>
        <chinese>英文</chinese>
    </date_format>
    <date_format>
        <language>es</language>
        <format>dd/MM/yyyy</format>
        <english>Spanish</english>
        <chinese>西班牙文</chinese>
    </date_format>
    <date_format>
        <language>fr</language>
        <format>dd/MM/yyyy</format>
        <english>French</english>
        <chinese>法文</chinese>
    </date_format>
    <date_format>
        <language>it</language>
        <format>dd/MM/yyyy</format>
        <english>Italian</english>
        <chinese>意大利文</chinese>
    </date_format>
	<!--没有-->
    <date_format>
        <language>hu</language>
        <format>yyyy.MM.dd</format>
        <english>Hungarian</english>
        <chinese>匈牙利文</chinese>
    </date_format>
    <date_format>
        <language>nl</language>
        <format>dd-M-yyyy</format>
        <english>Dutch</english>
        <chinese>荷兰文</chinese>
    </date_format>
	<!-- 没有 android.mk也没有-->
    <date_format>
        <language>no</language>
        <format>dd.MM.yyyy</format>
        <english>Norwegian</english>
        <chinese>挪威文</chinese>
    </date_format>
    <date_format>
        <language>pl</language>
        <format>yyyy-MM-dd</format>
        <english>Polish</english>
        <chinese>波兰文</chinese>
    </date_format>
    <date_format>
        <language>pt</language>
        <format>dd-MM-yyyy</format>
        <english>Portuguese</english>
        <chinese>葡萄牙文</chinese>
    </date_format>
	<!--没有-->
    <date_format>
        <language>ro</language>
        <format>dd.MM.yyyy</format>
        <english>Romanian</english>
        <chinese>罗马尼亚文</chinese>
    </date_format>
	<!--没有-->
    <date_format>
        <language>fi</language>
        <format>dd.M.yyyy</format>
        <english>Finnish</english>
        <chinese>芬兰文</chinese>
    </date_format>
    <date_format>
        <language>sv</language>
        <format>yyyy-MM-dd</format>
        <english>Swedish</english>
        <chinese>瑞典文</chinese>
    </date_format>
    <date_format>
        <language>tr</language>
        <format>dd.MM.yyyy</format>
        <english>Turkish</english>
        <chinese>土耳其文</chinese>
    </date_format>
    <date_format>
        <language>el</language>
        <format>dd/M/yyyy</format>
        <english>Greece</english>
        <chinese>希腊文</chinese>
    </date_format>
    <date_format>
        <language>ru</language>
        <format>dd.MM.yyyy</format>
        <english>Russian</english>
        <chinese>俄文</chinese>
    </date_format>
    <date_format>
        <language>zh</language>
        <format>yyyy-M-dd</format>
        <english>Chinese</english>
        <chinese>中文</chinese>
    </date_format>
</date_formats>

五、资源文件生成效果


1、控制台打印信息

2、资源文件存放目录及strings.xml内容


工具使用注意事项:

1>、sheet的命名必须和工具类中”STRINGS_SHEETS“和”ARRAYS_SHEETS“数组存储的元素名称保持一致(区分大小写)

2>、删除sheet中的空白单元格

3>、修改languages.xls模板文件和资源文件生成后的存放路径


相关资源下载地址:

项目源代码 语言文字Excel模板


android国际化参考资料:

http://blog.csdn.net/xyang81/article/details/8870819

Android屏幕适配工具类 Android自动生成不同分辨率的值

Android屏幕适配工具类 Android自动生成不同分辨率的值

本文实例为大家分享了Android屏幕适配工具类的具体代码,供大家参考,具体内容如下

DimenTool

github地址

Android 屏幕适配方案,自动生成不同分辨率的值

android中官方建议的屏幕适配方式,通过根据不同的分辨率在工程的res文件夹下建立不同的尺寸文件夹,每个文件夹下都建立dimens.xml文件。然后根据不同的尺寸在dimens.xml文件夹中分别计算配置不同的dp或者sp单位。开发中发现,android屏幕适配需要用到很多的尺寸,每个尺寸都建立dimens.xml问价。每个文件中的数值都要按照比例去计算,一个一个拿着计算器去计算吗?这样太麻烦了。今天有一个好的办法,来为大家介绍一下。

步骤

1.在工程的java文件夹下把项目的DimenTool.java复制到该文件夹下。

/**
 * Created by cdy on 2016/2/3. 
 * 快速生成适配工具类 ,直接运行不成功需手动放入目录文件中
 */
public class DimenTool {

 public static void gen() {
 //以此文件夹下的dimens.xml文件内容为初始值参照 
 File file = new File("./app/src/main/res/values/dimens.xml");

 BufferedReader reader = null;
 StringBuilder sw240 = new StringBuilder();
 StringBuilder sw320 = new StringBuilder();
 StringBuilder sw360 = new StringBuilder();
 StringBuilder sw480 = new StringBuilder();
 StringBuilder sw600 = new StringBuilder();
 StringBuilder sw720 = new StringBuilder();
 StringBuilder sw800 = new StringBuilder();
 StringBuilder w820 = new StringBuilder();

 try {

 System.out.println("生成不同分辨率:");

 reader = new BufferedReader(new FileReader(file));

 String tempString;

 int line = 1;

 // 一次读入一行,直到读入null为文件结束 

 while ((tempString = reader.readLine()) != null) {


 if (tempString.contains("</dimen>")) {

  //tempString = tempString.replaceAll(" ", ""); 

  String start = tempString.substring(0, tempString.indexOf(">") + 1);

  String end = tempString.substring(tempString.lastIndexOf("<") - 2);
  //截取<dimen></dimen>标签内的内容,从>右括号开始,到左括号减2,取得配置的数字 
  Double num = Double.parseDouble
  (tempString.substring(tempString.indexOf(">") + 1,
   tempString.indexOf("</dimen>") - 2));

  //根据不同的尺寸,计算新的值,拼接新的字符串,并且结尾处换行。 
  sw240.append(start).append( num * 0.75).append(end).append("\r\n");
  sw320.append(start).append( num * 1).append(end).append("\r\n");
  sw360.append(start).append( num * 1.125).append(end).append("\r\n");
  sw480.append(start).append(num * 1.5).append(end).append("\r\n");
  sw600.append(start).append(num * 1.87).append(end).append("\r\n");
  sw720.append(start).append(num * 2.25).append(end).append("\r\n");
  sw800.append(start).append(num * 2.5).append(end).append("\r\n");
  w820.append(start).append(num * 2.56).append(end).append("\r\n");


 } else {
  sw240.append(tempString).append("");
  sw320.append(tempString).append("");
  sw360.append(tempString).append("");
  sw480.append(tempString).append("");
  sw600.append(tempString).append("");
  sw720.append(tempString).append("");
  sw800.append(tempString).append("");
  w820.append(tempString).append("");

 }

 line++;

 }

 reader.close();
 System.out.println("<!-- sw240 -->");
 System.out.println(sw240);
 System.out.println("<!-- sw320 -->");
 System.out.println(sw320);
 System.out.println("<!-- sw360 -->");
 System.out.println(sw360);
 System.out.println("<!-- sw480 -->");
 System.out.println(sw480);
 System.out.println("<!-- sw600 -->");
 System.out.println(sw600);
 System.out.println("<!-- sw720 -->");
 System.out.println(sw720);
 System.out.println("<!-- sw800 -->");
 System.out.println(sw800);
 String sw240file = "./app/src/main/res/values-sw240dp/dimens.xml";
 String sw320file = "./app/src/main/res/values-sw320dp/dimens.xml";
 String sw360file = "./app/src/main/res/values-sw360dp/dimens.xml";
 String sw480file = "./app/src/main/res/values-sw480dp/dimens.xml";
 String sw600file = "./app/src/main/res/values-sw600dp/dimens.xml";
 String sw720file = "./app/src/main/res/values-sw720dp/dimens.xml";
 String sw800file = "./app/src/main/res/values-sw800dp/dimens.xml";

 String w820file = "./app/src/main/res/values-w820dp/dimens.xml";
 //将新的内容,写入到指定的文件中去 
 writeFile(sw240file, sw240.toString());
 writeFile(sw320file, sw320.toString());
 writeFile(sw360file, sw360.toString());
 writeFile(sw480file, sw480.toString());
 writeFile(sw600file, sw600.toString());
 writeFile(sw720file, sw720.toString());
 writeFile(sw800file, sw800.toString());
 writeFile(w820file, w820.toString());

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

 } finally {

 if (reader != null) {
 try {

  reader.close();
 } catch (IOException e1) {
 e1.printStackTrace();

 }

 }

 }

 }


 /**
 * 写入方法 
 *
 */

public static void writeFile(String file, String text) {
 PrintWriter out = null;

 try {

 out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
 out.println(text);
 } catch (IOException e) {

 e.printStackTrace();

 }


 out.close();
 }
 public static void main(String[] args) {
 gen();

 }

} 

2.编写dimens下的数值(0.5-360,可根据项目来定范围,主要为以后方便使用),可直接把项目dimens复制到你的项目中

3.创建文件夹(values-sw240dp,values-sw320dp values-sw360dp…根据dimentool代码创建对应的文件夹)

4.单击鼠标右键,执行Run.Dimentools.main,对应values文件夹下即可生成对用的dimens值

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

您可能感兴趣的文章:
  • Android中关于屏幕的三个小众知识(宽屏适配、禁止截屏和保持屏幕常亮)
  • 简单谈谈我的Android屏幕适配之路
  • Android 图片显示与屏幕适配的问题
  • Android 手机屏幕适配解决办法
  • Android的分辨率和屏幕适配详解
  • Android-屏幕适配需要注意的地方总结
  • Android 简单好用的屏幕适配方案

Android自动化与持续集成实践

Android自动化与持续集成实践

Android自动化与持续集成实践


通过该文档,您可以了解到Android功能自动化测试实践、Android性能测试实践、以及持续集成实践等内容。


对其内容详细阅读

Android自动化性能收集

Android自动化性能收集

<h1>Android自动化性能收集</h1>

<p>Android 功能测试自动化框架较多,UIAutomator,Robotium,Appium等。Case执行过程中,可能希望收集手机的性能指标,包括内存、cpu、流量等。使用java+shell+bat简单实现了android手机性能收集。</p>

<h2>简述</h2>

<p>过程很简单:</p>

<ul> <li><p>在启动自动化case前,执行收集信息的命令。<br/> 其实就是一些adb shell命令,如下:</p>

<pre><code> adb shell top -n 1| awk ''{print $3" "$10}'' &gt;&gt; cpu.dat adb shell ps | awk ''{print $5" "$9}'' &gt;&gt; mem.dat //android sdk level 大于16 adb shell cat /proc/uid_stat/$uid/tcp_rcv &gt;&gt; $uid"_recv.dat" adb shell cat /proc/uid_stat/$uid/tcp_snd &gt;&gt; $uid"_snd.dat" //android sdk level 小于16 adb shell cat /proc/$pid/net/dev | grep wlan | awk ''{print $2" "$10}'' &gt;&gt; $pid"_net.dat" </code></pre></li>

<li><p>执行自动化case,可能需要很久。这个过程中,上面的命令在不断地执行</p></li> <li>case执行结束,kill掉第一步中的命令</li> <li>分析收集到的dat文件,使用jscharts绘出走势图</li> </ul>

<h2>脚本</h2>

<h3>cpu</h3>

<p>使用top命令不断查看各进程的cpu占用</p>

<h4>linux</h4>

<p>get-android-cpu.sh</p>

<pre><code> #!/bin/sh #path--target/android-info/mem/dat cd ../../../ mkdir -p target/android-info/cpu/dat mkdir -p target/android-info/cpu/html cp src/main/resources/jscharts.js target/android-info/cpu/html cd target/android-info/cpu/dat while true do adb shell top -n 1| awk ''{print $3" "$10}'' &gt;&gt; cpu.dat sleep 15 done </code></pre>

<h4>windows</h4>

<p>get-android-cpu.bat</p>

<pre><code> cd ..\..\jenkins\workspace\android-info-end3 mkdir target\android-info\cpu\dat mkdir target\android-info\cpu\html copy src\main\resources\jscharts.js target\android-info\cpu\html cd target\android-info\cpu\dat :run adb shell top -n 1 | awk "{print $3\" \"$10}" &gt;&gt; cpu.dat ping 127.0.0.1 -n 15 &gt; null goto run </code></pre>

<h3>memory</h3>

<p>使用ps命令不断查看各进程的内存占用</p>

<h4>linux</h4>

<p>get-android-mem.sh</p>

<pre><code> #!/bin/sh #path--target/android-info/mem/dat cd ../../../ mkdir -p target/android-info/mem/dat mkdir -p target/android-info/mem/html cp src/main/resources/jscharts.js target/android-info/mem/html cd target/android-info/mem/dat while true do adb shell ps | awk ''{print $5" "$9}'' &gt;&gt; mem.dat sleep 15 done </code></pre>

<h4>windows</h4>

<pre><code> cd ..\..\jenkins\workspace\android-info-end3 mkdir target\android-info\mem\dat mkdir target\android-info\mem\html copy src\main\resources\jscharts.js target\android-info\mem\html cd target\android-info\mem\dat :run adb shell ps | awk "{print $5\" \"$9}" &gt;&gt; mem.dat ping 127.0.0.1 -n 15 &gt; null goto run </code></pre>

<h3>流量</h3>

<p>android 4.0以上版本可以用<code>/proc/uid_stat/$uid/tcp_rcv</code>和<code>/proc/uid_stat/$uid/tcp_snd</code>来获取某个程序的上下行流量;而4.0以下版本要用<code>cat /proc/$pid/net/dev</code>来查看上下行流量。uid和pid的关系,可以从<code>/data/system/packages.list</code>这个文件中获取。</p>

<h4>linux</h4>

<p>判断android api level:</p>

<pre><code> #!/bin/sh #android 4.0以上和4.0以下方法不同 #get android sdk level apileveltemp=`adb shell getprop | grep ro.build.version.sdk` apilevel=${apileveltemp:25:2} chmod +x *.sh echo "android api level:"$apilevel if [ $apilevel -gt 14 ] then ./get-android-net-gt-4.0.sh elif [ $apilevel -lt 14 ] then ./get-android-net-lt-4.0.sh fi </code></pre>

<p>get-android-net-gt-4.0.sh</p>

<pre><code> #!/bin/sh #android api level great than 14(android 4.0) #path--target/android-info/net/dat cd ../../../ mkdir -p target/android-info/net/dat mkdir -p target/android-info/net/html cp src/main/resources/jscharts.js target/android-info/net/html cd target/android-info/net/dat cd .. echo "adb pull/data/system/packages.list--start" adb pull /data/system/packages.list cd dat while true do echo "get net info from /proc/uid-stat/$uid" for i in `adb shell ls /proc/uid_stat` do #delete the Enter character uid=`echo $i | tr -d ["\r\n"]` adb shell cat /proc/uid_stat/$uid/tcp_rcv &gt;&gt; $uid"_recv.dat" adb shell cat /proc/uid_stat/$uid/tcp_snd &gt;&gt; $uid"_snd.dat" done sleep 15 done </code></pre>

<p>get-android-net-lt-4.0.sh</p>

<pre><code> #!/bin/sh #path--target/android-info/net/dat cd ../../../ mkdir -p target/android-info/net/dat mkdir -p target/android-info/net/html cp src/main/resources/jscharts.js target/android-info/net/html cd target/android-info/net/dat #get /proc/$pid/net/dev while true do #get pid for i in `adb shell ps | awk ''{print $2}''` do pid=`echo $i | tr -d ["\r\n"]` echo $pid adb shell cat /proc/$pid/net/dev | grep wlan | awk ''{print $2" "$10}'' &gt;&gt; $pid"_net.dat" done sleep 15 done </code></pre>

<h4>windows</h4>

<p>bat命令不熟,不知道如何在windows下实现linux下地反转义,这里用java代码实现。</p>

<pre><code> import java.io.*; /** * Created by Xuemeng Wang on 14-9-15. * api Level &gt; 16 */ public class GetNetInfo { public static void main(String[] args) { String uidString = execCmd("adb shell ls /proc/uid_stat"); String[] uidArray = uidString.split("\n"); int length = uidArray.length-1; for(int i=0;i&lt;=length-1;i++) { String contentRcv = execCmd("adb shell cat /proc/uid_stat/"+uidArray[i]+"/tcp_rcv"); String contentSnd = execCmd("adb shell cat /proc/uid_stat/"+uidArray[i]+"/tcp_snd"); System.out.println(System.getProperty("user.dir")); try { File file = new File(uidArray[i]+"_recv.dat"); if(!file.exists()) file.createNewFile(); File file2 = new File(uidArray[i]+"_snd.dat"); if(!file2.exists()) file2.createNewFile(); FileWriter fileWriter1 = new FileWriter(file, true); FileWriter fileWriter2 = new FileWriter(file2, true); fileWriter1.write(contentRcv); fileWriter2.write(contentSnd); fileWriter1.close(); fileWriter2.close(); } catch (IOException e) { e.printStackTrace(); } } } public static String execCmd(String command) { BufferedReader br = null; StringBuffer stringBuffer = new StringBuffer(); try { Process p = Runtime.getRuntime().exec(command); br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = null; while ((line = br.readLine()) != null) { if("".equals(line.trim())) continue; stringBuffer.append(line+"\n"); } } catch (Exception e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (Exception e) { e.printStackTrace(); } } } return stringBuffer.toString(); } } </code></pre>

<p>api level小于16的情况,我没用到,略掉:)。</p>

<h3>杀掉进程</h3>

<p>linux: <code>ps -ef | grep get-android- | grep -v grep | awk ''{print $2}'' | xargs kill -9</code><br/> windows(后台运行,其实是cmd进程,注意下面会杀掉所有的cmd进程):</p>

<pre><code> taskkill /F /IM cmd.exe taskkill /F /IM adb.exe </code></pre>

<h2>结果收集</h2>

<p>使用java分析dat,给出分析cpu的代码,工程已上传到github,<a href="https://github.com/yeetrack/android-performance">https://github.com/yeetrack/android-performance</a>。</p>

<p>CpuInfo.java</p>

<pre><code> package com.meilishuo.android.performance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.Test; import java.io.*; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.TreeMap; /** * Created by victor on 14-9-9. */ public class CpuInfo { private static final Logger logger = LoggerFactory.getLogger(MemInfo.class); private static final String JSCHARTPATH = "target/android-info/cpu/html/"; private static final String MEMFILEPATH = "target/android-info/cpu/dat/cpu.dat"; TreeMap&lt;String, List&lt;String&gt;&gt; cpuMap = new TreeMap&lt;String, List&lt;String&gt;&gt;(); /** * 解析cpu.dat存储到map中 */ public void parseCpuFile() { File file = new File(MEMFILEPATH); if(null==file) return; try { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file))); String line = null; while((line=bufferedReader.readLine())!=null) { String[] array = line.trim().split(" "); //空格分隔 if(null==array || array.length!=2 || !array[0].contains("%") || "".equals(array[1]) || "Name".equals(array[1])) continue; if(cpuMap.size()==0 || !cpuMap.containsKey(array[1])) { List&lt;String&gt; memList = new ArrayList&lt;String&gt;(); memList.add(array[0].substring(0, array[0].indexOf("%"))); cpuMap.put(array[1], memList); } else { cpuMap.get(array[1]).add(array[0].substring(0, array[0].indexOf("%"))); } } System.out.println(cpuMap.size()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 将map中的数据写到到xml中 */ public void writeXmlFromMap() { if(null==cpuMap || cpuMap.size()==0) return; Iterator&lt;String&gt; it = cpuMap.keySet().iterator(); while(it.hasNext()) { String key = it.next(); List&lt;String&gt; value = cpuMap.get(key); if(null==value || value.size()&lt;=1) continue; //写入xml File file = new File(JSCHARTPATH+key.replace("/", "_").replace(":", "_")+"_cpu.xml"); try { BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true))); bufferedWriter.write( "&lt;?xml version=\"1.0\"?&gt;\n" + "&lt;JSChart&gt;\n" + "\t&lt;dataset type=\"line\"&gt;"); int pos = 1; for(String index : value) { bufferedWriter.write("&lt;data unit=\""+pos+"\" value=\""+index+"\"/&gt;\n"); pos++; } bufferedWriter.write( "&lt;/dataset&gt;\n" + "\t&lt;optionset&gt;\n" + "\t\t&lt;option set=\"setLineColor\" value=\"''#8D9386''\"/&gt;\n" + "\t\t&lt;option set=\"setLineWidth\" value=\"4\"/&gt;\n" + "\t\t&lt;option set=\"setTitleColor\" value=\"''#7D7D7D''\"/&gt;\n" + "\t\t&lt;option set=\"setAxisColor\" value=\"''#9F0505''\"/&gt;\n" + "\t\t&lt;option set=\"setGridColor\" value=\"''#a4a4a4''\"/&gt;\n" + "\t\t&lt;option set=\"setAxisValuesColor\" value=\"''#333639''\"/&gt;\n" + "\t\t&lt;option set=\"setAxisNameColor\" value=\"''#333639''\"/&gt;\n" + "\t\t&lt;option set=\"setTextPaddingLeft\" value=\"0\"/&gt;\n" + "\t&lt;/optionset&gt;\n " + "&lt;/JSChart&gt;"); bufferedWriter.flush(); bufferedWriter.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } /** * 生成jschart html文件 */ public void writeJsHtml() { File file = new File(JSCHARTPATH); File[] xmlFiles = file.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.getName().endsWith("_cpu.xml"); } }); if(null== xmlFiles || xmlFiles.length==0) return; for(File index : xmlFiles) { File htmlFile = new File(index.getAbsolutePath().replace(".xml", ".html")); try { BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(htmlFile)); </code></pre>

继续阅读->

关于如何为Android自动化生成报告android 自动化的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Android国际化资源文件自动化生成工具、Android屏幕适配工具类 Android自动生成不同分辨率的值、Android自动化与持续集成实践、Android自动化性能收集的相关知识,请在本站寻找。

本文标签: