当前位置:  CSS属性参考手册 iis7站长之家
本页文章导读:
    ▪UITableView性能优化及手工作图UITableViewCell        UITableView性能优化及手工绘制UITableViewCell提高表视图的性能 UITableView作为应用中最常用的视图,它的性能优化问题几乎是经常提及。下面对在非网络访问情况下的表视图性能优化进行了主要.........
    ▪ Google Play跟基于Feature的过滤 —— Feature 参考手册        Google Play和基于Feature的过滤 —— Feature 参考手册翻译自 Features Reference下表列出了软/硬件Feature和权限的参考信息,它们被用于GooglePlay。硬件feature下面列出了被大多数当前发布的平台所支持.........
    ▪ Google Play跟基于Feature的过滤       Google Play和基于Feature的过滤田海立@CSDN翻译自Google Play and Feature-Based FilteringGooglePlay会过滤出那些对用户可见的应用程序,因此用户只能看到和下载那些与他们的设备兼容的应用程序。过滤应.........

[1]UITableView性能优化及手工作图UITableViewCell
    来源: 互联网  发布时间: 2014-02-18
UITableView性能优化及手工绘制UITableViewCell
提高表视图的性能

UITableView作为应用中最常用的视图,它的性能优化问题几乎是经常提及。下面对在非网络访问情况下的表视图性能优化进行了主要的几点说明:

1.自定义类或XIB文件时

在系统提供的样式不能满足我们的时候,我们经常会创建自定义类或者XIB文件来自定义单元格样式。
在之前,我们通常通过loadNib的方式或者在代理方法中继续使用老的方法来设置重用,管理缓存池。在IOS6以后,我们可以通过注册的方式在注册单元格甚至表头视图,让系统来更高效的进行管理。



2.InterfaceBuilder

据说有很多偏执的工程狮们坚持手打代码来完成工程,讨厌拖拖拽拽。不过随着IB的不断强大,已经有越来越多的人喜欢上了使用IB来建立和管理界面。在新的Xcode5中,IB又进步了不少。回到正题,尽管如此,在使用高性能的Cell时,还是推荐使用代码来创建单元格类。当UITableViewCell拥有多个子视图时,IOS的渲染机制会拖慢速度。重写drawRect直接绘制内容的方式可以提高性能,而不是在类初始化的时候初始化一些label或者imageview等。

3.图层颜色问题

透明图层对渲染性能会有一定的影响,系统必须将透明图层与下面的视图混合起来计算颜色,并绘制出来。减少透明图层并使用不透明的图层来替代它们,可以极大地提高渲染速度。

4.渲染中注意的问题

绘制时要尽可能的避免分配资源,比如UIFont,NSDateFormatter或者任何在绘制时需要的对象,推荐使用类层级的初始化方法中执行分配,并将其存储为静态变量。

5.为代理方法瘦身

我们经常能看到在项目中,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
这个方法中的代码多的吓人,我们可以讲一些数据绑定到cell中,或者在有多个tableview的时候,将其绑定到其他的tableviewcontroller中去。这样可以方便维护和管理,其实也对程序运行性能有很大的帮助。


手工绘制单元格

下面就绘制一个表视图单元格,并在表视图中显示。

初始化数据

- (void)loadAnimals
{
    _animalList = [NSMutableArray arrayWithCapacity:rAnimalCount];
    for (NSInteger i = 0; i < rAnimalCount; i++)
    {
        Animal *animal = [[Animal alloc] init];
        NSString *name = [NSString stringWithFormat:@"Animal-%03d", i+1];
        NSString *detail = [NSString stringWithFormat:@"dog or cat?"];
        NSInteger seed = arc4random()%8 + 1;
        NSString *imageName = [NSString stringWithFormat:@"head%02d", seed+1];
        
        animal.name = name;
        animal.detail = detail;
        animal.imageName = imageName;
        
        [_animalList addObject:animal];
    }
}

重点在于绘制,我首先创建了一个继承自UITableViewCell的父类一会让我们的单元格继承它,父类中有一个UIView类型的contentView成员,所有的绘制将在这个成员上进行。

