Skip to content

Commit 9267dc9

Browse files
committed
Speed up android livesync
1 parent 3a783e1 commit 9267dc9

File tree

7 files changed

+107
-14
lines changed

7 files changed

+107
-14
lines changed

lib/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const CONFIG_NS_APP_RESOURCES_ENTRY = "appResourcesPath";
3939
export const CONFIG_NS_APP_ENTRY = "appPath";
4040
export const DEPENDENCIES_JSON_NAME = "dependencies.json";
4141
export const APK_EXTENSION_NAME = ".apk";
42+
export const HASHES_FILE_NAME = ".nshashes";
4243

4344
export class PackageVersion {
4445
static NEXT = "next";
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
interface IFilesHashService {
22
generateHashes(files: string[]): Promise<IStringDictionary>;
3+
/**
4+
* Generate hashes for all prepared files (all files from app folder under platforms folder).
5+
* @param platformData - Current platform's data
6+
* @returns {Promise<IStringDictionary>}
7+
* A map with key file's path and value - file's hash
8+
*/
9+
generateHashesForProject(platformData: IPlatformData): Promise<IStringDictionary>;
10+
/**
11+
* @param hashesFileDirectory - Path to directory containing the hash file.
12+
* @returns {IStringDictionary}
13+
* In case .nshashes file exists (under `hashesFileDirectory` directory), returns its content
14+
* In case .nshashes file does not exist (under `hashesFileDirectory` directory), returns {}
15+
*/
16+
getGeneratedHashes(hashesFileDirectory: string): IStringDictionary;
17+
/**
18+
* Generates hashes for all prepared files (all files from app folder under platforms folder)
19+
* and saves them in .nshashes file under `hashFileDirectory` directory.
20+
* @param platformData - Current platform's data
21+
* @param hashesFileDirectory - Path to directory containing the hash file.
22+
* @returns {Promise<void>}
23+
*/
24+
saveHashesForProject(platformData: IPlatformData, hashesFileDirectory: string): Promise<void>;
325
getChanges(files: string[], oldHashes: IStringDictionary): Promise<IStringDictionary>;
426
hasChangesInShasums(oldHashes: IStringDictionary, newHashes: IStringDictionary): boolean;
527
}

lib/services/android-project-service.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
3030
private $npm: INodePackageManager,
3131
private $androidPluginBuildService: IAndroidPluginBuildService,
3232
private $platformEnvironmentRequirements: IPlatformEnvironmentRequirements,
33-
private $androidResourcesMigrationService: IAndroidResourcesMigrationService) {
33+
private $androidResourcesMigrationService: IAndroidResourcesMigrationService,
34+
private $filesHashService: IFilesHashService) {
3435
super($fs, $projectDataService);
3536
this.isAndroidStudioTemplate = false;
3637
}
@@ -340,6 +341,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
340341
message: "Gradle build..."
341342
})
342343
);
344+
345+
await this.$filesHashService.saveHashesForProject(this._platformData, this._platformData.deviceBuildOutputPath);
343346
}
344347

