包含androideventtype的词条
android accessibilityservice 服务问题
利用Android辅助工具类AccessibilityService可以获取手机当前页面的信息,用户的操作事件等等.首先新建一个类继承AccessibilityService:[html] view plain copy
span?style="font-family:Times?New?Roman;font-size:14px;"public?class?MyAccessibilityService?extends?AccessibilityService?{
private?final?String?TAG?=?"MyAccessibilityService";
@Override
public?void?onAccessibilityEvent(AccessibilityEvent?event)?{
int?eventType?=?event.getEventType();
String?eventTypeName?=?"";
switch?(eventType)?{
case?AccessibilityEvent.TYPE_VIEW_CLICKED:
eventTypeName?=?"TYPE_VIEW_CLICKED";
break;
case?AccessibilityEvent.TYPE_VIEW_FOCUSED:
eventTypeName?=?"TYPE_VIEW_FOCUSED";
break;
case?AccessibilityEvent.TYPE_VIEW_LONG_CLICKED:
eventTypeName?=?"TYPE_VIEW_LONG_CLICKED";
break;
case?AccessibilityEvent.TYPE_VIEW_SELECTED:
eventTypeName?=?"TYPE_VIEW_SELECTED";
break;
case?AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
eventTypeName?=?"TYPE_VIEW_TEXT_CHANGED";
break;
case?AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
eventTypeName?=?"TYPE_WINDOW_STATE_CHANGED";
break;
case?AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
eventTypeName?=?"TYPE_NOTIFICATION_STATE_CHANGED";
break;
case?AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
eventTypeName?=?"TYPE_TOUCH_EXPLORATION_GESTURE_END";
break;
case?AccessibilityEvent.TYPE_ANNOUNCEMENT:
eventTypeName?=?"TYPE_ANNOUNCEMENT";
break;
case?AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
eventTypeName?=?"TYPE_TOUCH_EXPLORATION_GESTURE_START";
break;
case?AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
eventTypeName?=?"TYPE_VIEW_HOVER_ENTER";
break;
case?AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
eventTypeName?=?"TYPE_VIEW_HOVER_EXIT";
break;
case?AccessibilityEvent.TYPE_VIEW_SCROLLED:
eventTypeName?=?"TYPE_VIEW_SCROLLED";
break;
case?AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED:
eventTypeName?=?"TYPE_VIEW_TEXT_SELECTION_CHANGED";
break;
case?AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
eventTypeName?=?"TYPE_WINDOW_CONTENT_CHANGED";
break;
}
Log.i(TAG,?"eventType:"?+?eventType);
Log.i(TAG,?"eventTypeName:"?+?eventTypeName);
}
@Override
public?void?onInterrupt()?{
//?TODO?Auto-generated?method?stub
}
}/span
然后新建一个xml配置文件来配置我们的MyAccessibility类:
accessibilityservice.xml :
[html] view plain copy
span?style="font-family:Times?New?Roman;font-size:14px;"?xml?version="1.0"?encoding="utf-8"?
accessibility-service?xmlns:android=""??
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"
android:description="@string/app_name"
android:settingsActivity="com.example.xxx.android.accessibility.ServiceSettingsActivity"?//span
android:accessibilityEventTypes="typeAllMask",相应所有的事件,就是MyAccessibility类中swich中的那些事件.
android:accessibilityFeedbackType="feedbackGeneric",手机用什么方式将信息反馈给用户,语音震动等等,这里默认;
android:canRetrieveWindowContent="true",允许获取手机页面中的信息
android:settingsActivity中com.example.xxx是你的应用的包名
然后将这个xml配置文件配置到项目中:
[html] view plain copy
span?style="font-family:Times?New?Roman;font-size:14px;"????????service
android:name="com.example.xxx.MyAccessibilityService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"?
intent-filter
action?android:name="android.accessibilityservice.AccessibilityService"?/
/intent-filter
meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibilityservice"?/
/service/span
然后在我们手机的设置中的辅助功能里,打开这个辅助服务就可以了.
利用这个类我们可以获取当前手机页面的信息,包括控件ID,控件值;当前类的名称以及用户的一些操作和手机状态的变化. 所以利用这些可以做手机自动安装软件,模拟点击,手机自动滑屏等.
public void onAccessibilityEvent(AccessibilityEvent event){}
通过这个event我们可以得到:
event.getEventType()-当前事件的类型; ?event.getClassName()-当前类的名称; ?event.getSource()-当前页面中的节点信息,等等.更详细信查看官方API
遍历获取窗口中所有的节点信息也可以用这个方法:
[html] view plain copy
span?style="font-family:Times?New?Roman;font-size:14px;"public?void?getInfo()?{
AccessibilityNodeInfo?info?=?getRootInActiveWindow();
if?(info?!=?null)?{
if?(info.getChildCount()?==?0)?{
Log.i(TAG,?"控件名称:"?+?info.getClassName());
Log.i(TAG,?"控件中的值:"?+?info.getText());
Log.i(TAG,?"控件的ID:"?+?info.getViewIdResourceName());
Log.i(TAG,?"点击是否出现弹窗:"?+?info.canOpenPopup());
}?else?{
for?(int?i?=?0;?i??info.getChildCount();?i++)?{
if?(info.getChild(i)?!=?null)?{
recycle(info.getChild(i));
}
}
}
}
}/span
不过这个方法对当前的SDK版本有一定的要求,需要API level?19及以上.
android studio 的xml数据获取
这个很简单啊xml解析,pull解析
public class PullBookParser {
@Override
public ListBook parse(InputStream is) throws Exception {
ListBook books = null;
Book book = null;
// XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
// XmlPullParser parser = factory.newPullParser();
XmlPullParser parser = Xml.newPullParser(); //由android.util.Xml创建一个XmlPullParser实例
parser.setInput(is, "UTF-8"); //设置输入流 并指明编码方式
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
books = new ArrayListBook();
break;
case XmlPullParser.START_TAG:
if (parser.getName().equals("book")) {
book = new Book();
} else if (parser.getName().equals("id")) {
eventType = parser.next();
book.setId(Integer.parseInt(parser.getText()));
} else if (parser.getName().equals("name")) {
eventType = parser.next();
book.setName(parser.getText());
} else if (parser.getName().equals("price")) {
eventType = parser.next();
book.setPrice(Float.parseFloat(parser.getText()));
}
break;
case XmlPullParser.END_TAG:
if (parser.getName().equals("book")) {
books.add(book);
book = null;
}
break;
}
eventType = parser.next();
}
return books;
}
}
安卓如何读取自定义XML文件里的任意数据
在程序升级的时候,每更新一个版本都要写升级日志,将升级日志放在xml文件中,通过代码来读取是一个较好的方案。
关键类:Resources
关键方法:public int getIdentifier(String name, String defType, String defPackage)
关于具体使用方法,举例如下:
1、updatelog.xml文件位于res/xml/文件夹下:
?xml version="1.0" encoding="utf-8"?
updatelog
release
version="1.0"
versioncode="1.1"
log1、这个文件在res/xml文件夹下;/log
log2、这个文件的名字是“updatelog.xml”/log
log3、这是一个xml文件/log
/release
/updatelog
2、在代码中调用方法如下:
public class ResourcesActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView( R.layout.resources_layout );
mTextView = ( TextView )findViewById( R.id.textId );
getFileResources( );
}
private void getFileResources( ){
String packageName = getPackageName( );
try {
Resources resources = this.getPackageManager( ).getResourcesForApplication( packageName );
int resId = resources.getIdentifier( "updatelog", "xml", packageName );
String log = getUpdatelog( resId, resources );
int appId = resources.getIdentifier( "action_settings", "string", packageName );
String appName = resources.getString( appId );
mTextView.setText( appName + "\n" + log );
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
private String parseTag( XmlResourceParser xml ) throws XmlPullParserException, IOException {
String result = "Version: "+ xml.getAttributeValue(null, "version") + "\n" + "VersionCode: " + xml.getAttributeValue(null, "versioncode") + "\n";
int eventType = xml.getEventType( );
while( ( eventType != XmlPullParser.END_TAG ) || ( xml.getName( ).equals( "log" ) ) ) {
if( (eventType == XmlPullParser.START_TAG) ( xml.getName( ).equals( "log" ) ) ) {
eventType = xml.next( );
result = result + xml.getText( ) + "\n";
}
eventType = xml.next( );
}
return result;
}
private String getUpdatelog( int resourceId, Resources resource ) {
String result = "";
XmlResourceParser xmlResParser = resource.getXml( resourceId );
try {
int eventType = xmlResParser.getEventType( );
while ( eventType != XmlPullParser.END_DOCUMENT ) {
if ( ( eventType == XmlPullParser.START_TAG ) ( xmlResParser.getName( ).equals( "release" ) ) ) {
result = result + parseTag( xmlResParser );
}
eventType = xmlResParser.next( );
}
} catch (XmlPullParserException e) {
System.out.println( e.getMessage( ) );
} catch (IOException e) {
System.out.println( e.getMessage( ) );
} finally {
xmlResParser.close( );
}
return result;
}
private TextView mTextView = null;
}
如何在android 中service后台监听按键,比如监听音量键
为了实现键盘的监控,从新开发一个输入法是不现实的,一般的操作就是在系统的输入法机制中添加接口回调。我们知道,再应用程序中拿到按键的回调一般是监听onKeyDown的接口,如下所示:publicbooleanonKeyDown(intkeyCode,KeyEventevent)开发者就可以根据回调方法中的参数,keyCode与KeyEvent来判断具体事件。但是,由于事件的回调机制在其的沙箱中运行,在其他应用中是无法拿到当前应用事件回调的。那么我们就从上到下,具体的看看事件的传递机制。如下图所示,用户点击后,软键盘或物理按键的输入驱动就会产生一个中断,且向/dev/input/event*中写入一个相应的信号量。Android操作系统则会循环的读取其中的事件,再分发给WindowManagerServer。由WindowManagerServer根据事件的来源分发到各个不同的ViewGroup与View中,从而产生不同的OnClick、OnKeyDown和OnTouch等事件。这个时候很自然的想到,黑客们希望做键盘监控,一定会向Linux底层增加自定义的事件。这里我们使用的是Linux中的getevent获得/dev/input/eventX设备汇报的事件,这个命令还会输出所有event设备的基本信息。包括触屏、按键、耳机插入等等。其基本用法如下:Usage:getevent[-t][-n][-sswitchmask][-S][-v[mask]][-d][-p][-i][-l][-q][-ccount][-r][device]-t:showtimestamps-n:don'tprintnewlines-s:printswitchstatesforgivenbits-S:printallswitchstates-v:verbositymask(errs=1,dev=2,name=4,info=8,vers=16,pos.events=32,props=64)-d:showHIDdescriptor,ifavailable-p:showpossibleevents(errs,dev,name,pos.events)-i:showalldeviceinfoandpossibleevents-l:labeleventtypesandnamesinplaintext-q:quiet(clearverbositymask)-c:printgivennumberofeventsthenexit-r:printrateeventsarereceived键入getevent后,我们能够看到设备中的一些列输入硬件驱动信息,同样下面会出现很多输入指令信号,通常情况下,这些信号量都在刷屏,如下图所示:这些信号量的表示我们无法直接看懂,输入getevent–l加入Label我们能够看到一些添加的标签,如下所示:其实这些Lable已经在其input.h头文件中定义好,其中type的定义如下:/**Eventtypes*/#defineEV_SYN0x00#defineEV_KEY0x01#defineEV_REL0x02#defineEV_ABS0x03#defineEV_MSC0x04#defineEV_SW0x05#defineEV_LED0x11#defineEV_SND0x12#defineEV_REP0x14#defineEV_FF0x15#defineEV_PWR0x16#defineEV_FF_STATUS0x17#defineEV_MAX0x1f#defineEV_CNT(EV_MAX+1)一般来说,常用的是EV_KEY、EV_REL、EV_ABS、EV_SYN,分别对应键盘按键、相对坐标、绝对坐标、同步事件。EV_SYN则表示一组完整事件已经完成,需要处理,EV_SYN的code定义事件分发的类型。
如何解决Android帧动画出现的内存溢出
1.anin_searh.xml
[html] view plain copy
?xml version="1.0" encoding="utf-8"?
animation-list xmlns:android=""
android:oneshot="true"
item android:drawable="@drawable/a1" android:duration="100"/item
item android:drawable="@drawable/a2" android:duration="100"/item
item android:drawable="@drawable/a4" android:duration="100"/item
item android:drawable="@drawable/a5" android:duration="100"/item
item android:drawable="@drawable/a6" android:duration="100"/item
item android:drawable="@drawable/a7" android:duration="100"/item
item android:drawable="@drawable/a8" android:duration="100"/item
item android:drawable="@drawable/a9" android:duration="100"/item
item android:drawable="@drawable/a10" android:duration="100"/item
item android:drawable="@drawable/a11" android:duration="100"/item
/animation-list
2.使用帧动画
[java] view plain copy
search_scale_iv.setBackgroundResource(R.drawable.anim_search);
AnimationDrawable drawable = (AnimationDrawable) search_scale_iv.getBackground();
drawable.start();
结果setBackgroundResource出现内存溢出,这个方法其实获取drawable时候,会消耗很多内存,很容易内存溢出,崩溃。
3.解决方法:在网上找了个类,处理,结果我使用11张560k大小图片,没有内存溢出;
[java] view plain copy
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.graphics.BitmapFactory;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.widget.ImageView;
import org.apache.commons.io.IOUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/****
* 此工具类源于stack over flow
* 原文链接:
* 主要使用了BitmapFactory.decodeByteArray方法通过底层C来绘制图片,有效防止OOM
* 使用了第三方类库:org.apache.commons.io.IOUtils,将Inputstream转为byte字节数组
* *******/
public class MyAnimationDrawable {
public static class MyFrame {
byte[] bytes;
int duration;
Drawable drawable;
boolean isReady = false;
}
public interface OnDrawableLoadedListener {
public void onDrawableLoaded(ListMyFrame myFrames);
}
// 1
/***
* 性能更优
* 在animation-list中设置时间
* **/
public static void animateRawManuallyFromXML(int resourceId,
final ImageView imageView, final Runnable onStart,
final Runnable onComplete) {
loadRaw(resourceId, imageView.getContext(),
new OnDrawableLoadedListener() {
@Override
public void onDrawableLoaded(ListMyFrame myFrames) {
if (onStart != null) {
onStart.run();
}
animateRawManually(myFrames, imageView, onComplete);
}
});
}
// 2
private static void loadRaw(final int resourceId, final Context context,
final OnDrawableLoadedListener onDrawableLoadedListener) {
loadFromXml(resourceId, context, onDrawableLoadedListener);
}
// 3
private static void loadFromXml(final int resourceId,
final Context context,
final OnDrawableLoadedListener onDrawableLoadedListener) {
new Thread(new Runnable() {
@Override
public void run() {
final ArrayListMyFrame myFrames = new ArrayListMyFrame();
XmlResourceParser parser = context.getResources().getXml(
resourceId);
try {
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
} else if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("item")) {
byte[] bytes = null;
int duration = 1000;
for (int i = 0; i parser.getAttributeCount(); i++) {
if (parser.getAttributeName(i).equals(
"drawable")) {
int resId = Integer.parseInt(parser
.getAttributeValue(i)
.substring(1));
bytes = IOUtils.toByteArray(context
.getResources()
.openRawResource(resId));
} else if (parser.getAttributeName(i)
.equals("duration")) {
duration = parser.getAttributeIntValue(
i, 1000);
}
}
MyFrame myFrame = new MyFrame();
myFrame.bytes = bytes;
myFrame.duration = duration;
myFrames.add(myFrame);
}
} else if (eventType == XmlPullParser.END_TAG) {
} else if (eventType == XmlPullParser.TEXT) {
}
eventType = parser.next();
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e2) {
// TODO: handle exception
e2.printStackTrace();
}
// Run on UI Thread
new Handler(context.getMainLooper()).post(new Runnable() {
@Override
public void run() {
if (onDrawableLoadedListener != null) {
onDrawableLoadedListener.onDrawableLoaded(myFrames);
}
}
});
}
}).run();
}
// 4
private static void animateRawManually(ListMyFrame myFrames,
ImageView imageView, Runnable onComplete) {
animateRawManually(myFrames, imageView, onComplete, 0);
}
// 5
private static void animateRawManually(final ListMyFrame myFrames,
final ImageView imageView, final Runnable onComplete,
final int frameNumber) {
final MyFrame thisFrame = myFrames.get(frameNumber);
if (frameNumber == 0) {
thisFrame.drawable = new BitmapDrawable(imageView.getContext()
.getResources(), BitmapFactory.decodeByteArray(
thisFrame.bytes, 0, thisFrame.bytes.length));
} else {
MyFrame previousFrame = myFrames.get(frameNumber - 1);
((BitmapDrawable) previousFrame.drawable).getBitmap().recycle();
previousFrame.drawable = null;
previousFrame.isReady = false;
}
imageView.setImageDrawable(thisFrame.drawable);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// Make sure ImageView hasn't been changed to a different Image
// in this time
if (imageView.getDrawable() == thisFrame.drawable) {
if (frameNumber + 1 myFrames.size()) {
MyFrame nextFrame = myFrames.get(frameNumber + 1);
if (nextFrame.isReady) {
// Animate next frame
animateRawManually(myFrames, imageView, onComplete,
frameNumber + 1);
} else {
nextFrame.isReady = true;
}
} else {
if (onComplete != null) {
onComplete.run();
}
}
}
}
}, thisFrame.duration);
// Load next frame
if (frameNumber + 1 myFrames.size()) {
new Thread(new Runnable() {
@Override
public void run() {
MyFrame nextFrame = myFrames.get(frameNumber + 1);
nextFrame.drawable = new BitmapDrawable(imageView
.getContext().getResources(),
BitmapFactory.decodeByteArray(nextFrame.bytes, 0,
nextFrame.bytes.length));
if (nextFrame.isReady) {
// Animate next frame
animateRawManually(myFrames, imageView, onComplete,
frameNumber + 1);
} else {
nextFrame.isReady = true;
}
}
}).run();
}
}