@interface HRCellView : UIView
@end
@implementation HRCellView
- (void)drawRect:(CGRect)rect
{
    [(HRCell *)[self superview] drawContentView:rect];
}
@end

@implementation HRCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        contentView = [[HRCellView alloc] init];
        contentView.opaque = YES;   //不透明,提升渲染性能
        [self addSubview:contentView];
    }
    return self;
}

- (void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    CGRect b = [self bounds];
    b.size.height -= 1;     // 给分割线留出位置
    contentView.frame = b;  
}

- (void)setNeedsDisplay
{
    [super setNeedsDisplay];
    [contentView setNeedsDisplay];
}

- (void)drawContentView:(CGRect)rect
{
    //子类实现
}
@end


下面是绘制单元格

在初始化类方法中初始化字体资源

static UIFont *NameFont;
static UIFont *DetailFont;

@implementation HRCustomCell

+ (void)initialize
{
    NameFont = [UIFont fontWithName:@"American Typewriter" size:rNameFontSize];
    DetailFont = [UIFont fontWithName:@"American Typewriter" size:rDetailFontSize];
}

将数据绑定到这个单元格中

- (void)bindAnimal:(Animal *)animal
{
    if (_nameText != animal.name)
    {
        _nameText = animal.name;
    }
    if (_detailText != animal.detail)
    {
        _detailText = animal.detail;
    }
    if (_imageName != animal.imageName)
    {
        _imageName = animal.imageName;
    }
    
    [self setNeedsDisplay];
}


实现父类的drawContentView方法,实现绘制

- (void)drawContentView:(CGRect)rect
{
    static UIColor *nameColor;
    nameColor = [UIColor blackColor];
    static UIColor *detailColor;
    detailColor = [UIColor darkGrayColor];
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGRect cellRect = self.frame;
    
    if (self.highlighted || self.selected)  //选择或高亮时对应的颜色
    {
        CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);
        CGContextFillRect(context, CGRectMake(0, 0, cellRect.size.width, cellRect.size.height));
    }
    else
    {
        CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
        CGContextFillRect(context, CGRectMake(0, 0, cellRect.size.width, cellRect.size.height));
    }
    
    UIImage *image = [UIImage imageNamed:_imageName];
    [image drawInRect:CGRectMake(5, 5, 50, 50)];
    
    [nameColor set];
    [_nameText drawAtPoint:CGPointMake(65, 10)
                  forWidth:200
                  withFont:NameFont
                  fontSize:rNameFontSize
             lineBreakMode:NSLineBreakByWordWrapping
        baselineAdjustment:UIBaselineAdjustmentAlignBaselines];
    
    [detailColor set];
    [_detailText drawAtPoint:CGPointMake(180, 40)
                    forWidth:120
                    withFont:DetailFont
                    fontSize:rDetailFontSize
               lineBreakMode:NSLineBreakByWordWrapping
          baselineAdjustment:UIBaselineAdjustmentAlignBaselines];
}

虽然方法很长,但是只要会简单的quartz绘图这些都是最基础的方法。

完成后我们讲这个类注册到tableview中

[self.tableView registerClass:[HRCustomCell class] forCellReuseIdentifier:CellIdentifier];

再来看我们的代理方法



就只有3行,比把数据都从这里赋值的方法要简洁许多。

完成的效果图



如果用真机调试,性能也要比使用非手工绘制的性能要好很多。


demo示例点击打开链接


以上为本篇博客全部内容,欢迎指正和交流。转载注明出处~


    
[2] Google Play跟基于Feature的过滤 —— Feature 参考手册
    来源: 互联网  发布时间: 2014-02-18
Google Play和基于Feature的过滤 —— Feature 参考手册

翻译自 Features Reference

下表列出了软/硬件Feature和权限的参考信息,它们被用于GooglePlay。

硬件feature

下面列出了被大多数当前发布的平台所支持的硬件功能描述。为了标明应用程序所使用或需要的某个硬件Feature,都要在一个独立的<uses-feature>元素的android:name属性中声明。

