1
0
Code Issues Pull Requests Packages Projects Releases Wiki Activity GitHub Gitee

working on android

This commit is contained in:
tdzl2003 2016-03-31 16:22:47 +08:00
parent 2765d2f4be
commit dbe1f9b26d
20 changed files with 375 additions and 168 deletions

2
.gitignore vendored
View File

@ -3,3 +3,5 @@
/local-cli/lib
/react-native-pushy-cli/node_modules
/react-native-pushy-cli/lib
*.iml

View File

@ -7,3 +7,4 @@
/local-cli/src
/react-native-pushy-cli
/Example
/android/build

View File

@ -1,51 +1 @@
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
import React, {
AppRegistry,
Component,
StyleSheet,
Text,
View
} from 'react-native';
class testHotUpdate extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
<Text style={styles.instructions}>
Shake or press menu button for dev menu
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('testHotUpdate', () => testHotUpdate);
require('./js/index');

View File

@ -1,69 +1 @@
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
import React, {
AppRegistry,
Component,
StyleSheet,
Text,
View,
TouchableOpacity,
} from 'react-native';
import {downloadFile, reloadUpdate} from 'react-native-update'
class testHotUpdate extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<TouchableOpacity onPress={
()=>{
downloadFile({updateUrl:'http://7xjhby.com2.z0.glb.qiniucdn.com/ios1.ppk', hashName:'test'})
}
}>
<Text style={styles.instructions}>
Press To DownloadFile
</Text>
</TouchableOpacity>
<TouchableOpacity onPress={
()=>{
reloadUpdate({hashName:'test'})
}
}>
<Text style={styles.instructions}>
Press To Reload
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('testHotUpdate', () => testHotUpdate);
require('./js/index');

View File

@ -0,0 +1,69 @@
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
import React, {
AppRegistry,
Component,
StyleSheet,
Text,
View,
TouchableOpacity,
} from 'react-native';
import {downloadFile, reloadUpdate} from 'react-native-update'
class testHotUpdate extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<TouchableOpacity onPress={
()=>{
downloadFile({updateUrl:'http://7xjhby.com2.z0.glb.qiniucdn.com/ios1.ppk', hashName:'test'})
}
}>
<Text style={styles.instructions}>
Press To DownloadFile
</Text>
</TouchableOpacity>
<TouchableOpacity onPress={
()=>{
reloadUpdate({hashName:'test'})
}
}>
<Text style={styles.instructions}>
Press To Reload
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('testHotUpdate', () => testHotUpdate);

View File

@ -7,6 +7,6 @@
},
"dependencies": {
"react-native": "^0.20.0",
"react-native-update": "git+https://github.com/reactnativecn/react-native-pushy"
"react-native-pushy": "../.."
}
}

17
android/build.gradle Normal file
View File

@ -0,0 +1,17 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
}
dependencies {
compile 'com.facebook.react:react-native:+'
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.reactnative.modules.update">
</manifest>

View File

@ -0,0 +1,115 @@
package cn.reactnative.modules.update;
import android.os.AsyncTask;
import android.util.Log;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
/**
* Created by tdzl2003 on 3/31/16.
*/
class DownloadTask extends AsyncTask<DownloadTaskParams, Void, Void> {
final int DOWNLOAD_CHUNK_SIZE = 4096;
@Override
protected Void doInBackground(DownloadTaskParams... params) {
DownloadTaskParams param = params[0];
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(param.url)
.build();
Response response = client.newCall(request).execute();
ResponseBody body = response.body();
long contentLength = body.contentLength();
BufferedSource source = body.source();
if (param.zipFilePath.exists()) {
param.zipFilePath.delete();
}
BufferedSink sink = Okio.buffer(Okio.sink(param.zipFilePath));
if (UpdateContext.DEBUG) {
Log.d("RNUpdate", "Downloading " + param.url);
}
long bytesRead = 0;
long totalRead = 0;
while ((bytesRead = source.read(sink.buffer(), DOWNLOAD_CHUNK_SIZE)) != -1) {
totalRead += bytesRead;
if (UpdateContext.DEBUG) {
Log.d("RNUpdate", "Progress " + totalRead + "/" + contentLength);
}
}
if (totalRead != contentLength) {
throw new Error("Unexpected eof while reading ppk");
}
sink.writeAll(source);
sink.close();
if (UpdateContext.DEBUG) {
Log.d("RNUpdate", "Download finished");
}
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(param.zipFilePath)));
ZipEntry ze;
byte[] buffer = new byte[1024];
int count;
String filename;
param.unzipDirectory.mkdirs();
while ((ze = zis.getNextEntry()) != null)
{
String fn = ze.getName();
File fmd = new File(param.unzipDirectory, fn);
if (UpdateContext.DEBUG) {
Log.d("RNUpdate", "Unzipping " + fn);
}
if (ze.isDirectory()) {
fmd.mkdirs();
continue;
}
FileOutputStream fout = new FileOutputStream(fmd);
while ((count = zis.read(buffer)) != -1)
{
fout.write(buffer, 0, count);
}
fout.close();
zis.closeEntry();
}
zis.close();
if (UpdateContext.DEBUG) {
Log.d("RNUpdate", "Unzip finished");
}
} catch (Throwable e) {
param.listener.onDownloadFailed(e);
}
return null;
}
}