345348
private getGradleBuildOptions(settings: IAndroidBuildOptionsSettings, projectData: IProjectData): Array<string> {

lib/services/files-hash-service.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { executeActionByChunks } from "../common/helpers";
22
import { DEFAULT_CHUNK_SIZE } from "../common/constants";
3+
import { APP_FOLDER_NAME, HASHES_FILE_NAME } from "../constants";
4+
import * as path from "path";
35

46
export class FilesHashService implements IFilesHashService {
57
constructor(private $fs: IFileSystem,
@@ -24,6 +26,29 @@ export class FilesHashService implements IFilesHashService {
2426
return result;
2527
}
2628

29+
public async generateHashesForProject(platformData: IPlatformData): Promise<IStringDictionary> {
30+
const appFilesPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME);
31+
const files = this.$fs.enumerateFilesInDirectorySync(appFilesPath);
32+
const hashes = await this.generateHashes(files);
33+
return hashes;
34+
}
35+
36+
public async saveHashesForProject(platformData: IPlatformData, hashesFileDirectory: string): Promise<void> {
37+
const hashes = await this.generateHashesForProject(platformData);
38+
const hashesFilePath = path.join(hashesFileDirectory, HASHES_FILE_NAME);
39+
this.$fs.writeJson(hashesFilePath, hashes);
40+
}
41+
42+
public getGeneratedHashes(hashesFileDirectory: string): IStringDictionary {
43+
let result = {};
44+
const hashesFilePath = path.join(hashesFileDirectory, HASHES_FILE_NAME);
45+
if (this.$fs.exists(hashesFilePath)) {
46+
result = this.$fs.readJson(hashesFilePath);
47+
}
48+
49+
return result;
50+
}
51+
2752
public async getChanges(files: string[], oldHashes: IStringDictionary): Promise<IStringDictionary> {
2853
const newHashes = await this.generateHashes(files);
2954
return this.getChangesInShasums(oldHashes, newHashes);

lib/services/livesync/android-device-livesync-sockets-service.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa
117117
return transferredFiles;
118118
}
119119

120+
public getDeviceHashService(appIdentifier: string): Mobile.IAndroidDeviceHashService {
121+
const adb = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: this.device.deviceInfo.identifier });
122+
return this.$injector.resolve(AndroidDeviceHashService, { adb, appIdentifier });
123+
}
124+
120125
private async _transferFiles(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[]): Promise<Mobile.ILocalToDevicePathData[]> {
121126
await this.livesyncTool.sendFiles(localToDevicePaths.map(localToDevicePathData => localToDevicePathData.getLocalPath()));
122127

@@ -132,19 +137,24 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa
132137
private async _transferDirectory(deviceAppData: Mobile.IDeviceAppData, localToDevicePaths: Mobile.ILocalToDevicePathData[], projectFilesPath: string): Promise<Mobile.ILocalToDevicePathData[]> {
133138
let transferredLocalToDevicePaths: Mobile.ILocalToDevicePathData[];
134139
const deviceHashService = this.getDeviceHashService(deviceAppData.appIdentifier);
135-
const currentShasums: IStringDictionary = await deviceHashService.generateHashesFromLocalToDevicePaths(localToDevicePaths);
136-
const oldShasums = await deviceHashService.getShasumsFromDevice();
140+
const currentHashes = await deviceHashService.generateHashesFromLocalToDevicePaths(localToDevicePaths);
141+
const oldHashes = await deviceHashService.getShasumsFromDevice();
142+
console.log("!!!!! OLD HASHES!!!!!!");
143+
console.log(oldHashes);
137144

138-
if (this.$options.force || !oldShasums) {
145+
if (this.$options.force || !oldHashes) {
146+
console.log("!!!!!!!!! NO OLD HASHES!!!!! THIS SHOULD NOT HAPPEN!!!!!!!");
139147
await this.livesyncTool.sendDirectory(projectFilesPath);
140-
await deviceHashService.uploadHashFileToDevice(currentShasums);
148+
await deviceHashService.uploadHashFileToDevice(currentHashes);
141149
transferredLocalToDevicePaths = localToDevicePaths;
142150
} else {
143-
const changedShasums = deviceHashService.getChangedShasums(oldShasums, currentShasums);
151+
const changedShasums = deviceHashService.getChangedShasums(oldHashes, currentHashes);
152+
console.log("CHANGEDSHASUMS!!!!!!!!!!!!!!!");
153+
console.log(changedShasums);
144154
const changedFiles = _.keys(changedShasums);
145155
if (changedFiles.length) {
146156
await this.livesyncTool.sendFiles(changedFiles);
147-
await deviceHashService.uploadHashFileToDevice(currentShasums);
157+
await deviceHashService.uploadHashFileToDevice(currentHashes);
148158
transferredLocalToDevicePaths = localToDevicePaths.filter(localToDevicePathData => changedFiles.indexOf(localToDevicePathData.getLocalPath()) >= 0);
149159
} else {
150160
transferredLocalToDevicePaths = [];
@@ -165,9 +175,4 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa
165175
});
166176
}
167177
}
168-
169-
public getDeviceHashService(appIdentifier: string): Mobile.IAndroidDeviceHashService {
170-
const adb = this.$injector.resolve(DeviceAndroidDebugBridge, { identifier: this.device.deviceInfo.identifier });
171-
return this.$injector.resolve(AndroidDeviceHashService, { adb, appIdentifier });
172-
}
173178
}

lib/services/platform-service.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ export class PlatformService extends EventEmitter implements IPlatformService {
4141
private $projectChangesService: IProjectChangesService,
4242
private $analyticsService: IAnalyticsService,
4343
private $terminalSpinnerService: ITerminalSpinnerService,
44-
private $pacoteService: IPacoteService
44+
private $pacoteService: IPacoteService,
45+
private $filesHashService: IFilesHashService
4546
) {
4647
super();
4748
}
@@ -488,8 +489,18 @@ export class PlatformService extends EventEmitter implements IPlatformService {
488489

489490
await platformData.platformProjectService.cleanDeviceTempFolder(device.deviceInfo.identifier, projectData);
490491

492+
const isApplicationInstalled = await this.isApplicationInstalled(device, projectData);
493+
491494
await device.applicationManager.reinstallApplication(projectData.projectId, packageFile);
492495

496+
await this.updateHashesOnDevice({
497+
device,
498+
isApplicationInstalled,
499+
appIdentifier: projectData.projectId,
500+
outputFilePath,
501+
platformData
502+
});
503+
493504
if (!buildConfig.release) {
494505
const deviceFilePath = await this.getDeviceBuildInfoFilePath(device, projectData);
495506
const options = buildConfig;
@@ -503,6 +514,32 @@ export class PlatformService extends EventEmitter implements IPlatformService {
503514
this.$logger.out(`Successfully installed on device with identifier '${device.deviceInfo.identifier}'.`);
504515
}
505516

517+
private async updateHashesOnDevice(data: { device: Mobile.IDevice, isApplicationInstalled: boolean, appIdentifier: string, outputFilePath: string, platformData: IPlatformData }): Promise<void> {
518+
const { device, isApplicationInstalled, appIdentifier, platformData, outputFilePath } = data;
519+
520+
if (!this.$mobileHelper.isAndroidPlatform(platformData.normalizedPlatformName)) {
521+
return;
522+
}
523+
524+
let hashes = null;
525+
if (isApplicationInstalled) {
526+
hashes = await this.$filesHashService.generateHashesForProject(platformData);
527+
} else {
528+
hashes = this.$filesHashService.getGeneratedHashes(outputFilePath || platformData.deviceBuildOutputPath);
529+
}
530+
531+
await device.fileSystem.updateHashesOnDevice(hashes, appIdentifier);
532+
}
533+
534+
private async isApplicationInstalled(device: Mobile.IDevice, projectData: IProjectData): Promise<boolean> {
535+
let result = false;
536+
if (this.$mobileHelper.isAndroidPlatform) {
537+
result = await device.applicationManager.isApplicationInstalled(projectData.projectId);
538+
}
539+
540+
return result;
541+
}
542+
506543
public async deployPlatform(deployInfo: IDeployPlatformInfo): Promise<void> {
507544
await this.preparePlatform({
508545
platform: deployInfo.platform,

0 commit comments

Comments
 (0)