Feature类型

Feature描述符

描述

注释

Audio

android.hardware.audio.low_latency

应用程序使用设备上的低延迟的音频通道,并且对于输入或输出的延迟或之后是敏感的。

 

Bluetooth

android.hardware.bluetooth

应用程序要使用设备中的蓝牙射频Feature。

 

Camera

android.hardware.camera

应用程序要使用设备的摄像头,如果设备支持多个摄像头,那么应用程序会使用屏幕背面的那个。

 

android.hardware.camera.autofocus

子Feature。应用程序要使用设备摄像头的自动对焦能力。

这些子Feature隐式的声明了android.hardware.camera的父功能,除非声明了android:required="false"。

android.hardware.camera.flash

子Feature。应用程序要使用设备摄像头的闪光灯能力。

android.hardware.camera.front

子Feature。应用程序要使用设备上的前置摄像头。

android.hardware.camera.any

应用程序至少使用了任何方向上的摄像头。如果后摄像头不是必须的可以用android.hardware.camera。.

 

Location

android.hardware.location

应用程序会使用设备上的多种功能来获取位置,如GPS定位、网络定位、或小区定位。

 

android.hardware.location.network

子Feature,应用程序要从设备上所支持的基于网络的定位系统来获取大概的位置坐标。

这些子Feature的声明,就隐式的声明了android.hardware.location父Feature,除非其声明了android:required="false"。

android.hardware.location.gps

子Feature,应用程序使用了从设备上的全球定位系统接收器中获取精确的坐标。

Microphone

android.hardware.microphone

应用程序要使用设备上的麦克风。

 

NFC

android.hardware.nfc

应用程序要使用设备中的NFC近距离无线通信功能。

 

Sensors

android.hardware.sensor.accelerometer

应用程序要使用设备上的加速度传感器的运动读数。

 

android.hardware.sensor.barometer

应用程序要使用设备的压力传感器。

 

android.hardware.sensor.compass

应用程序要使用设备上的磁极(罗盘)来读取方向读数。

 

android.hardware.sensor.gyroscope

应用程序要使用设备上的陀螺仪。

 

android.hardware.sensor.light

应用程序要使用设备的亮度传感器。

 

android.hardware.sensor.proximity

应用程序要使用设备的接近proximity传感器。

 

Screen

android.hardware.screen.landscape

应用程序需要横向屏幕

例如:如果应用程序需要纵向屏幕,就应该声明<uses-featureandroid:name="android.hardware.screen.portrait"/>,以便只有支持纵向的设备能够安装该应用程序。如果应用程序两个方向都支持,那么就不需要做任何声明。

默认情况下,这两个方向都被假定为不需要,因此应用程序可以安装在支持一个方向或两个方向都支持的设备上。然而,一旦应用程序使用android:screenOrientation属性,设定要运行在一个特定的设备上,就声明了应用程序需要screen方向的Feature。例如,如果用android:screenOrientation属性声明了"landscape","reverseLandscape", 或"sensorLandscape"值,那么应用程序只对支持横向屏幕的设备有效。最好的实践是,依然使用<uses-feature>元素声明一个方向的Feature请求。如果使用android:screenOrientation,属性给Activity声明了一个方向,但实际却不需要该Feature请求,那么就可以通过<uses-feature>元素并包含android:required="false"来禁止该Feature需求。

为了向后兼容,任何平台版本只支持APILevel 12或更低的的设备,都被假定为同时支持横向和纵向屏幕。

android.hardware.screen.portrait

应用程序需要纵向屏幕

Telephony

android.hardware.telephony

应用程序要使用设备设备上的电话Feature,如带有数据通信服务的无线电话。

 

android.hardware.telephony.cdma

子Feature,应用程序要使用设备上的CDMA无线电话功能

这些子Feature隐式的声明了android.hardware.telephony父Feature,除非该功能需求声明了android:required="false"属性。

android.hardware.telephony.gsm

子Feature,应用程序要使用设备上的GSM无线电话功能

Television

android.hardware.type.television

The application is designed for a television user experience.