View File

@ -0,0 +1,14 @@
package cn.reactnative.modules.update;
import java.io.File;
/**
* Created by tdzl2003 on 3/31/16.
*/
class DownloadTaskParams {
String url;
String hash;
File zipFilePath;
File unzipDirectory;
UpdateContext.DownloadFileListener listener;
}

View File

@ -0,0 +1,51 @@
package cn.reactnative.modules.update;
import android.content.Context;
import java.io.File;
/**
* Created by tdzl2003 on 3/31/16.
*/
public class UpdateContext {
private Context context;
private File rootDir;
public static boolean DEBUG = false;
private static UpdateContext currentInstance = null;
static UpdateContext instance() {
return currentInstance;
}
public UpdateContext(Context context) {
this.context = context;
this.rootDir = new File(context.getFilesDir(), "_update");
if (!rootDir.exists()) {
rootDir.mkdir();
}
}
public String getRootDir() {
return rootDir.toString();
}
public interface DownloadFileListener {
void onDownloadCompleted();
void onDownloadFailed(Throwable error);
}
public void downloadFile(String url, String hashName, DownloadFileListener listener) {
DownloadTaskParams params = new DownloadTaskParams();
params.url = url;
params.hash = hashName;
params.listener = listener;
params.zipFilePath = new File(rootDir, hashName + ".ppk");
params.unzipDirectory = new File(rootDir, hashName);
new DownloadTask().execute(params);
}
}

View File

@ -0,0 +1,51 @@
package cn.reactnative.modules.update;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import java.util.HashMap;
import java.util.Map;
/**
* Created by tdzl2003 on 3/31/16.
*/
public class UpdateModule extends ReactContextBaseJavaModule{
UpdateContext updateContext;
public UpdateModule(ReactApplicationContext reactContext) {
super(reactContext);
this.updateContext = new UpdateContext(reactContext.getApplicationContext());
}
@Override
public Map<String, Object> getConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put("downloadRootDir", updateContext.getRootDir());
return constants;
}
@Override
public String getName() {
return "RCTHotUpdate";
}
@ReactMethod
public void downloadUpdate(ReadableMap options, final Promise promise){
String url = options.getString("updateUrl");
String hash = options.getString("hashName");
updateContext.downloadFile(url, hash, new UpdateContext.DownloadFileListener() {
@Override
public void onDownloadCompleted() {
promise.resolve(null);
}
@Override
public void onDownloadFailed(Throwable error) {
promise.reject(error);
}
});
}
}

View File

@ -0,0 +1,34 @@
package cn.reactnative.modules.update;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Created by tdzl2003 on 3/31/16.
*/
public class UpdatePackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.asList(new NativeModule[]{
// Modules from third-party
new UpdateModule(reactContext),
});
}
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}

View File

@ -1,5 +1,6 @@
/**
* Created by tdzl2003 on 2/6/16.
* @providesModule react-native-update
*/
//if (__DEV__){

View File

