标签: 版本更新

Android Things APP版本更新的解决方案

Android Things中如果使用传统的Intent来安装APK,你将永远安装不上

常见的应用内APK安装方法有以下两种方法

1.Intent安装APK的方法如下:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + “.fileProvider”, new File(path + “app-debug.apk”));
intent.setDataAndType(contentUri, “application/vnd.android.package-archive”);
startActivity(intent);

同时添加权限:

<uses-permission android:name=”android.permission.REQUEST_INSTALL_PACKAGES”/>
2.通过install命令来安装

命令如下:

pm install -i 当前包名 –user 0 XX.apk
运行方法:

Runtime.getRuntime().exec(“”)
注意:以上两种方法在android 手机中没有问题,但截止目前在Android Things 1.0.1中是行不通的

为了能在Android Things系统中更新APP,故经过不断的探索发现,*终采用插件化的方案来解决此问题

%title插图%num
经过评估测试,*终发现360出品的RePlugin框架满足我们的需求

https://github.com/Qihoo360/RePlugin

在RePlugin壳子中,必须申请完所有权限,因为壳子是不会更新的。我整理了所有的权限,在下面列出来

<!–Android Things所有权限–>
<uses-permission android:name=”com.google.android.things.permission.MANAGE_BLUETOOTH” />
<uses-permission android:name=”com.google.android.things.permission.PERFORM_UPDATE_NOW” />
<uses-permission android:name=”com.google.android.things.permission.USE_PERIPHERAL_IO” />
<uses-permission android:name=”com.google.android.things.permission.SET_TIME” />
<uses-permission android:name=”com.google.android.things.permission.REBOOT” />

<!–Android所有权限–>
<uses-permission android:name=”andriod.permission.ACCESS_CHECKIN_PROPERTIES”></uses-permission>
<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION” />
<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”/>
<uses-permission android:name=”android.permission.ACCESS_LOCATION_EXTRA_COMMANDS”/>
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE”/>
<uses-permission android:name=”android.permission.ACCESS_NOTIFICATION_POLICY”/>
<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE”/>
<uses-permission android:name=”android.permission.ADD_VOICEMAIL”/>
<uses-permission android:name=”android.permission.BLUETOOTH”/>
<uses-permission android:name=”android.permission.BLUETOOTH_ADMIN”/>
<uses-permission android:name=”android.permission.BODY_SENSORS”/>
<uses-permission android:name=”android.permission.BROADCAST_STICKY”/>
<uses-permission android:name=”android.permission.CALL_PHONE”/>
<uses-permission android:name=”android.permission.CAMERA”/>
<uses-permission android:name=”android.permission.CHANGE_NETWORK_STATE”/>
<uses-permission android:name=”android.permission.CHANGE_WIFI_MULTICAST_STATE”/>
<uses-permission android:name=”android.permission.CHANGE_WIFI_STATE”/>
<uses-permission android:name=”android.permission.DISABLE_KEYGUARD”></uses-permission>
<uses-permission android:name=”android.permission.EXPAND_STATUS_BAR”></uses-permission>
<uses-permission android:name=”android.permission.GET_ACCOUNTS”/>
<uses-permission android:name=”android.permission.GET_PACKAGE_SIZE”/>
<uses-permission android:name=”android.permission.GET_TASKS”/>
<uses-permission android:name=”android.permission.INSTALL_SHORTCUT”/>
<uses-permission android:name=”android.permission.INTERNET”/>
<uses-permission android:name=”android.permission.KILL_BACKGROUND_PROCESSES”/>
<uses-permission android:name=”android.permission.MODIFY_AUDIO_SETTINGS”/>
<uses-permission android:name=”android.permission.NFC”></uses-permission>
<uses-permission android:name=”android.permission.PERSISTENT_ACTIVITY”></uses-permission>
<uses-permission android:name=”android.permission.PROCESS_OUTGOING_CALLS”></uses-permission>
<uses-permission android:name=”android.permission.READ_CALENDAR”/>
<uses-permission android:name=”android.permission.READ_CALL_LOG”/>
<uses-permission android:name=”android.permission.READ_CONTACTS”/>
<uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE”/>
<uses-permission android:name=”android.permission.READ_PHONE_STATE”/>
<uses-permission android:name=”android.permission.READ_SMS”/>
<uses-permission android:name=”android.permission.READ_SYNC_SETTINGS”/>
<uses-permission android:name=”android.permission.READ_SYNC_STATS”/>
<uses-permission android:name=”android.permission.READ_VOICEMAIL”/>
<uses-permission android:name=”android.permission.RECEIVE_BOOT_COMPLETED”/>
<uses-permission android:name=”android.permission.RECEIVE_MMS”/>
<uses-permission android:name=”android.permission.RECEIVE_SMS”/>
<uses-permission android:name=”android.permission.RECEIVE_WAP_PUSH”/>
<uses-permission android:name=”android.permission.RECORD_AUDIO”/>
<uses-permission android:name=”android.permission.REORDER_TASKS”/>
<uses-permission android:name=”android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS”/>
<uses-permission android:name=”android.permission.REQUEST_INSTALL_PACKAGES”/>
<uses-permission android:name=”android.permission.RESTART_PACKAGES”/>
<uses-permission android:name=”android.permission.SEND_SMS”/>
<uses-permission android:name=”android.permission.SET_ALARM”/>
<uses-permission android:name=”android.permission.SET_WALLPAPER”/>
<uses-permission android:name=”android.permission.SET_WALLPAPER_HINTS”/>
<uses-permission android:name=”android.permission.SYSTEM_ALERT_WINDOW”/>
<uses-permission android:name=”android.permission.TRANSMIT_IR”/>
<uses-permission android:name=”android.permission.UNINSTALL_SHORTCUT”/>
<uses-permission android:name=”android.permission.USE_FINGERPRINT”/>
<uses-permission android:name=”android.permission.USE_SIP”/>
<uses-permission android:name=”android.permission.VIBRATE”/>
<uses-permission android:name=”android.permission.WAKE_LOCK”/>
<uses-permission android:name=”android.permission.WRITE_CALENDAR”/>
<uses-permission android:name=”android.permission.WRITE_CALL_LOG”/>
<uses-permission android:name=”android.permission.WRITE_CONTACTS”/>
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>
<uses-permission android:name=”android.permission.WRITE_SYNC_SETTINGS”/>
<uses-permission android:name=”android.permission.WRITE_VOICEMAIL”/>