This feature defines "television" to be a typicalliving room television experience: displayed on a big screen,where the user is sitting far away and the dominant form of inputis something like a d-pad, and generally not through touch or amouse/pointer-device.

Touchscreen

android.hardware.faketouch

应用程序要使用基本的触屏事件,如“clickdown”、“clickup”和“drag”

当应用程序声明了这个功能需求时,则表明该应用程序只能跟提供了模拟触屏(faketouch 接口)操作的设备兼容。提供faketouch接口的设备会给用户提供一种模拟触屏能力的输入系统。例如,驱动屏幕光标提供faketouch接口的鼠标或远程控制。如果应用程序需要基本的点和click交互(换句话说,只有一个方向板(d-pad),应用程序是不会工作的),就应该声明这个功能,因为这是触屏交互的最低级别,这样应用程序也会跟提供更复杂的触屏交互的设备兼容。

注意:默认情况下,因为应用程序需要android.hardware.touchscreenFeature,所以如果想要应用程序对提供了faketouch接口的设备有效,那么就必须通过声明<uses-featureandroid:name="android.hardware.touchscreen"android:required="false"/>,来明确的声明触屏不是必须的。

android.hardware.faketouch.multitouch.distinct

应用程序要在faketouch(假触屏)表面上执行区分两点以上触摸的轨迹的操作,这是faketouce功能的一个超集。

当应用程序声明了这个需求时,表明该应用程序只跟支持区分两点以上的模拟触屏事件的设备兼容。

跟通过android.hardware.touchscreen.multitouch.distinct定义的多点触控不同,支持在faketouch表面进行两点以上触控输入的设备,它不支持所有的双指手势,因为当前输入会被转换成平面上的光标移动。也就是说,在这样设备上的单指手势会移动光标,双指碰擦会导致单指的触屏事件;其他的双指手势会导致相应的双指触屏事件。例如:提供了移动光标的和多指触控的轨迹板,就是一种支持在faketouch表面执行区分多点触控的设备。

android.hardware.faketouch.multitouch.jazzhand

应用程序要在faketouch(假触屏)表面上执行区分五点以上触摸的轨迹的操作,这是faketouce功能的一个超集。

当应用程序声明这个功能需求时,表明该应用程序只会跟支持区分五点以上轨迹的模拟触屏设备兼容。

跟通过android.hardware.touchscreen.multitouch.jazzhand定义的多点触控不同,该功能定义的输入设备表面不会支持所有的五指手势,因为该输入会转换成屏幕上的光标移动。也就是说,单指手势会移动设备上的光标,多指触碰手势会导致一个单指触碰事件;其他的多指手势会导致相应的多指触碰事件。例如:提供了移动光标的和多指触控的轨迹板,就是一种支持在faketouch表面执行区分多点触控的设备。

android.hardware.touchscreen

应用程序要使用比基本的触屏事件还要多的手势交互功能,如,抛物手势。该功能是基本faketouch功能的一个超集。

默认情况下,应用程序需要这个功能。因此,默认情况下,应用程序对只提供模拟触摸屏(faketouch)的设备是无效的。如果想要应用程序对提供模拟触摸屏的设备有效,就必须明确的声明触摸屏不是必须的,声明方式如下:<uses-featurename=”android:hardware.touchscreen” android:required=”false”/>。即使应用程序不需要使用一个实际的触摸屏。

如果应用程序需要一个触摸屏(为了执行一些触碰手势),那么不需要做任何该功能的定义,因为默认这个功能是必须的。但是,最好还是明确的声明应用程序所要使用的全部功能,因此如果应用程序要使用该功能,依然还应该声明它。

如果需要更复杂的触摸交互,如多指手势,就应该声明下面的高级触屏功能。

android.hardware.touchscreen.multitouch

应用程序要使用多点触屏上的基本双点触摸功能,如掐捏手势,但不需要独立的轨迹跟踪。该功能是touchscreenFeature的一个超集。

声明该Feature,隐式的声明了android.hardware.touchscreen父Feature,除非该功能声明了android:required="false"属性。

