Skip to content

Commit 3bbe72d

Browse files
committed
wifi only option, and missing typings.
1 parent ffc372e commit 3bbe72d

File tree

10 files changed

+112
-26
lines changed

10 files changed

+112
-26
lines changed

README.md

+35-11
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ rn-fetch-blob version 0.10.16 is only compatible with react native 0.60 and up.
4141

4242
## About
4343

44-
This project was started in the cause of solving issue [facebook/react-native#854](https://github.com/facebook/react-native/issues/854), React Native's lacks of `Blob` implementation which results into problems when transferring binary data.
44+
This project was started in the cause of solving issue [facebook/react-native#854](https://github.com/facebook/react-native/issues/854), React Native's lacks of `Blob` implementation which results into problems when transferring binary data.
4545

4646
It is committed to making file access and transfer easier and more efficient for React Native developers. We've implemented highly customizable filesystem and network module which plays well together. For example, developers can upload and download data directly from/to storage, which is more efficient, especially for large files. The file system supports file stream, so you don't have to worry about OOM problem when accessing large files.
4747

@@ -116,8 +116,8 @@ If you're going to access external storage (say, SD card storage) for `Android 5
116116

117117
<uses-permission android:name="android.permission.INTERNET" />
118118
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
119-
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
120-
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
119+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
120+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
121121
+ <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
122122
...
123123

@@ -129,10 +129,18 @@ Also, if you're going to use `Android Download Manager` you have to add this to
129129
<intent-filter>
130130
<action android:name="android.intent.action.MAIN" />
131131
<category android:name="android.intent.category.LAUNCHER" />
132-
+ <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
132+
+ <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
133133
</intent-filter>
134134
```
135135

136+
If you are going to use the `wifiOnly` flag, you need to add this to `AndroidManifest.xml`
137+
138+
```diff
139+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
140+
...
141+
142+
```
143+
136144
**Grant Access Permission for Android 6.0**
137145

138146
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. So adding permissions in `AndroidManifest.xml` won't work for Android 6.0+ devices. To grant permissions in runtime, you might use [PermissionAndroid API](https://facebook.github.io/react-native/docs/permissionsandroid.html).
@@ -168,7 +176,7 @@ To sum up:
168176

169177
- To send a form data, the `Content-Type` header does not matter. When the body is an `Array` we will set proper content type for you.
170178
- To send binary data, you have two choices, use BASE64 encoded string or path points to a file contains the body.
171-
- If the `Content-Type` containing substring`;BASE64` or `application/octet` the given body will be considered as a BASE64 encoded data which will be decoded to binary data as the request body.
179+
- If the `Content-Type` containing substring`;BASE64` or `application/octet` the given body will be considered as a BASE64 encoded data which will be decoded to binary data as the request body.
172180
- Otherwise, if a string starts with `RNFetchBlob-file://` (which can simply be done by `RNFetchBlob.wrap(PATH_TO_THE_FILE)`), it will try to find the data from the URI string after `RNFetchBlob-file://` and use it as the request body.
173181
- To send the body as-is, simply use a `Content-Type` header not containing `;BASE64` or `application/octet`.
174182

@@ -189,7 +197,7 @@ RNFetchBlob.fetch('GET', 'http://www.example.com/images/img1.png', {
189197
})
190198
.then((res) => {
191199
let status = res.info().status;
192-
200+
193201
if(status == 200) {
194202
// the conversion is done in native code
195203
let base64Str = res.base64()
@@ -290,7 +298,7 @@ RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
290298
'Content-Type' : 'application/octet-stream',
291299
// here's the body you're going to send, should be a BASE64 encoded string
292300
// (you can use "base64"(refer to the library 'mathiasbynens/base64') APIs to make one).
293-
// The data will be converted to "byte array"(say, blob) before request sent.
301+
// The data will be converted to "byte array"(say, blob) before request sent.
294302
}, base64ImageString)
295303
.then((res) => {
296304
console.log(res.text())
@@ -648,7 +656,7 @@ RNFetchBlob.fs.readStream(
648656
ifstream.onError((err) => {
649657
console.log('oops', err)
650658
})
651-
ifstream.onEnd(() => {
659+
ifstream.onEnd(() => {
652660
<Image source={{ uri : 'data:image/png,base64' + data }}
653661
})
654662
})
@@ -673,7 +681,7 @@ RNFetchBlob.fs.writeStream(
673681
.catch(console.error)
674682
```
675683

676-
or
684+
or
677685

678686
```js
679687
RNFetchBlob.fs.writeStream(
@@ -749,7 +757,7 @@ You can also group requests by using `session` API and use `dispose` to remove t
749757
.then((res) => {
750758
// set session of a response
751759
res.session('foo')
752-
})
760+
})
753761

754762
RNFetchblob.config({
755763
// you can also set session beforehand
@@ -759,7 +767,7 @@ You can also group requests by using `session` API and use `dispose` to remove t
759767
.fetch('GET', 'http://example.com/download/file')
760768
.then((res) => {
761769
// ...
762-
})
770+
})
763771

764772
// or put an existing file path to the session
765773
RNFetchBlob.session('foo').add('some-file-path')
@@ -794,6 +802,22 @@ RNFetchBlob.config({
794802
})
795803
```
796804

805+
### WiFi only requests
806+
807+
If you wish to only route requests through the Wifi interface, set the below configuration.
808+
Note: On Android, the `ACCESS_NETWORK_STATE` permission must be set, and this flag will only work
809+
on API version 21 (Lollipop, Android 5.0) or above. APIs below 21 will ignore this flag.
810+
811+
```js
812+
RNFetchBlob.config({
813+
wifiOnly : true
814+
})
815+
.fetch('GET', 'https://mysite.com')
816+
.then((resp) => {
817+
// ...
818+
})
819+
```
820+
797821
## Web API Polyfills
798822

799823
After `0.8.0` we've made some [Web API polyfills](https://github.com/joltup/rn-fetch-blob/wiki/Web-API-Polyfills-(experimental)) that makes some browser-based library available in RN.

android/src/main/java/com/RNFetchBlob/RNFetchBlobConfig.java

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class RNFetchBlobConfig {
1010
public String appendExt;
1111
public ReadableMap addAndroidDownloads;
1212
public Boolean trusty;
13+
public Boolean wifiOnly = false;
1314
public String key;
1415
public String mime;
1516
public Boolean auto;
@@ -26,6 +27,7 @@ class RNFetchBlobConfig {
2627
this.path = options.hasKey("path") ? options.getString("path") : null;
2728
this.appendExt = options.hasKey("appendExt") ? options.getString("appendExt") : "";
2829
this.trusty = options.hasKey("trusty") ? options.getBoolean("trusty") : false;
30+
this.wifiOnly = options.hasKey("wifiOnly") ? options.getBoolean("wifiOnly") : false;
2931
if(options.hasKey("addAndroidDownloads")) {
3032
this.addAndroidDownloads = options.getMap("addAndroidDownloads");
3133
}

android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java

+46-13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import android.net.Uri;
1010
import android.os.Build;
1111
import androidx.annotation.NonNull;
12+
import android.net.Network;
13+
import android.net.NetworkCapabilities;
14+
import android.net.ConnectivityManager;
1215
import android.util.Base64;
1316

1417
import com.RNFetchBlob.Response.RNFetchBlobDefaultResp;
@@ -36,6 +39,7 @@
3639
import java.net.SocketException;
3740
import java.net.SocketTimeoutException;
3841
import java.net.URL;
42+
import java.net.Proxy;
3943
import java.nio.ByteBuffer;
4044
import java.nio.charset.CharacterCodingException;
4145
import java.nio.charset.Charset;
@@ -231,6 +235,45 @@ else if(this.options.fileCache)
231235
clientBuilder = client.newBuilder();
232236
}
233237

238+
// wifi only, need ACCESS_NETWORK_STATE permission
239+
// and API level >= 21
240+
if(this.options.wifiOnly){
241+
242+
boolean found = false;
243+
244+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
245+
ConnectivityManager connectivityManager = (ConnectivityManager) RNFetchBlob.RCTContext.getSystemService(RNFetchBlob.RCTContext.CONNECTIVITY_SERVICE);
246+
Network[] networks = connectivityManager.getAllNetworks();
247+
248+
for (Network network : networks) {
249+
//NetworkInfo netInfo = connectivityManager.getNetworkInfo(network);
250+
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(network);
251+
if(caps == null){
252+
continue;
253+
}
254+
255+
// netinfo is deprecated
256+
//if (netInfo.getType() == ConnectivityManager.TYPE_WIFI && netInfo.getState() == NetworkInfo.State.CONNECTED) {
257+
if(caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)){
258+
clientBuilder.proxy(Proxy.NO_PROXY);
259+
clientBuilder.socketFactory(network.getSocketFactory());
260+
found = true;
261+
break;
262+
263+
}
264+
}
265+
266+
if(!found){
267+
callback.invoke("No available WiFi connections.", null, null);
268+
releaseTaskResource();
269+
return;
270+
}
271+
}
272+
else{
273+
RNFetchBlobUtils.emitWarningEvent("RNFetchBlob: wifiOnly was set, but SDK < 21. wifiOnly was ignored.");
274+
}
275+
}
276+
234277
final Request.Builder builder = new Request.Builder();
235278
try {
236279
builder.url(new URL(url));
@@ -530,26 +573,16 @@ private void done(Response resp) {
530573
}
531574
break;
532575
case FileStorage:
533-
ResponseBody responseBody = resp.body();
534-
535576
try {
536577
// In order to write response data to `destPath` we have to invoke this method.
537578
// It uses customized response body which is able to report download progress
538579
// and write response data to destination path.
539-
responseBody.bytes();
580+
resp.body().bytes();
540581
} catch (Exception ignored) {
541582
// ignored.printStackTrace();
542583
}
543-
544-
RNFetchBlobFileResp rnFetchBlobFileResp = (RNFetchBlobFileResp) responseBody;
545-
546-
if(rnFetchBlobFileResp != null && rnFetchBlobFileResp.isDownloadComplete() == false){
547-
callback.invoke("RNFetchBlob failed. Download interrupted.", null);
548-
}
549-
else {
550-
this.destPath = this.destPath.replace("?append=true", "");
551-
callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
552-
}
584+
this.destPath = this.destPath.replace("?append=true", "");
585+
callback.invoke(null, RNFetchBlobConst.RNFB_RESPONSE_PATH, this.destPath);
553586
break;
554587
default:
555588
try {

index.d.ts

+10
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,16 @@ export interface RNFetchBlobConfig {
546546
*/
547547
trusty?: boolean;
548548

549+
/**
550+
* Set this property to true will only do requests through the WiFi interface, and fail otherwise.
551+
*/
552+
wifiOnly?: boolean;
553+
554+
/**
555+
* Set this property so redirects are not automatically followed.
556+
*/
557+
followRedirect?: boolean;
558+
549559
/**
550560
* Set this property to true will makes response data of the fetch stored in a temp file, by default the temp
551561
* file will stored in App's own root folder with file name template RNFetchBlob_tmp${timestamp}.

index.js

+6
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ function wrap(path:string):string {
105105
* If it doesn't exist, the file is downloaded as usual
106106
* @property {number} timeout
107107
* Request timeout in millionseconds, by default it's 30000ms.
108+
* @property {boolean} followRedirect
109+
* Follow redirects automatically, default true
110+
* @property {boolean} trusty
111+
* Trust all certificates
112+
* @property {boolean} wifiOnly
113+
* Only do requests through WiFi. Android SDK 21 or above only.
108114
*
109115
* @return {function} This method returns a `fetch` method instance.
110116
*/

index.js.flow

+3-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,9 @@ export type RNFetchBlobConfig = {
163163
path?: string,
164164
session?: string,
165165
timeout?: number,
166-
trusty?: boolean
166+
trusty?: boolean,
167+
wifiOnly?: boolean,
168+
followRedirect?: boolean
167169
};
168170
export type RNFetchBlobResponseInfo = {
169171
headers: {[fieldName: string]: string},

ios/RNFetchBlobConst.h

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ extern NSString *const CONFIG_USE_TEMP;
3232
extern NSString *const CONFIG_FILE_PATH;
3333
extern NSString *const CONFIG_FILE_EXT;
3434
extern NSString *const CONFIG_TRUSTY;
35+
extern NSString *const CONFIG_WIFI_ONLY;
3536
extern NSString *const CONFIG_INDICATOR;
3637
extern NSString *const CONFIG_KEY;
3738
extern NSString *const CONFIG_EXTRA_BLOB_CTYPE;

ios/RNFetchBlobConst.m

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
NSString *const CONFIG_FILE_PATH = @"path";
1717
NSString *const CONFIG_FILE_EXT = @"appendExt";
1818
NSString *const CONFIG_TRUSTY = @"trusty";
19+
NSString *const CONFIG_WIFI_ONLY = @"wifiOnly";
1920
NSString *const CONFIG_INDICATOR = @"indicator";
2021
NSString *const CONFIG_KEY = @"key";
2122
NSString *const CONFIG_EXTRA_BLOB_CTYPE = @"binaryContentTypes";

ios/RNFetchBlobRequest.m

+4
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ - (void) sendRequest:(__weak NSDictionary * _Nullable )options
124124
defaultConfigObject.timeoutIntervalForRequest = timeout/1000;
125125
}
126126

127+
if([options valueForKey:CONFIG_WIFI_ONLY] != nil && ![options[CONFIG_WIFI_ONLY] boolValue]){
128+
[defaultConfigObject setAllowsCellularAccess:NO];
129+
}
130+
127131
defaultConfigObject.HTTPMaximumConnectionsPerHost = 10;
128132
session = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:operationQueue];
129133

types.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ type RNFetchBlobConfig = {
55
appendExt : string,
66
session : string,
77
addAndroidDownloads : any,
8-
indicator : bool
8+
indicator : bool,
9+
followRedirect : bool,
10+
trusty : bool,
11+
wifiOnly : bool
912
};
1013

1114
type RNFetchBlobNative = {

0 commit comments

Comments
 (0)