<!–所有系统权限–>
<uses-permission android:name=”android.permission.ACCOUNT_MANAGER”/>
<uses-permission android:name=”android.permission.BATTERY_STATS”/>
<uses-permission android:name=”android.permission.BIND_ACCESSIBILITY_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_CARRIER_MESSAGING_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_CARRIER_SERVICES”/>
<uses-permission android:name=”android.permission.BIND_CHOOSER_TARGET_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_DEVICE_ADMIN”/>
<uses-permission android:name=”android.permission.BIND_CONDITION_PROVIDER_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_DREAM_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_INCALL_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_INPUT_METHOD”/>
<uses-permission android:name=”android.permission.BIND_MIDI_DEVICE_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_NFC_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_NOTIFICATION_LISTENER_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_PRINT_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_QUICK_SETTINGS_TILE”/>
<uses-permission android:name=”android.permission.BIND_REMOTEVIEWS”/>
<uses-permission android:name=”android.permission.BIND_SCREENING_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_TELECOM_CONNECTION_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_TEXT_SERVICE”></uses-permission>
<uses-permission android:name=”android.permission.BIND_TV_INPUT”></uses-permission>
<uses-permission android:name=”android.permission.BIND_VOICE_INTERACTION”></uses-permission>
<uses-permission android:name=”android.permission.BIND_*_SERVICE”></uses-permission>
<uses-permission android:name=”android.permission.BIND_VR_LISTENER_SERVICE”/>
<uses-permission android:name=”android.permission.BIND_WALLPAPER”/>
<uses-permission android:name=”android.permission.BLUETOOTH_PRIVILEGED”/>
<uses-permission android:name=”android.permission.BROADCAST_PACKAGE_REMOVED”/>
<uses-permission android:name=”android.permission.BROADCAST_SMS”/>
<uses-permission android:name=”android.permission.BROADCAST_WAP_PUSH”/>
<uses-permission android:name=”android.permission.CALL_PRIVILEGED”/>
<uses-permission android:name=”android.permission.CAPTURE_AUDIO_OUTPUT”/>
<uses-permission android:name=”android.permission.CAPTURE_SECURE_VIDEO_OUTPUT”/>
<uses-permission android:name=”android.permission.CAPTURE_VIDEO_OUTPUT”/>
<uses-permission android:name=”android.permission.CHANGE_COMPONENT_ENABLED_STATE”/>
<uses-permission android:name=”android.permission.CHANGE_CONFIGURATION”/>
<uses-permission android:name=”android.permission.CLEAR_APP_CACHE”/>
<uses-permission android:name=”android.permission.CONTROL_LOCATION_UPDATES”/>
<uses-permission android:name=”android.permission.DELETE_CACHE_FILES”/>
<uses-permission android:name=”android.permission.DELETE_PACKAGES”/>
<uses-permission android:name=”android.permission.DIAGNOSTIC”/>
<uses-permission android:name=”android.permission.DUMP”></uses-permission>
<uses-permission android:name=”android.permission.FACTORY_TEST”></uses-permission>
<uses-permission android:name=”android.permission.GET_ACCOUNTS_PRIVILEGED”/>
<uses-permission android:name=”android.permission.GLOBAL_SEARCH”/>
<uses-permission android:name=”android.permission.INSTALL_LOCATION_PROVIDER”/>
<uses-permission android:name=”android.permission.INSTALL_PACKAGES”/>
<uses-permission android:name=”android.permission.LOCATION_HARDWARE”/>
<uses-permission android:name=”android.permission.MANAGE_DOCUMENTS”/>
<uses-permission android:name=”android.permission.MASTER_CLEAR”/>
<uses-permission android:name=”android.permission.MEDIA_CONTENT_CONTROL”/>
<uses-permission android:name=”android.permission.MODIFY_PHONE_STATE”/>
<uses-permission android:name=”android.permission.MOUNT_FORMAT_FILESYSTEMS”/>
<uses-permission android:name=”android.permission.MOUNT_UNMOUNT_FILESYSTEMS”/>
<uses-permission android:name=”android.permission.PACKAGE_USAGE_STATS”></uses-permission>
<uses-permission android:name=”android.permission.READ_FRAME_BUFFER”/>
<uses-permission android:name=”android.permission.READ_INPUT_STATE”/>
<uses-permission android:name=”android.permission.READ_LOGS”/>
<uses-permission android:name=”android.permission.REBOOT”/>
<uses-permission android:name=”android.permission.SEND_RESPOND_VIA_MESSAGE”/>
<uses-permission android:name=”android.permission.SET_ALWAYS_FINISH”/>
<uses-permission android:name=”android.permission.SET_ANIMATION_SCALE”/>
<uses-permission android:name=”android.permission.SET_DEBUG_APP”/>
<uses-permission android:name=”android.permission.SET_PREFERRED_APPLICATIONS”></uses-permission>
<uses-permission android:name=”android.permission.SET_PROCESS_LIMIT”></uses-permission>
<uses-permission android:name=”android.permission.SET_TIME”></uses-permission>
<uses-permission android:name=”android.permission.SET_TIME_ZONE”></uses-permission>
<uses-permission android:name=”android.permission.SIGNAL_PERSISTENT_PROCESSES”/>
<uses-permission android:name=”android.permission.STATUS_BAR”/>
<uses-permission android:name=”android.permission.UPDATE_DEVICE_STATS”/>
<uses-permission android:name=”android.permission.WRITE_APN_SETTINGS”/>
<uses-permission android:name=”android.permission.WRITE_GSERVICES”/>
<uses-permission android:name=”android.permission.WRITE_SECURE_SETTINGS”/>
<uses-permission android:name=”android.permission.WRITE_SETTINGS”/>
但是,光这些还不够,还需要解决两个坑