android.hardware.touchscreen.multitouch.distinct

子Feature,应用程序要使用多点触屏设备的高级多点触摸功能,如两个以上完全独立的点的轨迹跟踪。它是multitouchFeature的子集。

声明该Feature,隐式的声明了android.hardware.touchscreen.multitouch父Feature,除非该功能声明了android:required="false"属性。

android.hardware.touchscreen.multitouch.jazzhand

该应用程序要使用多点触屏设备的多点触摸功能,如五个以上完全独立的点的轨迹跟踪。它是multitouchFeature的子集。

USB

android.hardware.usb.host

应用程序要使用USBHOST(主机)模式Feature(应用程序以主机的方式连接到USB设备上)

 

android.hardware.usb.accessory

应用程序要使用访问USB的Feature(应用程序以USB设备的方式连接到USBHOST/主机上)。

 

Wifi

android.hardware.wifi

应用程序使用设备上的802.11网络(wifi)Feature。

 

软件Feature列表

下表中列出了由当前大多数发布的Android平台所支持的软件Feature描述。对于应用程序要使用或需要的某一Feature,都要在应用程序的Manifest中的<uses-feature>元素中使用android:name属性来进行声明。



Feature

属性值

描述

注释

Live Wallpaper

android.software.live_wallpaper

应用程序使用或提供LiveWallpapers

 

SIP/VOIP

android.software.sip

应用程序使用SIP服务。

 

android.software.sip.voip

子Feature。应用程序要使用设备上的基于SIP的VOIP服务。

声明这个子Feature,隐式的声明了android.software.sip父Feature,除非声明该功能时也声明了android:required="false"。



隐式的Feature需求的权限

在上面列出的一些Feature常量中,要在相应的API发布之后,才对应用有效。例如,在Android2.2(APILevel 8)中添加了android.hardware.bluetooth功能常量,但是它所指向的蓝牙API是在Android2.0(APILevel5)中被添加的。正因为这样,某些应用能够在有能力通过<uses-feature>元素声明其所需的API功能之前,就能够使用这些API。

要防止无意间让某些功能对应用程序有效,GooglePlay会假定某些相关硬件的权限,来指定默认情况下所需要的底层硬件功能。例如,使用蓝牙功能的应用程序必须在<uses-permission>元素中申请BLUETOOTH权限,对于旧版应用程序,GooglePlay会假定权限的声明,意味着应用程序需要底层的android.hardware.bluetoothFeature,并且会基于该功能来过滤应用程序。

下表中列出的暗示功能需求的权限,等同于那些在<uses-feature>元素中声明的功能需求。要注意的是那些包含android:required属性的<uses-feature>声明,它的优先级要始终高于下表中隐式的的功能需求。

对于下表中的任何权限,都能够用带有android:required="false"属性的<uses-feature>元素来明确的禁止基于隐式功能的过滤。例如,要禁止基于CAMERA权限的任何过滤,可以在其清单文件中添加以下<uses-feature>元素的声明:

<uses-feature android:name="android.hardware.camera" android:required="false" />



分类

权限...

隐含的Feature需求

Bluetooth

BLUETOOTH

android.hardware.bluetooth

(详情参考Specialhandling for Bluetooth feature)

BLUETOOTH_ADMIN

android.hardware.bluetooth

Camera

CAMERA

android.hardware.camera and
android.hardware.camera.autofocus

Location

ACCESS_MOCK_LOCATION

android.hardware.location

ACCESS_LOCATION_EXTRA_COMMANDS

android.hardware.location

INSTALL_LOCATION_PROVIDER

android.hardware.location

ACCESS_COARSE_LOCATION

android.hardware.location.networkand
android.hardware.location

ACCESS_FINE_LOCATION

android.hardware.location.gps and
android.hardware.location

Microphone

RECORD_AUDIO

android.hardware.microphone

Telephony

CALL_PHONE

android.hardware.telephony

CALL_PRIVILEGED

android.hardware.telephony

MODIFY_PHONE_STATE

android.hardware.telephony

PROCESS_OUTGOING_CALLS