@ -85,8 +85,6 @@ function getPathOnDevserver(devServerUrl, asset) {
* Returns a path like 'assets/AwesomeModule'
*/
function getBasePath(asset) {
// TODO(frantic): currently httpServerLocation is used both as
// path in http URL and path within IPA. Should we have zipArchiveLocation?
var path = asset.httpServerLocation;
if (path[0] === '/') {
path = path.substr(1);

View File

@ -42,7 +42,7 @@
"hasValue": true
},
"output": {
"default": "build/output/${platform}.${hash}.ppk",
"default": "build/output/${platform}.${time}.ppk",
"hasValue": true
},
"verbose": {

View File

@ -26,38 +26,9 @@ function mkdir(dir){
});
}
function calcMd5ForFile(fn) {
return new Promise((resolve, reject) => {
var hash = crypto.createHash('md5'),
stream = fs.createReadStream(fn);
stream.on('data', (data) => hash.update(data, 'utf8'));
stream.on('end', () => resolve(hash.digest('hex')));
stream.on('error', err => reject(err));
})
}
async function calcMd5ForDirectory(dir) {
const childs = fs.readdirSync(dir).sort();
const result = {};
for (const name of childs) {
const fullPath = path.join(dir, name);
const stat = fs.statSync(fullPath);
if (stat.isFile()) {
result[name] = 'file:' + await calcMd5ForFile(fullPath);
} else {
result[name] = 'directory:' + await calcMd5ForDirectory(fullPath);
}
}
var hash = crypto.createHash('md5');
hash.update(JSON.stringify(result), 'md5');
return hash.digest('hex');
}
async function pack(dir, output){
const hash = await calcMd5ForDirectory(dir);
const realOutput = output.replace(/\$\{hash\}/g, hash);
await mkdir(path.dirname(realOutput))
const realOutput = output.replace(/\$\{time\}/g, '' + Date.now());
await mkdir(path.dirname(realOutput));
await new Promise((resolve, reject) => {
var zipfile = new ZipFile();
@ -91,7 +62,7 @@ async function pack(dir, output){
});
zipfile.end();
});
console.log('Bundled with hash: ' + hash);
console.log('Bundled saved to: ' + realOutput);
}
function enumZipEntries(zipFn, callback) {
@ -207,20 +178,15 @@ export const commands = {
} else {
// If same file.
if (originEntries[entry.fileName] === entry.crc32) {
console.log('keep:', entry.fileName);
copies[entry.fileName] = 1;
return;
}
// If moved from other place
if (originMap[entry.crc32]){
console.log('move:' + originMap[entry.crc32] + '->' + entry.fileName);
copies[entry.fileName] = originMap[entry.crc32];
return;
}
// TODO: test diff
console.log('add:' + entry.fileName);
return new Promise((resolve, reject)=>{
nextZipfile.openReadStream(entry, function(err, readStream) {
if (err){

View File

@ -31,6 +31,7 @@
"fs-promise": "^0.4.1",
"isomorphic-fetch": "^2.2.1",
"mkdir-recursive": "^0.2.1",
"node-bsdiff": "^0.1.1",
"read": "^1.0.7",
"yauzl": "^2.4.1",
"yazl": "^2.3.0"

View File

@ -1,5 +1,5 @@
{
"name": "react-native-pushy-cli",
"name": "react-native-update-cli",
"version": "0.1.0",
"description": "Command tools for javaScript updater with `pushy` service for react native apps.",
"main": "index.js",

View File

@ -10,7 +10,7 @@ const CLI_MODULE_PATH = function() {
return path.resolve(
process.cwd(),
'node_modules',
'react-native-pushy',
'react-native-update',
'local-cli'
);
};
@ -19,7 +19,7 @@ const PACKAGE_JSON_PATH = function() {
return path.resolve(
process.cwd(),
'node_modules',
'react-native-pushy',
'react-native-update',
'package.json'
);
};
@ -36,17 +36,17 @@ if (cli) {
cli.run();
} else {
console.error('Are you at home directory of a react-native project?');
console.error('`pushy install` is under development, please run `npm install react-native-pushy` to install pushy manually.');
console.error('`pushy install` is under development, please run `npm install react-native-update` to install pushy manually.');
process.exit(1);
}
function checkForVersionCommand() {
if (process.argv.indexOf('-v') >= 0 || process.argv[2] === 'version') {
console.log('react-native-pushy-cli: ' + require('../package.json').version);
console.log('react-native-update-cli: ' + require('../package.json').version);
try {
console.log('react-native-pushy: ' + require(PACKAGE_JSON_PATH()).version);
console.log('react-native-update: ' + require(PACKAGE_JSON_PATH()).version);
} catch (e) {
console.log('react-native-pushy: n/a - not inside a React Native project directory')
console.log('react-native-update: n/a - not inside a React Native project directory')
}
process.exit();
}