1.关于FileProvider的问题

我们需要提前在RePlugin中申请注册,Replugin是不会动态申请FileProvider

所以,需要在宿主程序中添加:

<provider
android:name=”android.support.v4.content.FileProvider”
android:authorities=”宿主包名.fileProvider”
android:exported=”false”
android:grantUriPermissions=”true”>
<meta-data
android:name=”android.support.FILE_PROVIDER_PATHS”
android:resource=”@xml/file_paths” />
</provider>
注意一点:此处填写宿主包名,当我们在插件中使用context.getPackageName()的时候,拿到的是宿主包名

2.在Android Things中APP默认是横屏,但当我们加载打开插件时,会发现APP被强制改为了竖屏

在这里,尝试反编译宿主APK,打开AndroidManifest文件后,发现screenOrientation的值为1,故RePlugin框架默认是将所有的Activity坑位默认设置的portrait竖屏

<activity
android:theme=”@ref/0x01030006″
android:name=”com.xx.a.ActivityP2NRNTS1″
android:exported=”false”
android:process=”:p2″
android:screenOrientation=”1″
android:configChanges=”0x4b0″ />
解决方案如下,修改RePlugin源码,找到replugin-host-gradle源码,修改ComponentsGenerator类,添加oriL变量,然后将所有的oriV改为oriL

 

iOS App版本更新