android.hardware.telephony

READ_SMS

android.hardware.telephony

RECEIVE_SMS

android.hardware.telephony

RECEIVE_MMS

android.hardware.telephony

RECEIVE_WAP_PUSH

android.hardware.telephony

SEND_SMS

android.hardware.telephony

WRITE_APN_SETTINGS

android.hardware.telephony

WRITE_SMS

android.hardware.telephony

Wifi

ACCESS_WIFI_STATE

android.hardware.wifi

CHANGE_WIFI_STATE

android.hardware.wifi

CHANGE_WIFI_MULTICAST_STATE

android.hardware.wifi




    
[3] Google Play跟基于Feature的过滤
    来源: 互联网  发布时间: 2014-02-18
Google Play和基于Feature的过滤

田海立@CSDN

翻译自Google Play and Feature-Based Filtering



GooglePlay会过滤出那些对用户可见的应用程序,因此用户只能看到和下载那些与他们的设备兼容的应用程序。过滤应用程序其中的一种方法就是通过Feature兼容性。

Google Play为判断应用程序与给定的用户设备是否兼容,比较:

  • 应用程序需要的Feature– 应用程序在它自己的manifest中通过<uses-feature>申明所需要的Feature;

  • 在设备上有效的硬/软件Feature-- 设备用只读的系统属性报告的它所支持的Feature。

为了确保Feature的准确比较,AndroidPackage Manager提供了一个共享的Feature常量集合,应用程序和设备都使用这些常量来声明各自所需要和支持的Feature。可用的Feature常量在本文下面的Feature参考表中被列出,它们定义在类文档PackageManager中。

当用户启动GooglePlay时,应用程序通过调用getSystemAvailableFeatures()方法,来查询包PackageManager中所列出的设备上可用的Featurelist。然后在建立用户会话的时候,软件商店(TheStore)应用程序会把这个Featurelist上传给GooglePlay。

每次把应用程序上传给GooglePlay的发布网站时,GooglePlay都会扫描应用程序的Manifest文件。它会查找Manifest中的<uses-feature>元素,并且在某些情况下,会把它们跟其他元素组合在一起来评估,如<uses-sdk>和<uses-permission>元素。在建立了应用程序所需的Feature集合之后,GooglePlay会把这个列表做为跟应用程序的.apk和版本相关联的内部元数据保存起来。

当用户使用GooglePlay应用程序查询或浏览应用商店里的应用程序时,服务就会把每个应用程序所需的Feature跟用户设备上可用的Feature进行比较。如果应用程序所需要的所有Feature在设备上都存在,那么GooglePlay就允许用户看到该应用程序,并潜在的可下载它。如果应用所需的任何一个Feature不被设备所支持,GooglePlay就过滤掉该应用程序,这样用户就看不到并且也不能够下载。

因为在<uses-feature>元素中声明的Feature直接影响到GooglePlay如何过滤应用程序,因此理解GooglePlay是如何评估应用程序的Manifest和建立需求Feature的集合是至关重要的,以下章节会详细说明。

基于明确声明Feature的过滤

一个明确声明的Feature就是应用程序声明的一个<uses-feature>元素。Feature声明可以包含一个android:required=["true"| "false"]的属性(如果在APILeve5或以上的版本上编译),这个属性指定了应用程序是否绝对的需要该Feature,如果目标设备上不存在该Feature,该应用程序就不能正常的运行("true"的场合),或指定应用程序偏好该Feature,在Feature有效的时候就使用该它,而在该Feature无效时,应用程序也被设计成也是可以运行的("false"的场合)。

Google Play用以下方法来处理明确声明的Feature:

  • 如果一个Feature被明确声明为必须的,那么GooglePlay就会把该Feature加入到该应用程序所需要的功能列表中。然后把应用程序从没有提供该应用所需Feature的设备中过滤掉。例如:

    <uses-feature android:name="android.hardware.camera" android:required="true" />
  • 如果一个Feature被明确声明为非必须的,GooglePlay就不会把这个的Feature添加到所需的Feature列表中。由于这个原因,明确声明的非必须的Feature,在GooglePlay过滤应用程序时就不会被考虑。即使设备不声明提供该Feature,GooglePlay依然会认为该应用程序与设备是兼容的,并允许显示给用户,除非使用了其他过滤规则。例如:

    <uses-feature android:name="android.hardware.camera" android:required="false" />
  • 如果一个Feature被明确声明,但没有设置android:required属性,那么GooglePlay就会假定该功能是必须的,并且要针对该功能进行过滤。(译者注:缺省是true)

通常,如果应用程序被设计成要运行在Android1.6或更早的版本上,那么在API中android:required属性是无效的,并且GooglePlay会假定<uses-feature>的申明都是必须的。

注意:通过明确声明一个Feature,并且包含android:required=”false”的属性,能够禁止GooglePlay针对该Feature的所有过滤。

基于隐式Feature的过滤

一个隐式的Feature是为了让应用程序正确运行所需的功能,但是,这个Feature并不在申明在Manifest的<uses-feature>元素中。严格来说,每个应用程序都应该始终声明它所使用和需要的所有Feature,因此对于应用程序使用的Feature,却没有声明,应该被认为是一个错误。但是,出于对用户和开发者的保护,GooglePlay会查看每个应用程序的隐式Feature,并基于这些Feature来建立过滤器,就像是对明确声明的Feature所做的处理一样。

应用程序可能需要一个Feature,但却没有声明,这是因为:

  • 应用程序是针对较旧的Android类库版本(Android1.5或更早)来编译的,当时<uses-feature>元素还是无效的;

  • 开发者错误的假定所需要的Feature在所有的设备上都存在,而认为没有必要声明;

  • 开发者不小心忽略的该Feature的声明;

  • 开发者明确的声明了该Feature,但该声明是无效的。例如:<uses-feature>元素名的一个拼写错误或给android:name属性设定一个无法识别的字符串,这些都会导致Feature声明的无效。

To account for the cases above, Google Play attempts to discoveran application's implied feature requirements by examining otherelements declared in the manifest file, specifically,<uses-permission>elements.基于以上原因的考虑,GooglePlay会尝试通过检查Manifest文件中其他元素(特别是<uses-permission>元素)的声明来发现被应用隐式需要的Feature。

如果一个应用程序申请了硬件相关的权限,那么GooglePlay就会假定应用程序要使用底层的硬件Feature,并因此而需要那些Feature,即使可能没有相应的<uses-feature>声明。针对这样的权限申请,GooglePlay也会把底层的硬件Feature添加到它所保持的对应的应用程序的元数据中,并基于这些信息来建立相应的过滤器。

例如,如果应用程序申请了CAMERA权限,但却没有声明一个<uses-feature>元素要求android.hardware.cameraFeature,那么GooglePlay就会认为应用程序需要照相机,并且该应用程序不应该显示给没有提供照相机功能的那些用户设备。

如果不想要GooglePlay基于某个特殊的隐式Feature来过滤应用程序,就要禁止这种行为。通过在<uses-feature>元素中明确的声明Feature,并包含一个android:required="false"属性,可以达到禁止GooglePlay过滤应用程序的目的。例如:要禁止由CAMERA权限所派生出来的过滤,就要像下面这样声明Feature:

<uses-feature android:name="android.hardware.camera" android:required="false" />

理解用<uses-permission>元素声明的权限能够直接影响GooglePlay对应用程序的过滤是至关重要的。在下面的权限隐含的Feature需求章节中,列出了所有的隐含的Feature需求的权限集,并因此而引发的过滤处理。

对于蓝牙Feature的特殊处理

当GooglePlay针对蓝牙功能来判断过滤时,它会使用比以上描述稍微不同的规则。

如果应用程序在其清单的一个<uses-permission>元素中声明了一个蓝牙权限,但没有明确的在<uses-feature>>元素中声明蓝牙Feature,那么GooglePlay会检查应用程序被设计成要运行在Android平台的哪个版本上,这个版本是在<uses-sdk>元素中被指定的。