版本更新的方式:
可选更新:弹框时有取消和更新两个按钮,用户可以选择取消按钮(增加新的功能,改善用户的体验等,这种更新不会影响软件的正常的使用)
强制更新:弹框时只有一个更新按钮,用户没得选择,必须更新(系统重大漏洞,严重影响用户正常使用等必须强制用户更新,不更新就不能使用该软件)
解决方案:
方案一:
调用服务器接口获取App的版本号,如果服务器的版本号大于当前App的版本号,那么则弹框提示更新,否则就不提示
1
方案二:
获取App Store 上的应用的版本号,如果App Store 上的版本号大于当前App的版本号,那么则弹框提示更新,否则就不提示
1
两种方案比较:
方式二是调用App Store对应的接口,由于App Store服务器在外国,可能请求比较慢或者连接失败,网络不稳定;再者这种方式不能确定该版本是否是强制更新类型的;还有该方式只能用于iOS, 这让Android怎么办?这种方式唯一的优点就是可以App审核通过后,用户能在*时间进行更新

方式一是调用自己应用的服务器,网速稳定,比较灵活,可以在接口中任意定义字段如*新版本号、是否强制更新isForceUpdate 等参数;因App Store 审核需要2-3天时间,不能及时知道什么时候审核通过,可能会出现审核通过了,开发人员还不知道,这段时间获取应用的版本信息接口可能版本号还是老的,这段时间还不能更新,没有达到*时间就能更新的效果

方法一:获取自己服务器版本号检查
1. 通过网络请求获取服务器上的版本号;
2. 获取当前应用版本号;
3. 将版本号转换为整形进行比较;
4. 如果有版本更新则跳转到app store上下载。

方法二:获取app store上架版本号检查
1. 通过网络同步请求获取app store上对应APP ID的应用信息;
2. 提取信息上的*新版本号和下载地址;
3. 获取当前应用版本号;
4. 将版本号转换成双精度型进行比较;
5. 对于有两个点的版本号的*后一个点不处理。

iTunes Search API 查询应用程序信息,包括作者,版本,app 介绍页面地址等信息
iTunes Search API

获取App Store中的应用信息接口
方式一:通过APPId查询: https://itunes.apple.com/lookup?id=xxx
方式二:通过bundleId查询: http://itunes.apple.com/lookup?bundleId=xxx

App有两个版本号,一个是Version,另一个是Build,对应于Info.plist的字段名分别为CFBundleShortVersionString,CFBundleVersion。 AppSotre默认取的是Version即CFBundleShortVersionString

方式二代码示例:
#import “AppDelegate.h”
#import <AFNetworking.h>
@interface AppDelegate () <UIAlertViewDelegate>

@property (strong, nonatomic) NSString *trackViewUrl;
@end

@implementation AppDelegate
– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
NSString *APPID = @”123456789″;
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:@”https://itunes.apple.com/lookup” parameters:@{@”id”: APPID} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseObject) {
/*
results:[
{
trackViewUrl = “https://itunes.apple.com/us/app/xxx/id123456789?mt=8&uo=4”;
version = “1.7.4”
}
]*/
NSLog(@”%@”, responseObject);
NSArray *results = responseObject[@”results”];
NSString *version = [[results objectAtIndex:0] objectForKey:@”version”];
self.trackViewUrl = [[results objectAtIndex:0] objectForKey:@”trackViewUrl”];

NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
float shortVersion = [infoDict[@”CFBundleShortVersionString”] floatValue];

if ([version floatValue] > shortVersion) {
NSString * title = [NSString stringWithFormat:@”检查更新: %@”, @”应用名称”];
NSString * message = [NSString stringWithFormat:@”发现新版本(%@), 是否升级 ?”, version];

UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:@”取消” otherButtonTitles:@”升级”, nil];
[alertView show];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

}];

self.window.rootViewController = [[UIViewController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}

– (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
NSURL *trackViewUrl = [NSURL URLWithString:self.trackViewUrl];
UIApplication *application = [UIApplication sharedApplication];
if ([application canOpenURL:trackViewUrl]) {
[application openURL:trackViewUrl];
}
}
}

方式一的代码和方式二差不多,只不过是请求自己应用的服务器接口,然后解析

第三方实现
第三方实现的思路一般都是上面的思路,只不过对上述代码进行封装了,比如如果将appId作为参数或者直接获取应用的bundleId,对于UIAlertView的title,message,buttonTitle作为参数提取出来,提供更简洁的方法来使用。

https://github.com/emotality/ATAppUpdate 只需要一行代码就能集成版本更新

实现逻辑是根据Bundle Identifier 去查找应用信息的

– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ATAppUpdater *updater = [ATAppUpdater sharedUpdater];
updater.alertTitle = @”版本升级”;
updater.alertMessage = @”*新版本位为:%@ “;
updater.alertCancelButtonTitle = @”暂不更新”;
updater.alertUpdateButtonTitle = @”马上更新”;
[updater showUpdateWithConfirmation];

return YES;
}

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速