如下表所示,GooglePlay只会在应用程序把Android2.0(APILeve5)或更高的版本作为最低版本或目标平台时,才会启用针对蓝牙功能的过滤。但是,要注意的是,当应用程序在<uses-feature>元素中明确声明了蓝牙Feature时,GooglePlay会使用普通的规则来进行过滤处理。

表1:GooglePlay如何判断申请了蓝牙权限但却没有在<uses-feature>元素中声明蓝牙Feature的应用程序的蓝牙Feature需求的:

如果minSdkVersion

或targetSdkVersion

结果

<=4 (或者uses-sdk没被申明)

<=4

对于任何报告其支持android.hardware.bluetoothFeature的设备,GooglePlay不会把应用程序过滤掉。

<=4

>=5

对于任何不支持android.hardware.bluetooth Feature的设备,GooglePlay都会把该应用程序过滤掉。

>=5

>=5

以下的例子,基于GooglePlay如何处理蓝牙Feature,演示了不同的过滤效果。

第一个例子中,应用程序被设计成要运行在比较旧的APILevel上并声明了蓝牙权限,但是它没有在其<uses-feature>元素中声明蓝牙Feature。结果:GooglePlay不会把该应用程序从任何设备上过滤掉。
<manifest ...>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-sdk android:minSdkVersion="3" />
    ...
</manifest>
第二个例子,相同的应用程序,还声明了一个目标APILevel是5的属性。结果:GooglePlay会假设应用程序需要蓝牙Feature,并把应用程序从那些没有报告支持蓝牙功能的设备上过滤掉,包括那些运行较旧平台版本的的设备。
<manifest ...>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" />
    ...
</manifest>
这里,相同的应用程序,但声明的蓝牙Feature需求。结果:与第二个例子相同(过滤被应用)。
<manifest ...>
    <uses-feature android:name="android.hardware.bluetooth" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" />
    ...
</manifest>
最后,上面的例子中,相同的应用程序,但添加了android:required="false"属性。结果:GooglePlay会针对所有设备禁止使用基于蓝牙Feature支持的过滤。
<manifest ...>
    <uses-feature android:name="android.hardware.bluetooth" android:required="false" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="5" />
    ...
</manifest>
测试应用程序所需要的Feature

可以使用包含在AndroidSDK中的aapt工具,来判断GooglePlay会怎样过滤自己的应用程序(基于应用声明的Feature和Permission/权限)。用dump badging 命令来运行aapt工具,执行该项测试工作。aapt工具会解析应用程序的Manifest文件,并且使用与GooglPlay相同的规则,来判断应用程序所申请的Feature。

以下是使用这个工具的步骤:

  • 首先,把应用程序作为一个未签名的..apk来编译并导出。如果使用带有ADT的Eclipse来开发应用程序,那么右击工程,并选择AndroidTools > Export Unsigned ApplicationPackage。选择目标文件名和路径,点击OK按钮。

  • 接下来,如果在环境变量PATH中没有设置aapt的路径,定位找到它。如果使用的是SDK Toolsr8或更高的版本,那么可以在<SDK>/platform-tools/目录中找到aapt。

    注意:所使用的aapt工具版本必须是提供给最新的可用的平台工具组件。如果没有,使用AndroidSDK Manager 来下载。

  • 使用以下语法来运行aapt:

  • $ aapt dump badging <path_to_exported_.apk>

    以下例子是针对上面第二个蓝牙的例子的命令输出:

    $ ./aapt dump badging BTExample.apk
    package: name='com.example.android.btexample' versionCode='' versionName=''
    uses-permission:'android.permission.BLUETOOTH_ADMIN'
    uses-feature:'android.hardware.bluetooth'
    sdkVersion:'3'
    targetSdkVersion:'5'
    application: label='BT Example' icon='res/drawable/app_bt_ex.png'
    launchable activity name='com.example.android.btexample.MyActivity'label='' icon=''
    uses-feature:'android.hardware.touchscreen'
    main
    supports-screens: 'small' 'normal' 'large'
    locales: '--_--'
    densities: '160'


        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3