Commit 079a0e4a authored by wangqinghua's avatar wangqinghua

init

parent 27ea3b20
## ChangeLog
#### Version 0.8.8 (19.11.2018)
- Upgrade ShortcutBadger to v1.1.22
#### Version 0.8.7 (24.01.2018)
- Added `appShortcutBadgerCustom` gradle switch.
- Upgrade ShortcutBadger to v1.1.21
- Added `isSupported` to check support at runtime (on Android).
#### Version 0.8.6 (02.01.2018)
- Added polyfill for Object.assign to fix issue on Android.
#### Version 0.8.5 (23.10.2017)
- Upgrade ShortcutBadger to v1.1.19
- BadgeImpl class can now be used from other Android plugins.
#### Version 0.8.4 (17.10.2017)
- Fix _autoClear_ for desktop platforms.
- Support for _download_ and _circular_ indicator on OSX.
<br>Based on https://github.com/hokein/DockProgressBar
#### Version 0.8.3 (27.09.2017)
- Fix threading warnings with iOS 11
#### Version 0.8.2 (06.09.2017)
- Fix package.json to work with latest cordova and npm
- Upgrade ShortcutBadger to v1.1.18
#### Version 0.8.1 (12.06.2017)
- Fixed issue with Android 4.x, see #95, #97
#### Version 0.8.0 (07.06.2017)
- Support for OSX platform
- Updated code to work properly with iOS@10
- Dropped supported for iOS@9
- Upgrade ShortcutBadger to v1.1.17
- Allow specifying ShortcutBadger version via gradle property
- Config settings like `autoClear` are not persisted
- Small enhancements and bug fixes
- Removed platform support for WP8
- Removed old namespace `plugin.notification.badge`
#### Version 0.7.4 (30.12.2016)
- Upgrade ShortcutBadger to v1.1.11
- Support for ZUK
- Improved support for Samsung devices
#### Version 0.7.3 (22.09.2016)
- Upgrade ShortcutBadger to v1.1.8
- Support for Huawei
- Support for iOS 10
#### Version 0.7.2 (19.02.2016)
- __New ID__ `cordova-plugin-badge`
- Upgraded ShortcutBadger to v1.1.4
- Use new app-event plugin
- Removed support for Amazon FireOS (ShortcutBadger doesnt support it)
#### Version 0.7.1 (30.07.2015)
- Support for app icon badges on selective Android platforms thanks to [ShortcutBadger](https://github.com/leolin310148/ShortcutBadger)
- Sony
- Samsung
- LG
- HTC
- Xiaomi
- ASUS
- ADW, APEX, NOVA
#### Version 0.7.0 (18.07.2015)
- New platform support:
- Amazon FireOS
- Browser
- Windows
- `get`, `set` and `clear` support callbacks.
- Support for [Glyphs](https://msdn.microsoft.com/de-de/library/windows/apps/hh779719#phone_badge) on _Windows_ platform.
- Added tests
#### Version 0.6.4 (02.05.2015)
- Upgrade cordova dependency from 3.0 to 3.6
- Fix incompatibility with local-notification plugin and PGB caused by the usage of hooks.
#### Version 0.6.3 (22.03.2015)
- New interfaces to increase or decrease the badge number.
- Fix incompatibility with local-notification plugin.
- Add instead of replace permissions on iOS.
- Refreshed layout of the example app.
#### Version 0.6.2 (01.03.2015)
- [change:] Renamed `promptForPermission` to `registerPermission`. Older one is still supported.
- [enhancement:] Support iOS8 and older SDK versions from a single binary.
- [enhancement:] `registerPermission` returns result of registration.
- [enhancement:] No need anymore to call `registerPermission` explicit before trying to set the badge number.
#### Version 0.6.1 (03.10.2014)
- [bugfix:] `hasPermission` and `promptForPermission` let the app crash on iOS7 and older.
#### Version 0.6.0 (29.09.2014)
- [enhancement:] iOS 8 support
- [enhancement:] All methods are asynchron now and do not block the main thread anymore.
- [feature:] New method `hasPermission` to ask if the user has granted to display badge notifications.
- [feature:] New method `promptForPermission` to promt the user to grant permission to display badge notifications.
- [feature:] New method `configure` to configure badge properties.
- [feature:] The small icon on Android can be changed through `configure`.
- [**change**:] The namespace `plugin.notification.badge` will be removed with v0.6.1
- [**change**:] `setTitle` is deprecated, please use `configure({ title: 'title' })`.
- [**change**:] `clearOnTap` is deprecated, please use `configure({ autoClear: true })`.
- [bugfix:] `getBadge` still returned the number when autoClear: was set and the notification was already cleared by the system (Android).
- [bugfix:] `clean` was not working on Windows Phone.
#### Version 0.5.3 (23.05.2014)
- Added new namespace `cordova.plugins.notification.badge`<br>
**Note:** The former `plugin.notification.badge` namespace is deprecated now and will be removed in the next major release.
- [bugfix:] `get` returned the old value even after `clear` was called on Android.
#### Version 0.5.2 (12.04.2014)
- [enhancement:] Badge can be cleared automatically through `setClearOnTap`
- [enhancement:] Badge can be retrieved through `get`
#### Version 0.5.1 (25.01.2014)
- [enhancement:] Specify custom notification title on Android can be set through JS interface.
- [enhancement:] Setting launchMode to *singleInstance* isn't necessary anymore. App does not restart on click anymore.
#### Version 0.5.0 (04.01.2014)
- Added Android support
#### Version 0.4.1 (04.12.2013)
- Release under the Apache 2.0 license.
#### Version 0.4.0 (07.10.2013)
- Added WP8 support
- **Note:** The former `plugin.badge` namespace is not longer available.
#### Version 0.2.1 (15.08.2013)
- Added new namespace `plugin.notification.badge`<br>
**Note:** The former `plugin.badge` namespace is deprecated now and will be removed in the next major release.
#### Version 0.2.0 (11.08.2013)
- Added iOS support<br>
*Based on the Badge iOS plugin made by* ***Joseph Stuhr***
This diff is collapsed.
<p align="left"><b><a href="https://github.com/katzer/cordova-plugin-badge/tree/example">SAMPLE APP</a> :point_right:</b></p>
# Cordova Badge Plugin <br> [![npm version](https://badge.fury.io/js/cordova-plugin-badge.svg)](https://badge.fury.io/js/cordova-plugin-badge) [![Code Climate](https://codeclimate.com/github/katzer/cordova-plugin-badge/badges/gpa.svg)](https://codeclimate.com/github/katzer/cordova-plugin-badge) [![PayPayl donate button](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=L3HKQCD9UA35A "Donate once-off to this project using Paypal")
[Cordova][cordova] plugin to access and modify the badge number of the app icon on various mobile platforms including iOS, Android and Windows.
<img height="150px" align="right" hspace="19" vspace="12" src="http://4.bp.blogspot.com/-GBwBSN92DvU/UB8Kut7Oz0I/AAAAAAAAJKs/mJgBmj1RKqU/s1600/whatsapp+wp8+10.png"></img>
### How they appear to the user
Users see notifications in the following ways:
- Badging the app’s icon
- Progress indicator (OSX based on https://github.com/hokein/DockProgressBar)
### Supported Platforms
- __Android / Amazon FireOS__ (via [ShortcutBadger][shortcut_badger])
- __Browser__ (via [favico.js][favico_js])
- __iOS 10+__
- __OSX__
- __Windows__ (Phone and Desktop)
## Installation
The plugin can be installed via [Cordova-CLI][CLI] and is publicly available on [NPM][npm].
Execute from the projects root folder:
$ cordova plugin add cordova-plugin-badge
Or install a specific version:
$ cordova plugin add cordova-plugin-badge@VERSION
Or install the latest head version:
$ cordova plugin add https://github.com/katzer/cordova-plugin-badge.git
Or install from local source:
$ cordova plugin add <path> --nofetch --nosave
## Usage
The plugin creates the object `cordova.plugins.notification.badge` and is accessible after *deviceready* has been fired.
```js
document.addEventListener('deviceready', function () {
// cordova.plugins.notification.badge is now available
}, false);
```
### Set the badge number
Badge numbers cannot be negative. The maximum might be restricted by the OS.
A callback is optional and will be invoked with the current badge number.
```js
cordova.plugins.notification.badge.set(10);
```
<p align="center">
<img height="150px" src="images/ios.png">
&nbsp;&nbsp;&nbsp;&nbsp;
<img height="150px" src="images/android.png">
&nbsp;&nbsp;&nbsp;&nbsp;
<img height="150px" src="images/windows.png">
</p>
There's built-in support to increase the badge number:
```js
cordova.plugins.notification.badge.increase(1, function (badge) {
// badge is now 11 (10 + 1)
});
```
To decrease the badge number:
```js
cordova.plugins.notification.badge.decrease(2, function (badge) {
// badge is now 9 (11 - 2)
});
```
And to clear out the badge number:
```js
cordova.plugins.notification.badge.clear();
```
### Get the badge number
The default value is 0. The badge number wont get lost after reboot or app restart.
```js
cordova.plugins.notification.badge.get(function (badge) {
...
});
```
__Note:__ Modifying the badge number outside of the plugin does result into wrong behaivor!
### Configurations
To clear the badge number automatically if the user taps the app icon:
```js
cordova.plugins.notification.badge.configure({ autoClear: true });
```
OSX supports additional indicators. Other than to `badge` these are `circular` and `download`.
```js
cordova.plugins.notification.badge.configure({ indicator: 'circular' });
```
<p align="center">
<img src="images/osx-badge.png">
&nbsp;&nbsp;&nbsp;&nbsp;
<img src="images/osx-circular.png">
&nbsp;&nbsp;&nbsp;&nbsp;
<img src="images/osx-download.png">
</p>
## Permissions
The plugin might ask for granting permissions to modify the badge number.
That's done automatically but it's also possible to request them manually:
```javascript
cordova.plugins.notification.badge.requestPermission(function (granted) {
...
});
```
<p align="center">
<img height="200px" src="images/ios-permission.png">
</p>
To check if they have been granted already:
```javascript
cordova.plugins.notification.badge.hasPermission(function (granted) {
...
});
```
## Quirks
On Android not all launchers support badges. In order to set badges the plugin uses [ShortcutBadger][shortcut_badger]. Check out their website to see which launchers are supported.
If you're using PhoneGap Build please make sure you specify gradle as your Android build tool in config.xml:
```xml
<preference name="android-build-tool" value="gradle" />
```
To specify a custom version of _ShortcutBadger_ follow this [guide][gradle-guide]. The name of the property is `appShortcutBadgerVersion`.
```gradle
# In <your-project>/platforms/android/gradle.properties
appShortcutBadgerVersion=1.1.22
```
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
## License
This software is released under the [Apache 2.0 License][apache2_license].
Made with :yum: from Leipzig
© 2013 [appPlant GmbH][appplant]
[cordova]: https://cordova.apache.org
[shortcut_badger]: https://github.com/leolin310148/ShortcutBadger
[favico_js]: http://lab.ejci.net/favico.js/
[CLI]: http://cordova.apache.org/docs/en/edge/guide_cli_index.md.html#The%20Command-line%20Interface
[npm]: https://www.npmjs.com/package/cordova-plugin-badge
[gradle-guide]: https://cordova.apache.org/docs/en/latest/guide/platforms/android/#configuring-gradle
[apache2_license]: http://opensource.org/licenses/Apache-2.0
[appplant]: http://appplant.de
{
"_from": "cordova-plugin-badge",
"_id": "cordova-plugin-badge@0.8.8",
"_inBundle": false,
"_integrity": "sha1-CSQBhpm0j5LdOzNhVFJzdYIUTJY=",
"_location": "/cordova-plugin-badge",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "cordova-plugin-badge",
"name": "cordova-plugin-badge",
"escapedName": "cordova-plugin-badge",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "http://r.cnpmjs.org/cordova-plugin-badge/download/cordova-plugin-badge-0.8.8.tgz",
"_shasum": "0924018699b48f92dd3b33615452737582144c96",
"_spec": "cordova-plugin-badge",
"_where": "/Users/ben/gitLab-project/party-build-cloud",
"author": {
"name": "Sebastián Katzer"
},
"bugs": {
"url": "https://github.com/katzer/cordova-plugin-badge/issues"
},
"bundleDependencies": false,
"cordova": {
"id": "cordova-plugin-badge",
"platforms": [
"ios",
"osx",
"android",
"browser",
"windows"
]
},
"deprecated": false,
"description": "Shows the count of unread messages as a badge on the app icon.",
"engines": [
{
"name": "cordova",
"version": ">=6.0.0"
},
{
"name": "apple-ios",
"version": ">=10.0.0"
},
{
"name": "cordova-android",
"version": ">=4"
},
{
"name": "cordova-plugman",
"version": ">=4.2.0"
}
],
"homepage": "https://github.com/katzer/cordova-plugin-badge#readme",
"keywords": [
"appplant",
"badge",
"shortcutbadger",
"ecosystem:cordova",
"cordova-ios",
"cordova-osx",
"cordova-android",
"cordova-browser",
"cordova-windows"
],
"license": "Apache 2.0",
"name": "cordova-plugin-badge",
"repository": {
"type": "git",
"url": "git+https://github.com/katzer/cordova-plugin-badge.git"
},
"version": "0.8.8"
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
-->
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-badge"
version="0.8.8">
<name>Badge</name>
<description>Shows the count of unread messages as a badge on the app icon.</description>
<repo>https://github.com/katzer/cordova-plugin-badge.git</repo>
<issue>https://github.com/katzer/cordova-plugin-badge/issues</issue>
<keywords>appplant, badge, shortcutbadger</keywords>
<license>Apache 2.0</license>
<author>Sebastián Katzer</author>
<!-- cordova -->
<engines>
<engine name="cordova" version=">=6.0.0" />
<engine name="apple-ios" version=">=10.0.0" />
<engine name="cordova-android" version=">=4"/>
<engine name="cordova-plugman" version=">=4.2.0"/><!-- needed for gradleReference support -->
</engines>
<!-- js -->
<js-module src="www/badge.js" name="Badge">
<clobbers target="cordova.plugins.notification.badge" />
</js-module>
<!-- ios -->
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="Badge">
<param name="ios-package" value="APPBadge"/>
</feature>
</config-file>
<header-file src="src/ios/APPBadge.h" />
<source-file src="src/ios/APPBadge.m" />
</platform>
<!-- osx -->
<platform name="osx">
<config-file target="config.xml" parent="/*">
<feature name="Badge">
<param name="osx-package" value="APPBadge"/>
</feature>
</config-file>
<header-file src="src/osx/APPBadge.h" />
<source-file src="src/osx/APPBadge.m" />
<header-file src="src/osx/DockCircularProgressBar.h" />
<source-file src="src/osx/DockCircularProgressBar.mm" />
<header-file src="src/osx/DockDownloadProgressBar.h" />
<source-file src="src/osx/DockDownloadProgressBar.mm" />
</platform>
<!-- android -->
<platform name="android">
<config-file target="config.xml" parent="/*">
<feature name="Badge">
<param name="android-package" value="de.appplant.cordova.plugin.badge.Badge"/>
</feature>
</config-file>
<framework src="src/android/badge.gradle" custom="true" type="gradleReference"/>
<source-file
src="src/android/Badge.java"
target-dir="src/de/appplant/cordova/plugin/badge" />
<source-file
src="src/android/BadgeImpl.java"
target-dir="src/de/appplant/cordova/plugin/badge" />
</platform>
<!-- browser -->
<platform name="browser">
<config-file target="config.xml" parent="/*">
<feature name="Badge">
<param name="browser-package" value="Badge"/>
</feature>
</config-file>
<js-module src="src/browser/favico.min.js" name="Badge.Favico">
<clobbers target="cordova.plugins.notification.badge.Favico" />
</js-module>
<js-module src="src/browser/BadgeProxy.js" name="Badge.Proxy">
<runs />
</js-module>
</platform>
<!-- windows -->
<platform name="windows">
<js-module src="src/windows/BadgeProxy.js" name="Badge.Proxy" >
<runs />
</js-module>
</platform>
</plugin>
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.badge;
import android.content.Context;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import static org.apache.cordova.PluginResult.Status.OK;
public class Badge extends CordovaPlugin {
// Implementation of the badge interface methods
private BadgeImpl impl;
/**
* Called after plugin construction and fields have been initialized.
*/
protected void pluginInitialize() {
impl = new BadgeImpl(getContext());
}
/**
* Executes the request.
*
* @param action The action to execute.
* @param args The exec() arguments.
* @param callback The callback context used when
* calling back into JavaScript.
*
* @return Returning false results in a "MethodNotFound" error.
*/
@Override
public boolean execute (String action, JSONArray args, CallbackContext callback)
throws JSONException {
boolean ret = true;
if (action.equalsIgnoreCase("load")) {
loadConfig(callback);
}
else if (action.equalsIgnoreCase("save")) {
saveConfig(args.getJSONObject(0));
}
else if (action.equalsIgnoreCase("clear")) {
clearBadge(callback);
}
else if (action.equalsIgnoreCase("get")) {
getBadge(callback);
}
else if (action.equalsIgnoreCase("set")) {
setBadge(args, callback);
}
else if (action.equalsIgnoreCase("check")) {
checkSupport(callback);
}
else {
ret = false;
}
return ret;
}
/**
* Load the persisted plugin config.
*
* @param callback The function to be exec as the callback.
*/
private void loadConfig(final CallbackContext callback) {
cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
JSONObject cfg = impl.loadConfig();
callback.success(cfg);
}
});
}
/**
* Persist the plugin config.
*
* @param config The config map to persist.
*/
private void saveConfig(final JSONObject config) {
cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
impl.saveConfig(config);
}
});
}
/**
* Clear the badge number.
*
* @param callback The function to be exec as the callback.
*/
private void clearBadge (final CallbackContext callback) {
cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
impl.clearBadge();
int badge = impl.getBadge();
callback.success(badge);
}
});
}
/**
* Get the badge number.
*
* @param callback The function to be exec as the callback.
*/
private void getBadge (final CallbackContext callback) {
cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
int badge = impl.getBadge();
callback.success(badge);
}
});
}
/**
* Set the badge number.
*
* @param args The number to set as the badge number.
* @param callback The function to be exec as the callback.
*/
private void setBadge (final JSONArray args,
final CallbackContext callback) {
cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
impl.clearBadge();
impl.setBadge(args.optInt(0));
int badge = impl.getBadge();
callback.success(badge);
}
});
}
/**
* Check support for badges.
*
* @param callback The function to be exec as the callback.
*/
private void checkSupport (final CallbackContext callback) {
cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
boolean support = impl.isSupported();
PluginResult result = new PluginResult(OK, support);
callback.sendPluginResult(result);
}
});
}
/**
* Returns the context of the activity.
*/
private Context getContext () {
return cordova.getActivity();
}
}
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.badge;
import android.content.Context;
import android.content.SharedPreferences;
import org.json.JSONException;
import org.json.JSONObject;
import me.leolin.shortcutbadger.ShortcutBadger;
import static me.leolin.shortcutbadger.ShortcutBadger.isBadgeCounterSupported;
/**
* Implementation of the badge interface methods.
*/
@SuppressWarnings("WeakerAccess")
public final class BadgeImpl {
// The name for the shared preferences key
private static final String BADGE_KEY = "badge";
// The name for the shared preferences key
private static final String CONFIG_KEY = "badge.config";
// The application context
private final Context ctx;
// if the device does support native badges
private final boolean isSupported;
/**
* Initializes the impl with the context of the app.
*
* @param context The app context.
*/
public BadgeImpl (Context context) {
if (isBadgeCounterSupported(context)) {
ctx = context;
isSupported = true;
} else {
ctx = context.getApplicationContext();
isSupported = isBadgeCounterSupported(ctx);
}
ShortcutBadger.applyCount(ctx, getBadge());
}
/**
* Clear the badge number.
*/
public void clearBadge() {
saveBadge(0);
ShortcutBadger.removeCount(ctx);
}
/**
* Get the badge number.
*
* @return The badge number
*/
public int getBadge() {
return getPrefs().getInt(BADGE_KEY, 0);
}
/**
* Check if the device/launcher does support badges.
*/
public boolean isSupported() {
return isSupported;
}
/**
* Set the badge number.
*
* @param badge The number to set as the badge number.
*/
public void setBadge (int badge) {
saveBadge(badge);
ShortcutBadger.applyCount(ctx, badge);
}
/**
* Get the persisted config map.
*/
public JSONObject loadConfig() {
String json = getPrefs().getString(CONFIG_KEY, "{}");
try {
return new JSONObject(json);
} catch (JSONException e) {
return new JSONObject();
}
}
/**
* Persist the config map so that `autoClear` has same value after restart.
*
* @param config The config map to persist.
*/
public void saveConfig (JSONObject config) {
SharedPreferences.Editor editor = getPrefs().edit();
editor.putString(CONFIG_KEY, config.toString());
editor.apply();
}
/**
* Persist the badge of the app icon so that `getBadge` is able to return
* the badge number back to the client.
*
* @param badge The badge number to persist.
*/
private void saveBadge (int badge) {
SharedPreferences.Editor editor = getPrefs().edit();
editor.putInt(BADGE_KEY, badge);
editor.apply();
}
/**
* The Local storage for the application.
*/
private SharedPreferences getPrefs() {
return ctx.getSharedPreferences(BADGE_KEY, Context.MODE_PRIVATE);
}
}
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
repositories {
mavenCentral()
}
if (!project.ext.has('appShortcutBadgerVersion')) {
ext.appShortcutBadgerVersion = '1.1.22'
}
if (!project.ext.has('appShortcutBadgerCustom')) {
dependencies {
compile "me.leolin:ShortcutBadger:${appShortcutBadgerVersion}@aar"
}
}
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
// Instance of the Favico.js libary
exports.favico = new cordova.plugins.notification.badge.Favico({
animation: 'none'
});
// Holds the current badge number
var BADGE_KEY = 'cordova_badge_number';
// Holds the saved badge config
var CONFIG_KEY = 'APPBadgeConfigKey';
/**
* Clears the badge of the app icon.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.clear = function (success, error) {
exports.set(success, error, [0]);
};
/**
* Gets the badge of the app icon.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.get = function (success, error) {
var badge = localStorage[BADGE_KEY];
success(badge || 0);
};
/**
* Sets the badge of the app icon.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Int ] badge The badge number
*
* @return [ Void ]
*/
exports.set = function (success, error, args) {
var badge = args[0];
exports.saveBadge(badge);
exports.favico.badge(badge);
success(badge);
};
/**
* Save the badge config.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Int ] config The config map
*
* @return [ Void ]
*/
exports.save = function (success, error, args) {
var config = args[0] || null,
json = JSON.stringify(config);
localStorage[CONFIG_KEY] = json;
};
/**
* Load the badge config.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.load = function (success, error) {
var json = localStorage[CONFIG_KEY],
config = JSON.parse(json || null);
success(config);
};
/**
* Persist the badge of the app icon so that `getBadge` is able to return the
* badge number back to the client.
*
* @param [ Int ] badge The badge number
*
* @return [ Void ]
*/
exports.saveBadge = function (badge) {
localStorage[BADGE_KEY] = badge;
};
cordova.commandProxy.add('Badge', exports);
/**
* @license MIT
* @fileOverview Favico animations
* @author Miroslav Magda, http://blog.ejci.net
* @version 0.3.10
*/
!function(){var e=function(e){"use strict";function t(e){if(e.paused||e.ended||g)return!1;try{f.clearRect(0,0,s,l),f.drawImage(e,0,0,s,l)}catch(o){}p=setTimeout(function(){t(e)},S.duration),O.setIcon(h)}function o(e){var t=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(t,function(e,t,o,n){return t+t+o+o+n+n});var o=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return o?{r:parseInt(o[1],16),g:parseInt(o[2],16),b:parseInt(o[3],16)}:!1}function n(e,t){var o,n={};for(o in e)n[o]=e[o];for(o in t)n[o]=t[o];return n}function r(){return b.hidden||b.msHidden||b.webkitHidden||b.mozHidden}e=e?e:{};var i,a,l,s,h,f,c,d,u,y,w,g,x,m,p,b,v={bgColor:"#d00",textColor:"#fff",fontFamily:"sans-serif",fontStyle:"bold",type:"circle",position:"down",animation:"slide",elementId:!1,dataUrl:!1,win:window};x={},x.ff="undefined"!=typeof InstallTrigger,x.chrome=!!window.chrome,x.opera=!!window.opera||navigator.userAgent.indexOf("Opera")>=0,x.ie=/*@cc_on!@*/!1,x.safari=Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0,x.supported=x.chrome||x.ff||x.opera;var C=[];w=function(){},d=g=!1;var E=function(){i=n(v,e),i.bgColor=o(i.bgColor),i.textColor=o(i.textColor),i.position=i.position.toLowerCase(),i.animation=S.types[""+i.animation]?i.animation:v.animation,b=i.win.document;var t=i.position.indexOf("up")>-1,r=i.position.indexOf("left")>-1;if(t||r)for(var d=0;d<S.types[""+i.animation].length;d++){var u=S.types[""+i.animation][d];t&&(u.y=u.y<.6?u.y-.4:u.y-2*u.y+(1-u.w)),r&&(u.x=u.x<.6?u.x-.4:u.x-2*u.x+(1-u.h)),S.types[""+i.animation][d]=u}i.type=A[""+i.type]?i.type:v.type,a=O.getIcon(),h=document.createElement("canvas"),c=document.createElement("img"),a.hasAttribute("href")?(c.setAttribute("crossOrigin","anonymous"),c.onload=function(){l=c.height>0?c.height:32,s=c.width>0?c.width:32,h.height=l,h.width=s,f=h.getContext("2d"),M.ready()},c.setAttribute("src",a.getAttribute("href"))):(c.onload=function(){l=32,s=32,c.height=l,c.width=s,h.height=l,h.width=s,f=h.getContext("2d"),M.ready()},c.setAttribute("src",""))},M={};M.ready=function(){d=!0,M.reset(),w()},M.reset=function(){d&&(C=[],u=!1,y=!1,f.clearRect(0,0,s,l),f.drawImage(c,0,0,s,l),O.setIcon(h),window.clearTimeout(m),window.clearTimeout(p))},M.start=function(){if(d&&!y){var e=function(){u=C[0],y=!1,C.length>0&&(C.shift(),M.start())};if(C.length>0){y=!0;var t=function(){["type","animation","bgColor","textColor","fontFamily","fontStyle"].forEach(function(e){e in C[0].options&&(i[e]=C[0].options[e])}),S.run(C[0].options,function(){e()},!1)};u?S.run(u.options,function(){t()},!0):t()}}};var A={},I=function(e){return e.n="number"==typeof e.n?Math.abs(0|e.n):e.n,e.x=s*e.x,e.y=l*e.y,e.w=s*e.w,e.h=l*e.h,e.len=(""+e.n).length,e};A.circle=function(e){e=I(e);var t=!1;2===e.len?(e.x=e.x-.4*e.w,e.w=1.4*e.w,t=!0):e.len>=3&&(e.x=e.x-.65*e.w,e.w=1.65*e.w,t=!0),f.clearRect(0,0,s,l),f.drawImage(c,0,0,s,l),f.beginPath(),f.font=i.fontStyle+" "+Math.floor(e.h*(e.n>99?.85:1))+"px "+i.fontFamily,f.textAlign="center",t?(f.moveTo(e.x+e.w/2,e.y),f.lineTo(e.x+e.w-e.h/2,e.y),f.quadraticCurveTo(e.x+e.w,e.y,e.x+e.w,e.y+e.h/2),f.lineTo(e.x+e.w,e.y+e.h-e.h/2),f.quadraticCurveTo(e.x+e.w,e.y+e.h,e.x+e.w-e.h/2,e.y+e.h),f.lineTo(e.x+e.h/2,e.y+e.h),f.quadraticCurveTo(e.x,e.y+e.h,e.x,e.y+e.h-e.h/2),f.lineTo(e.x,e.y+e.h/2),f.quadraticCurveTo(e.x,e.y,e.x+e.h/2,e.y)):f.arc(e.x+e.w/2,e.y+e.h/2,e.h/2,0,2*Math.PI),f.fillStyle="rgba("+i.bgColor.r+","+i.bgColor.g+","+i.bgColor.b+","+e.o+")",f.fill(),f.closePath(),f.beginPath(),f.stroke(),f.fillStyle="rgba("+i.textColor.r+","+i.textColor.g+","+i.textColor.b+","+e.o+")","number"==typeof e.n&&e.n>999?f.fillText((e.n>9999?9:Math.floor(e.n/1e3))+"k+",Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.2*e.h)):f.fillText(e.n,Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.15*e.h)),f.closePath()},A.rectangle=function(e){e=I(e);var t=!1;2===e.len?(e.x=e.x-.4*e.w,e.w=1.4*e.w,t=!0):e.len>=3&&(e.x=e.x-.65*e.w,e.w=1.65*e.w,t=!0),f.clearRect(0,0,s,l),f.drawImage(c,0,0,s,l),f.beginPath(),f.font=i.fontStyle+" "+Math.floor(e.h*(e.n>99?.9:1))+"px "+i.fontFamily,f.textAlign="center",f.fillStyle="rgba("+i.bgColor.r+","+i.bgColor.g+","+i.bgColor.b+","+e.o+")",f.fillRect(e.x,e.y,e.w,e.h),f.fillStyle="rgba("+i.textColor.r+","+i.textColor.g+","+i.textColor.b+","+e.o+")","number"==typeof e.n&&e.n>999?f.fillText((e.n>9999?9:Math.floor(e.n/1e3))+"k+",Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.2*e.h)):f.fillText(e.n,Math.floor(e.x+e.w/2),Math.floor(e.y+e.h-.15*e.h)),f.closePath()};var T=function(e,t){t=("string"==typeof t?{animation:t}:t)||{},w=function(){try{if("number"==typeof e?e>0:""!==e){var n={type:"badge",options:{n:e}};if("animation"in t&&S.types[""+t.animation]&&(n.options.animation=""+t.animation),"type"in t&&A[""+t.type]&&(n.options.type=""+t.type),["bgColor","textColor"].forEach(function(e){e in t&&(n.options[e]=o(t[e]))}),["fontStyle","fontFamily"].forEach(function(e){e in t&&(n.options[e]=t[e])}),C.push(n),C.length>100)throw new Error("Too many badges requests in queue.");M.start()}else M.reset()}catch(r){throw new Error("Error setting badge. Message: "+r.message)}},d&&w()},U=function(e){w=function(){try{var t=e.width,o=e.height,n=document.createElement("img"),r=o/l>t/s?t/s:o/l;n.setAttribute("crossOrigin","anonymous"),n.onload=function(){f.clearRect(0,0,s,l),f.drawImage(n,0,0,s,l),O.setIcon(h)},n.setAttribute("src",e.getAttribute("src")),n.height=o/r,n.width=t/r}catch(i){throw new Error("Error setting image. Message: "+i.message)}},d&&w()},R=function(e){w=function(){try{if("stop"===e)return g=!0,M.reset(),void(g=!1);e.addEventListener("play",function(){t(this)},!1)}catch(o){throw new Error("Error setting video. Message: "+o.message)}},d&&w()},L=function(e){if(window.URL&&window.URL.createObjectURL||(window.URL=window.URL||{},window.URL.createObjectURL=function(e){return e}),x.supported){var o=!1;navigator.getUserMedia=navigator.getUserMedia||navigator.oGetUserMedia||navigator.msGetUserMedia||navigator.mozGetUserMedia||navigator.webkitGetUserMedia,w=function(){try{if("stop"===e)return g=!0,M.reset(),void(g=!1);o=document.createElement("video"),o.width=s,o.height=l,navigator.getUserMedia({video:!0,audio:!1},function(e){o.src=URL.createObjectURL(e),o.play(),t(o)},function(){})}catch(n){throw new Error("Error setting webcam. Message: "+n.message)}},d&&w()}},O={};O.getIcon=function(){var e=!1,t=function(){for(var e=b.getElementsByTagName("head")[0].getElementsByTagName("link"),t=e.length,o=t-1;o>=0;o--)if(/(^|\s)icon(\s|$)/i.test(e[o].getAttribute("rel")))return e[o];return!1};return i.element?e=i.element:i.elementId?(e=b.getElementById(i.elementId),e.setAttribute("href",e.getAttribute("src"))):(e=t(),e===!1&&(e=b.createElement("link"),e.setAttribute("rel","icon"),b.getElementsByTagName("head")[0].appendChild(e))),e.setAttribute("type","image/png"),e},O.setIcon=function(e){var t=e.toDataURL("image/png");if(i.dataUrl&&i.dataUrl(t),i.element)i.element.setAttribute("href",t),i.element.setAttribute("src",t);else if(i.elementId){var o=b.getElementById(i.elementId);o.setAttribute("href",t),o.setAttribute("src",t)}else if(x.ff||x.opera){var n=a;a=b.createElement("link"),x.opera&&a.setAttribute("rel","icon"),a.setAttribute("rel","icon"),a.setAttribute("type","image/png"),b.getElementsByTagName("head")[0].appendChild(a),a.setAttribute("href",t),n.parentNode&&n.parentNode.removeChild(n)}else a.setAttribute("href",t)};var S={};return S.duration=40,S.types={},S.types.fade=[{x:.4,y:.4,w:.6,h:.6,o:0},{x:.4,y:.4,w:.6,h:.6,o:.1},{x:.4,y:.4,w:.6,h:.6,o:.2},{x:.4,y:.4,w:.6,h:.6,o:.3},{x:.4,y:.4,w:.6,h:.6,o:.4},{x:.4,y:.4,w:.6,h:.6,o:.5},{x:.4,y:.4,w:.6,h:.6,o:.6},{x:.4,y:.4,w:.6,h:.6,o:.7},{x:.4,y:.4,w:.6,h:.6,o:.8},{x:.4,y:.4,w:.6,h:.6,o:.9},{x:.4,y:.4,w:.6,h:.6,o:1}],S.types.none=[{x:.4,y:.4,w:.6,h:.6,o:1}],S.types.pop=[{x:1,y:1,w:0,h:0,o:1},{x:.9,y:.9,w:.1,h:.1,o:1},{x:.8,y:.8,w:.2,h:.2,o:1},{x:.7,y:.7,w:.3,h:.3,o:1},{x:.6,y:.6,w:.4,h:.4,o:1},{x:.5,y:.5,w:.5,h:.5,o:1},{x:.4,y:.4,w:.6,h:.6,o:1}],S.types.popFade=[{x:.75,y:.75,w:0,h:0,o:0},{x:.65,y:.65,w:.1,h:.1,o:.2},{x:.6,y:.6,w:.2,h:.2,o:.4},{x:.55,y:.55,w:.3,h:.3,o:.6},{x:.5,y:.5,w:.4,h:.4,o:.8},{x:.45,y:.45,w:.5,h:.5,o:.9},{x:.4,y:.4,w:.6,h:.6,o:1}],S.types.slide=[{x:.4,y:1,w:.6,h:.6,o:1},{x:.4,y:.9,w:.6,h:.6,o:1},{x:.4,y:.9,w:.6,h:.6,o:1},{x:.4,y:.8,w:.6,h:.6,o:1},{x:.4,y:.7,w:.6,h:.6,o:1},{x:.4,y:.6,w:.6,h:.6,o:1},{x:.4,y:.5,w:.6,h:.6,o:1},{x:.4,y:.4,w:.6,h:.6,o:1}],S.run=function(e,t,o,a){var l=S.types[r()?"none":i.animation];return a=o===!0?"undefined"!=typeof a?a:l.length-1:"undefined"!=typeof a?a:0,t=t?t:function(){},a<l.length&&a>=0?(A[i.type](n(e,l[a])),m=setTimeout(function(){o?a-=1:a+=1,S.run(e,t,o,a)},S.duration),O.setIcon(h),void 0):void t()},E(),{badge:T,video:R,image:U,webcam:L,reset:M.reset,browser:{supported:x.supported}}};"undefined"!=typeof define&&define.amd?define([],function(){return e}):"undefined"!=typeof module&&module.exports?module.exports=e:this.Favico=e}();
\ No newline at end of file
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import <Cordova/CDVPlugin.h>
@interface APPBadge : CDVPlugin
// Load the badge config
- (void) load:(CDVInvokedUrlCommand *)command;
// Save the badge config
- (void) save:(CDVInvokedUrlCommand *)command;
// Clear the badge number
- (void) clear:(CDVInvokedUrlCommand *)command;
// Set the badge number
- (void) set:(CDVInvokedUrlCommand *)command;
// Get the badge number
- (void) get:(CDVInvokedUrlCommand *)command;
// Check permission to show badges
- (void) check:(CDVInvokedUrlCommand *)command;
// Request permission to show badges
- (void) request:(CDVInvokedUrlCommand *)command;
@end
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPBadge.h"
@import UserNotifications;
@implementation APPBadge
static NSString * const kAPPBadgeConfigKey = @"APPBadgeConfigKey";
#pragma mark -
#pragma mark Interface
/**
* Load the badge config.
*/
- (void) load:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
NSDictionary *config = [self.settings objectForKey:kAPPBadgeConfigKey];
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:config];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* Save the badge config.
*/
- (void) save:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
[self.settings setObject:[command argumentAtIndex:0]
forKey:kAPPBadgeConfigKey];
}];
}
/**
* Clear the badge number.
*/
- (void) clear:(CDVInvokedUrlCommand *)command
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.app setApplicationIconBadgeNumber:0];
[self sendPluginResult:CDVCommandStatus_OK
messageAsLong:0
callbackId:command.callbackId];
});
}
/**
* Set the badge number.
*/
- (void) set:(CDVInvokedUrlCommand *)command
{
NSArray* args = [command arguments];
int number = [[args objectAtIndex:0] intValue];
dispatch_async(dispatch_get_main_queue(), ^{
[self.app setApplicationIconBadgeNumber:number];
[self sendPluginResult:CDVCommandStatus_OK
messageAsLong:number
callbackId:command.callbackId];
});
}
/**
* Get the badge number.
*/
- (void) get:(CDVInvokedUrlCommand *)command
{
dispatch_async(dispatch_get_main_queue(), ^{
long badge = [self.app applicationIconBadgeNumber];
[self sendPluginResult:CDVCommandStatus_OK
messageAsLong:badge
callbackId:command.callbackId];
});
}
/**
* Check permission to show badges.
*/
- (void) check:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
UNUserNotificationCenter *center =
UNUserNotificationCenter.currentNotificationCenter;
[center getNotificationSettingsWithCompletionHandler:
^(UNNotificationSettings* settings) {
BOOL authorized =
settings.authorizationStatus == UNAuthorizationStatusAuthorized;
BOOL enabled =
settings.badgeSetting == UNNotificationSettingEnabled;
[self sendPluginResult:CDVCommandStatus_OK
messageAsBool:authorized && enabled
callbackId:command.callbackId];
}];
}];
}
/**
* Request permission to show badges.
*/
- (void) request:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
UNUserNotificationCenter *center =
UNUserNotificationCenter.currentNotificationCenter;
UNAuthorizationOptions options = UNAuthorizationOptionBadge;
[center requestAuthorizationWithOptions:options
completionHandler:^(BOOL granted, NSError* e) {
[self sendPluginResult:CDVCommandStatus_OK
messageAsBool:granted
callbackId:command.callbackId];
}];
}];
}
#pragma mark -
#pragma mark Helper
/**
* Short hand for shared application instance.
*/
- (UIApplication*) app
{
return [UIApplication sharedApplication];
}
/**
* Short hand for standard user defaults instance.
*/
- (NSUserDefaults*) settings
{
return [NSUserDefaults standardUserDefaults];
}
/**
* Sends a plugin result with the specified status and message.
*/
- (void) sendPluginResult:(CDVCommandStatus)status
messageAsBool:(BOOL)msg
callbackId:(NSString*)callbackId
{
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:msg];
[self.commandDelegate sendPluginResult:result
callbackId:callbackId];
}
/**
* Sends a plugin result with the specified status and message.
*/
- (void) sendPluginResult:(CDVCommandStatus)status
messageAsLong:(long)msg
callbackId:(NSString*)callbackId
{
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDouble:msg];
[self.commandDelegate sendPluginResult:result
callbackId:callbackId];
}
@end
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import <Cordova/CDVPlugin.h>
@interface APPBadge : CDVPlugin
// Load the badge config
- (void) load:(CDVInvokedUrlCommand *)command;
// Save the badge config
- (void) save:(CDVInvokedUrlCommand *)command;
// Clear the badge number
- (void) clear:(CDVInvokedUrlCommand *)command;
// Set the badge number
- (void) set:(CDVInvokedUrlCommand *)command;
// Get the badge number
- (void) get:(CDVInvokedUrlCommand *)command;
@end
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPBadge.h"
#import "DockCircularProgressBar.h"
#import "DockDownloadProgressBar.h"
@implementation APPBadge
static NSString * const kAPPBadgeConfigKey = @"APPBadgeConfigKey";
enum APPBadgeIndicator { kAPPBadgeIndicatorBadge, kAPPBadgeIndicatorCircular, kAPPBadgeIndicatorDownload };
#pragma mark -
#pragma mark Interface
/**
* Load the badge config.
*/
- (void) load:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:self.config];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* Save the badge config.
*/
- (void) save:(CDVInvokedUrlCommand *)command
{
int badge = self.badgeValue;
[self.commandDelegate runInBackground:^{
[self.settings setObject:[command argumentAtIndex:0]
forKey:kAPPBadgeConfigKey];
if (badge != 0) {
[self setBadgeValue:badge];
}
}];
}
/**
* Clear the badge number.
*/
- (void) clear:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
[self sendPluginResult:CDVCommandStatus_OK
messageAsLong:0
callbackId:command.callbackId];
}];
dispatch_async(dispatch_get_main_queue(), ^{
self.dock.badgeLabel = @"";
[self.cbar clear];
[self.dbar clear];
});
}
/**
* Set the badge number.
*/
- (void) set:(CDVInvokedUrlCommand *)command
{
NSArray* args = [command arguments];
int number = [[args objectAtIndex:0] intValue];
if (number == 0) {
return [self clear:command];
}
[self.commandDelegate runInBackground:^{
[self setBadgeValue:number];
[self sendPluginResult:CDVCommandStatus_OK
messageAsLong:number
callbackId:command.callbackId];
}];
}
/**
* Get the badge number.
*/
- (void) get:(CDVInvokedUrlCommand *)command
{
dispatch_async(dispatch_get_main_queue(), ^{
[self sendPluginResult:CDVCommandStatus_OK
messageAsLong:self.badgeValue
callbackId:command.callbackId];
});
}
#pragma mark -
#pragma mark Core
/**
* Set the badge value.
*
* @param [ Int ] value The value to set.
*
* @return [ Void ]
*/
- (void) setBadgeValue:(int)value
{
dispatch_async(dispatch_get_main_queue(), ^{
switch (self.indicator) {
case kAPPBadgeIndicatorCircular:
self.dock.badgeLabel = @"";
[self.dbar clear];
[self.cbar setProgress:value/100.0];
[self.cbar setShowPercent:YES];
[self.cbar updateProgressBar];
break;
case kAPPBadgeIndicatorDownload:
self.dock.badgeLabel = @"";
[self.cbar clear];
[self.dbar setProgress:value/100.0];
[self.dbar updateProgressBar];
break;
default:
[self.cbar clear];
[self.dbar clear];
self.dock.badgeLabel = @(value).stringValue;
}
});
}
/**
* Get the badge value.
*
* @return [ Int ]
*/
- (int) badgeValue
{
switch (self.indicator) {
case kAPPBadgeIndicatorCircular:
return rint(100 * self.cbar.doubleValue);
break;
case kAPPBadgeIndicatorDownload:
return rint(100 * self.dbar.doubleValue);
break;
default:
return [self.dock badgeLabel].intValue;
}
}
#pragma mark -
#pragma mark Helper
/**
* Short hand for shared dock instance.
*/
- (NSDockTile*) dock
{
return [NSApp dockTile];
}
/**
* Short hand for shared circular progress bar.
*/
- (DockCircularProgressBar*) cbar
{
return [DockCircularProgressBar sharedDockCircularProgressBar];
}
/**
* Short hand for shared circular progress bar.
*/
- (DockDownloadProgressBar*) dbar
{
return [DockDownloadProgressBar sharedDockDownloadProgressBar];
}
/**
* Short hand for standard user defaults instance.
*/
- (NSUserDefaults*) settings
{
return [NSUserDefaults standardUserDefaults];
}
/**
* The saved config properties.
*/
- (NSDictionary*) config
{
return [self.settings objectForKey:kAPPBadgeConfigKey];
}
/**
* The indicator type.
*
* @return [ NSString* ]
*/
- (enum APPBadgeIndicator) indicator
{
NSString* indicator = [self.config objectForKey:@"indicator"];
if ([indicator isEqualToString:@"circular"])
return kAPPBadgeIndicatorCircular;
if ([indicator isEqualToString:@"download"])
return kAPPBadgeIndicatorDownload;
return kAPPBadgeIndicatorBadge;
}
/**
* Sends a plugin result with the specified status and message.
*/
- (void) sendPluginResult:(CDVCommandStatus)status
messageAsBool:(BOOL)msg
callbackId:(NSString*)callbackId
{
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:msg];
[self.commandDelegate sendPluginResult:result
callbackId:callbackId];
}
/**
* Sends a plugin result with the specified status and message.
*/
- (void) sendPluginResult:(CDVCommandStatus)status
messageAsLong:(long)msg
callbackId:(NSString*)callbackId
{
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDouble:msg];
[self.commandDelegate sendPluginResult:result
callbackId:callbackId];
}
@end
// Borrow from src/chrome/browser/ui/cocoa/dock_icon.h
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <Cocoa/Cocoa.h>
@interface DockCircularProgressBar : NSObject
+ (DockCircularProgressBar*)sharedDockCircularProgressBar;
- (void)updateProgressBar;
- (void)hideProgressBar;
// Indicates whether the progress indicator should be in an indeterminate state
// or not.
- (void)setIndeterminate:(BOOL)indeterminate;
// Indicates the amount of progress made of the download. Ranges from [0..1].
- (void)setProgress:(float)progress;
// Indicates whether the progress number should be showed in circular process bar.
- (void)setShowPercent:(BOOL)show_percent;
- (void)clear;
@property (readonly, getter=getProgress) double doubleValue;
@end
// Borrow from src/chrome/browser/ui/cocoa/dock_icon.mm
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "DockCircularProgressBar.h"
namespace {
// The fraction of the size of the dock icon that the badge is.
const float kBadgeFraction = 0.4f;
// The indentation of the badge.
const float kBadgeIndent = 5.0f;
class ScopedNSGraphicsContextSaveGState {
public:
ScopedNSGraphicsContextSaveGState() {
[NSGraphicsContext saveGraphicsState];
}
~ScopedNSGraphicsContextSaveGState() {
[NSGraphicsContext restoreGraphicsState];
}
};
}
@interface DockTileView : NSView {
@private
BOOL hide_progress_bar_;
BOOL show_percent_;
BOOL indeterminate_;
//float progress_;
}
// Indicates whether the progress indicator should be in an indeterminate state
// or not.
@property BOOL indeterminate;
// Indicates the amount of progress made of the download. Ranges from [0..1].
@property float progress;
// Indicates whether the progress number should be showed in circular process bar.
@property BOOL showPercent;
@property BOOL hideProgressBar;
@end
@implementation DockTileView
@synthesize indeterminate = indeterminate_;
@synthesize progress = progress_;
@synthesize showPercent = show_percent_;
@synthesize hideProgressBar = hide_progress_bar_;
- (void)drawRect:(NSRect)dirtyRect {
// Not -[NSApplication applicationIconImage]; that fails to return a pasted
// custom icon.
NSString* appPath = [[NSBundle mainBundle] bundlePath];
NSImage* appIcon = [[NSWorkspace sharedWorkspace] iconForFile:appPath];
[appIcon drawInRect:[self bounds]
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1.0];
if (hide_progress_bar_)
return;
NSRect badgeRect = [self bounds];
badgeRect.size.height = (int)(kBadgeFraction * badgeRect.size.height);
int newWidth = kBadgeFraction * NSWidth(badgeRect);
badgeRect.origin.x = NSWidth(badgeRect) - newWidth;
badgeRect.size.width = newWidth;
CGFloat badgeRadius = NSMidY(badgeRect);
badgeRect.origin.x -= kBadgeIndent;
badgeRect.origin.y += kBadgeIndent;
NSPoint badgeCenter = NSMakePoint(NSMidX(badgeRect), NSMidY(badgeRect));
// Background
NSColor* backgroundColor = [NSColor colorWithCalibratedRed:0.85
green:0.85
blue:0.85
alpha:1.0];
NSColor* backgroundHighlight =
[backgroundColor blendedColorWithFraction:0.85
ofColor:[NSColor whiteColor]];
NSGradient* backgroundGradient =
[[NSGradient alloc] initWithStartingColor:backgroundHighlight
endingColor:backgroundColor];
NSBezierPath* badgeEdge = [NSBezierPath bezierPathWithOvalInRect:badgeRect];
{
ScopedNSGraphicsContextSaveGState scopedGState;
[badgeEdge addClip];
[backgroundGradient drawFromCenter:badgeCenter
radius:0.0
toCenter:badgeCenter
radius:badgeRadius
options:0];
}
// Slice
if (!indeterminate_) {
NSColor* sliceColor = [NSColor colorWithCalibratedRed:0.45
green:0.8
blue:0.25
alpha:1.0];
NSColor* sliceHighlight =
[sliceColor blendedColorWithFraction:0.4
ofColor:[NSColor whiteColor]];
NSGradient* sliceGradient =
[[NSGradient alloc] initWithStartingColor:sliceHighlight
endingColor:sliceColor];
NSBezierPath* progressSlice;
if (progress_ >= 1.0) {
progressSlice = [NSBezierPath bezierPathWithOvalInRect:badgeRect];
} else {
CGFloat endAngle = 90.0 - 360.0 * progress_;
if (endAngle < 0.0)
endAngle += 360.0;
progressSlice = [NSBezierPath bezierPath];
[progressSlice moveToPoint:badgeCenter];
[progressSlice appendBezierPathWithArcWithCenter:badgeCenter
radius:badgeRadius
startAngle:90.0
endAngle:endAngle
clockwise:YES];
[progressSlice closePath];
}
ScopedNSGraphicsContextSaveGState scopedGState;
[progressSlice addClip];
[sliceGradient drawFromCenter:badgeCenter
radius:0.0
toCenter:badgeCenter
radius:badgeRadius
options:0];
}
// Edge
{
ScopedNSGraphicsContextSaveGState scopedGState;
[[NSColor whiteColor] set];
NSShadow* shadow = [[NSShadow alloc] init];
[shadow setShadowOffset:NSMakeSize(0, -2)];
[shadow setShadowBlurRadius:2];
[shadow set];
[badgeEdge setLineWidth:2];
[badgeEdge stroke];
}
if (!show_percent_) return;
// Show percent.
NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
NSString* countString =
[formatter stringFromNumber:[NSNumber numberWithInt:(int)(progress_ * 100)]];
NSShadow* countShadow = [[NSShadow alloc] init];
[countShadow setShadowBlurRadius:3.0];
[countShadow setShadowColor:[NSColor whiteColor]];
[countShadow setShadowOffset:NSMakeSize(0.0, 0.0)];
NSMutableDictionary* countAttrsDict =
[NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSColor blackColor], NSForegroundColorAttributeName,
countShadow, NSShadowAttributeName,
nil];
CGFloat countFontSize = badgeRadius;
NSSize countSize = NSZeroSize;
NSAttributedString* countAttrString;
while (1) {
NSFont* countFont = [NSFont fontWithName:@"Helvetica-Bold"
size:countFontSize];
// This will generally be plain Helvetica.
if (!countFont)
countFont = [NSFont userFontOfSize:countFontSize];
// Continued failure would generate an NSException.
if (!countFont)
break;
[countAttrsDict setObject:countFont forKey:NSFontAttributeName];
countAttrString =
[[NSAttributedString alloc] initWithString:countString
attributes:countAttrsDict];
countSize = [countAttrString size];
if (countSize.width > badgeRadius * 1.5) {
countFontSize -= 1.0;
} else {
break;
}
}
NSPoint countOrigin = badgeCenter;
countOrigin.x -= countSize.width / 2;
countOrigin.y -= countSize.height / 2.2; // tweak; otherwise too low
[countAttrString drawAtPoint:countOrigin];
}
@end
@implementation DockCircularProgressBar
+ (DockCircularProgressBar*) sharedDockCircularProgressBar {
static DockCircularProgressBar* progress_bar;
NSDockTile* dockTile = [NSApp dockTile];
if (!progress_bar) {
progress_bar = [[DockCircularProgressBar alloc] init];
}
if ([dockTile contentView] == NULL) {
DockTileView* dockTileView = [[DockTileView alloc] init];
[dockTile setContentView:dockTileView];
}
return progress_bar;
}
- (void)updateProgressBar {
NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
DockTileView* dockTileView = (DockTileView*)([dockTile contentView]);
[dockTileView setHideProgressBar:NO];
[[NSApp dockTile] display];
}
-(void)hideProgressBar {
NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
DockTileView* dockTileView = (DockTileView*)([dockTile contentView]);
[dockTileView setHideProgressBar:YES];
[[NSApp dockTile] display];
}
- (void)setIndeterminate:(BOOL)indeterminate {
NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
DockTileView* dockTileView = (DockTileView*)([dockTile contentView]);
if (indeterminate != [dockTileView indeterminate]) {
[dockTileView setIndeterminate:indeterminate];
}
}
- (void)setProgress:(float) progress {
NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
DockTileView* dockTileView = (DockTileView*)([dockTile contentView]);
[dockTileView setProgress:progress];
}
- (void)setShowPercent:(BOOL)show_percent {
NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
DockTileView* dockTileView = (DockTileView*)([dockTile contentView]);
[dockTileView setShowPercent:show_percent];
}
- (void)clear {
[[NSApp dockTile] setContentView:NULL];
}
- (double) getProgress
{
NSDockTile* dockTile = [[NSApplication sharedApplication] dockTile];
DockTileView* dockTileView = (DockTileView*)([dockTile contentView]);
return (double)dockTileView.progress;
}
@end
#import <Cocoa/Cocoa.h>
@interface DockDownloadProgressBar : NSProgressIndicator
+ (DockDownloadProgressBar*)sharedDockDownloadProgressBar;
- (void)setProgress:(float)progress;
- (void)updateProgressBar;
- (void)hideProgressBar;
- (void)clear;
@end
#import "DockDownloadProgressBar.h"
@implementation DockDownloadProgressBar
+ (DockDownloadProgressBar*)sharedDockDownloadProgressBar {
static DockDownloadProgressBar* progress_bar;
NSDockTile* dock_tile = [NSApp dockTile];
if (!progress_bar) {
progress_bar = [[DockDownloadProgressBar alloc] initWithFrame:
NSMakeRect(0.0f, 0.0f, dock_tile.size.width, 15.0f)];
[progress_bar setStyle:NSProgressIndicatorBarStyle];
[progress_bar setIndeterminate:NO];
[progress_bar setBezeled:YES];
[progress_bar setMinValue:0];
[progress_bar setMaxValue:1];
[progress_bar setHidden:NO];
}
if ([dock_tile contentView] == NULL) {
NSImageView* content_view = [[NSImageView alloc] init];
[content_view setImage:[NSApp applicationIconImage]];
[dock_tile setContentView:content_view];
[content_view addSubview:progress_bar];
}
return progress_bar;
}
- (void)drawRect:(NSRect)dirtyRect {
// Draw edges of rounded rect.
NSRect rect = NSInsetRect([self bounds], 1.0, 1.0);
CGFloat radius = rect.size.height / 2;
NSBezierPath* bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect
xRadius:radius
yRadius:radius];
[bezier_path setLineWidth:2.0];
[[NSColor grayColor] set];
[bezier_path stroke];
// Fill the rounded rect.
rect = NSInsetRect(rect, 2.0, 2.0);
radius = rect.size.height / 2;
bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius];
[bezier_path setLineWidth:1.0];
[bezier_path addClip];
// Calculate the progress width.
rect.size.width = floor(rect.size.width * ([self doubleValue] / [self maxValue]));
// Fill the progress bar with color blue.
[[NSColor colorWithSRGBRed:0.2 green:0.6 blue:1 alpha:1] set];
NSRectFill(rect);
}
- (void)updateProgressBar {
[self setHidden:NO];
[[NSApp dockTile] display];
}
- (void)hideProgressBar {
[self setHidden:YES];
[[NSApp dockTile] display];
}
- (void)setProgress:(float)progress {
[self setDoubleValue:progress];
}
- (void)clear {
[[NSApp dockTile] setContentView:NULL];
}
@end
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
var appData = Windows.Storage.ApplicationData.current,
CONFIG_KEY = 'APPBadgeConfigKey',
BADGE_KEY = 'cordova_badge_number';
/**
* Clear the badge number.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.clear = function (success, error) {
exports.set(success, error, [0]);
};
/**
* Get the badge number.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.get = function (success, error) {
var badge = appData.localSettings.values[BADGE_KEY];
success(badge || 0);
};
/**
* Set the badge number.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Int ] badge The badge number
*
* @return [ Void ]
*/
exports.set = function (success, error, args) {
var notifications = Windows.UI.Notifications,
badge = args[0],
type = notifications.BadgeTemplateType.badgeNumber,
xml = notifications.BadgeUpdateManager.getTemplateContent(type),
attrs = xml.getElementsByTagName('badge'),
notification = new notifications.BadgeNotification(xml);
attrs[0].setAttribute('value', badge);
notifications.BadgeUpdateManager
.createBadgeUpdaterForApplication()
.update(notification);
exports.saveBadge(badge);
success(badge);
};
/**
* Save the badge config.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Int ] config The config map
*
* @return [ Void ]
*/
exports.save = function (success, error, args) {
var config = args[0] || null,
json = JSON.stringify(config);
appData.localSettings.values[CONFIG_KEY] = json;
};
/**
* Load the badge config.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.load = function (success, error) {
var json = appData.localSettings.values[CONFIG_KEY],
config = JSON.parse(json || null);
success(config);
};
/**
* Persist the badge of the app icon so that `getBadge` is able to return the
* badge number back to the client.
*
* @param [ Int ] badge The badge number
*
* @return [ Void ]
*/
exports.saveBadge = function (badge) {
appData.localSettings.values[BADGE_KEY] = badge;
};
cordova.commandProxy.add('Badge', exports);
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Copyright (c) 2013-2016 by appPlant GmbH. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
-->
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="de.appplant.cordova.plugin.badge-tests"
version="0.7.4">
<name>Cordova Badge Plugin Tests</name>
<license>Apache 2.0</license>
<js-module src="tests.js" name="tests" />
</plugin>
/*
* Copyright (c) 2013-2016 by appPlant GmbH. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
exports.defineAutoTests = function() {
describe('Badge Plugin (cordova.plugins.notification.badge)', function () {
describe('Plugin availability', function () {
it("should exist", function() {
expect(cordova.plugins.notification.badge).toBeDefined();
});
it("should define clear", function() {
expect(cordova.plugins.notification.badge.clear).toBeDefined();
});
it("should define get", function() {
expect(cordova.plugins.notification.badge.get).toBeDefined();
});
it("should define set", function() {
expect(cordova.plugins.notification.badge.set).toBeDefined();
});
it("should define increase", function() {
expect(cordova.plugins.notification.badge.increase).toBeDefined();
});
it("should define decrease", function() {
expect(cordova.plugins.notification.badge.decrease).toBeDefined();
});
it("should define hasPermission", function() {
expect(cordova.plugins.notification.badge.hasPermission).toBeDefined();
});
it("should define registerPermission", function() {
expect(cordova.plugins.notification.badge.registerPermission).toBeDefined();
});
it("should define configure", function() {
expect(cordova.plugins.notification.badge.configure).toBeDefined();
});
});
describe('API callbacks', function () {
it("clear should invoke callback", function(done) {
cordova.plugins.notification.badge.clear(done);
});
it("get should invoke callback", function(done) {
cordova.plugins.notification.badge.get(done);
});
it("set should invoke callback", function(done) {
cordova.plugins.notification.badge.set(done);
});
it("increase should invoke callback", function(done) {
cordova.plugins.notification.badge.increase(done);
});
it("decrease should invoke callback", function(done) {
cordova.plugins.notification.badge.decrease(done);
});
it("hasPermission should invoke callback", function(done) {
cordova.plugins.notification.badge.hasPermission(done);
});
it("registerPermission should invoke callback", function(done) {
cordova.plugins.notification.badge.registerPermission(done);
});
});
describe('API functions', function () {
it("clear should set badge to 0", function(done) {
cordova.plugins.notification.badge.clear(function (badge) {
expect(badge).toBe(0);
done();
});
});
it("should return badge", function(done) {
cordova.plugins.notification.badge.set(10, function (badge) {
expect(badge).toBe(10);
cordova.plugins.notification.badge.get(function (badge2) {
expect(badge).toBe(badge2);
done();
});
});
});
it("should increase badge", function(done) {
cordova.plugins.notification.badge.set(10, function () {
cordova.plugins.notification.badge.increase(1, function (badge) {
expect(badge).toBe(11);
done();
});
});
});
it("should decrease badge", function(done) {
cordova.plugins.notification.badge.set(10, function () {
cordova.plugins.notification.badge.decrease(1, function (badge) {
expect(badge).toBe(9);
done();
});
});
});
it("hasPermission should return boolean", function(done) {
cordova.plugins.notification.badge.hasPermission(function (has) {
expect(has === true || has === false).toBe(true);
done();
});
});
it("registerPermission should return boolean", function(done) {
cordova.plugins.notification.badge.registerPermission(function (has) {
expect(has === true || has === false).toBe(true);
done();
});
});
});
});
};
/*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
var exec = require('cordova/exec'),
channel = require('cordova/channel'),
ua = navigator.userAgent.toLowerCase(),
isIOS = ua.indexOf('ipad') > -1 || ua.indexOf('iphone') > -1,
isMac = ua.indexOf('macintosh') > -1,
isWin = window.Windows !== undefined,
isAndroid = !isWin && ua.indexOf('android') > -1,
isWinPC = isWin && Windows.System.Profile.AnalyticsInfo.versionInfo.deviceFamily.includes('Desktop'),
isDesktop = isMac || isWinPC;
// Default settings
exports._config = { indicator: 'badge', autoClear: false };
/**
* Clears the badge number.
*
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Void ]
*/
exports.clear = function (callback, scope) {
this.exec('clear', null, callback, scope);
};
/**
* Sets the badge number.
*
* @param [ Int ] badge The new badge number.
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Void ]
*/
exports.set = function (badge, callback, scope) {
var args = [parseInt(badge) || 0];
this.requestPermission(function (granted) {
if (granted) {
this.exec('set', args, callback, scope);
}
}, this);
};
/**
* Gets the badge of the app icon.
*
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Void ]
*/
exports.get = function (callback, scope) {
this.exec('get', null, callback, scope);
};
/**
* Increases the badge number.
*
* @param [ Int ] count Number to add to the badge number.
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Void ]
*/
exports.increase = function (count, callback, scope) {
this.get(function (badge) {
this.set(badge + (count || 1), callback, scope);
}, this);
};
/**
* Decreases the badge number.
*
* @param [ Int ] count Number to substract to the badge number.
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Void ]
*/
exports.decrease = function (count, callback, scope) {
this.get(function (badge) {
this.set(Math.max(0, badge - (count || 1)), callback, scope);
}, this);
};
/**
* Check support to show badges.
*
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Void ]
*/
exports.isSupported = function (callback, scope) {
if (isAndroid) {
this.exec('check', null, callback, scope);
} else {
this.createCallbackFn(callback, scope)(true);
}
};
/**
* Check permission to show badges.
*
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Void ]
*/
exports.hasPermission = function (callback, scope) {
if (isIOS) {
this.exec('check', null, callback, scope);
} else {
this.createCallbackFn(callback, scope)(true);
}
};
/**
* Request permission to show badges.
*
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Void ]
*/
exports.requestPermission = function (callback, scope) {
if (isIOS) {
this.exec('request', null, callback, scope);
} else {
this.createCallbackFn(callback, scope)(true);
}
};
/**
* Configures the plugin's platform options.
*
* @param [ Hash ] object Optional config settings.
*
* @return [ Hash ] The merged config settings.
*/
exports.configure = function (config) {
this.mergeConfig(config);
this.exec('save', this._config);
return this._config;
};
/**
* Merge the config values with the current ones.
*
* @param [ Hash ] object Optional config settings.
*
* @return [ Hash ] The merged config settings.
*/
exports.mergeConfig = function (config) {
return Object.assign(this._config, config);
};
/**
* Create callback, which will be executed within a specific scope.
*
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Function ] The new callback function
*/
exports.createCallbackFn = function (callbackFn, scope) {
if (typeof callbackFn != 'function')
return;
return function () {
callbackFn.apply(scope || this, arguments);
};
};
/**
* Clear the badge if autoClear is on and the indicator type is badge.
*
* @return [ Void ]
*/
exports.clearIf = function () {
if (this._config.autoClear && this._config.indicator == 'badge') {
this.clear();
}
};
/**
* Execute the native counterpart.
*
* @param [ String ] action The name of the action to execute.
* @param [ Array ] args Array of arguments to pass with.
* @param [ Function ] callback The callback function to be execute later.
* @param [ Function ] scope Optional scope for the callback function.
*
* @return [ Void ]
*/
exports.exec = function (action, args, callback, scope) {
var fn = this.createCallbackFn(callback, scope),
params = [];
if (Array.isArray(args)) {
params = args;
} else if (args) {
params.push(args);
}
exec(fn, null, 'Badge', action, params);
};
// Clear badge on app start if autoClear is set to true
channel.onCordovaReady.subscribe(function () {
exports.exec('load', null, function (config) {
this.mergeConfig(config);
this.clearIf();
}, exports);
});
// Clear badge on app resume if autoClear is set to true
channel.onResume.subscribe(function () {
exports.clearIf();
});
// Clear badge on app resume if autoClear is set to true
channel.onActivated.subscribe(function () {
exports.clearIf();
});
if (isDesktop) {
// Clear badge on app resume if autoClear is set to true
document.addEventListener('visibilitychange', function () {
if (!document.hidden) { exports.clearIf(); }
}, false);
// Clear badge on app resume if autoClear is set to true
window.addEventListener('focus', function () {
exports.clearIf();
}, false);
}
// Polyfill for Object.assign
if (typeof Object.assign != 'function') {
Object.assign = function(target) {
'use strict';
if (target == null) {
throw new TypeError('Cannot convert undefined or null to object');
}
target = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source != null) {
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
}
return target;
};
}
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
### Expected Behaviour
### Actual Behaviour
### Reproduce Scenario (including but not limited to)
#### Steps to Reproduce
#### Platform and Version (eg. Android 5.0 or iOS 9.2.1)
#### (Android) What device vendor (e.g. Samsung, HTC, Sony...)
#### Cordova CLI info
cordova info
Here is the output:
#### Plugin version
cordova plugin version | grep cordova-plugin-file-opener2
Here is the output:
#### Sample Code that illustrates the problem
#### Logs taken while reproducing problem
The MIT License (MIT)
Copyright (c) 2013 pwlin - pwlin05@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# A File Opener Plugin for Cordova (The Original Version)
[![Latest Stable Version](https://img.shields.io/npm/v/cordova-plugin-file-opener2.svg)](https://www.npmjs.com/package/cordova-plugin-file-opener2) [![Total Downloads](https://img.shields.io/npm/dt/cordova-plugin-file-opener2.svg)](https://npm-stat.com/charts.html?package=cordova-plugin-file-opener2) [![Build Status](https://travis-ci.org/apache/cordova-plugin-file-opener2.svg?branch=master)](https://travis-ci.org/apache/cordova-plugin-file-opener2)
This plugin will open a file on your device file system with its default application.
```js
cordova.plugins.fileOpener2.open(
filePath,
fileMIMEType,
{
error : function(){ },
success : function(){ }
}
);
```
## Installation
```shell
$ cordova plugin add cordova-plugin-file-opener2
```
From release `2.1.0` you can also set the android support version
```shell
$ cordova plugin add cordova-plugin-file-opener2 --variable ANDROID_SUPPORT_V4_VERSION={required version}
```
## Requirements
The following platforms and versions are supported by the latest release:
- Android 4.4+ / iOS 9+ / WP8 / Windows
- Cordova CLI 7.0 or higher
Cordova CLI 6.0 is supported by 2.0.19, but there are a number of issues, particularly with Android builds (see [232](https://github.com/pwlin/cordova-plugin-file-opener2/issues/232) [203](https://github.com/pwlin/cordova-plugin-file-opener2/issues/203) [207](https://github.com/pwlin/cordova-plugin-file-opener2/issues/207)). Using the [cordova-android-support-gradle-release](https://github.com/dpa99c/cordova-android-support-gradle-release) plugin may help.
## fileOpener2.open(filePath, mimeType, options)
Opens a file
### Supported Platforms
- Android 4.4+
- iOS 9+
- Windows
- WP8
### Quick Examples
Open an APK install dialog:
```javascript
cordova.plugins.fileOpener2.open(
'/Downloads/gmail.apk',
'application/vnd.android.package-archive'
);
```
Open a PDF document with the default PDF reader and optional callback object:
```js
cordova.plugins.fileOpener2.open(
'/Download/starwars.pdf', // You can also use a Cordova-style file uri: cdvfile://localhost/persistent/Downloads/starwars.pdf
'application/pdf',
{
error : function(e) {
console.log('Error status: ' + e.status + ' - Error message: ' + e.message);
},
success : function () {
console.log('file opened successfully');
}
}
);
```
### Market place installation
Install From Market: to install an APK from a market place, such as Google Play or the App Store, you can use an `<a>` tag in combination with the `market://` protocol:
```html
<a href="market://details?id=xxxx" target="_system">Install from Google Play</a>
<a href="itms-apps://itunes.apple.com/app/my-app/idxxxxxxxx?mt=8" target="_system">Install from App Store</a>
```
or in code:
```js
window.open("[market:// or itms-apps:// link]","_system");
```
## fileOpener2.showOpenWithDialog(filePath, mimeType, options)
Opens with system modal to open file with an already installed app.
### Supported Platforms
- Android 4.4+
- iOS 9+
### Quick Example
```js
cordova.plugins.fileOpener2.showOpenWithDialog(
'/Downloads/starwars.pdf', // You can also use a Cordova-style file uri: cdvfile://localhost/persistent/Downloads/starwars.pdf
'application/pdf',
{
error : function(e) {
console.log('Error status: ' + e.status + ' - Error message: ' + e.message);
},
success : function () {
console.log('file opened successfully');
}
}
);
```
## fileOpener2.uninstall(packageId, callbackContext)
Uninstall a package with its ID
### Supported Platforms
- Android 4.4+
### Quick Example
```js
cordova.plugins.fileOpener2.uninstall('com.zynga.FarmVille2CountryEscape', {
error : function(e) {
console.log('Error status: ' + e.status + ' - Error message: ' + e.message);
},
success : function() {
console.log('Uninstall intent activity started.');
}
});
```
## fileOpener2.appIsInstalled(packageId, callbackContext)
Check if an app is already installed.
### Supported Platforms
- Android 4.4+
### Quick Example
```javascript
cordova.plugins.fileOpener2.appIsInstalled('com.adobe.reader', {
success : function(res) {
if (res.status === 0) {
console.log('Adobe Reader is not installed.');
} else {
console.log('Adobe Reader is installed.')
}
}
});
```
---
## Android APK installation limitation
The following limitations apply when opening an APK file for installation:
- On Android 8+, your application must have the `ACTION_INSTALL_PACKAGE` permission. You can add it by adding this to your app's `config.xml` file:
```xml
<platform name="android">
<config-file parent="/manifest" target="AndroidManifest.xml" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
</config-file>
</platform>
```
- Before Android 7, you can only install APKs from the "external" partition. For example, you can install from `cordova.file.externalDataDirectory`, but **not** from `cordova.file.dataDirectory`. Android 7+ does not have this limitation.
---
## SD card limitation on Android
It is not always possible to open a file from the SD Card using this plugin on Android. This is because the underlying Android library used [does not support serving files from secondary external storage devices](https://stackoverflow.com/questions/40318116/fileprovider-and-secondary-external-storage). Whether or not your the SD card is treated as a secondary external device depends on your particular phone's set up.
---
## Notes
- For properly opening _any_ file, you must already have a suitable reader for that particular file type installed on your device. Otherwise this will not work.
- [It is reported](https://github.com/pwlin/cordova-plugin-file-opener2/issues/2#issuecomment-41295793) that in iOS, you might need to remove `<preference name="iosPersistentFileLocation" value="Library" />` from your `config.xml`
- If you are wondering what MIME-type should you pass as the second argument to `open` function, [here is a list of all known MIME-types](http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=co)
---
{
"_from": "cordova-plugin-file-opener2",
"_id": "cordova-plugin-file-opener2@2.2.0",
"_inBundle": false,
"_integrity": "sha1-9WLxsCoqZsbE2/2eO12GG9me/kE=",
"_location": "/cordova-plugin-file-opener2",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "cordova-plugin-file-opener2",
"name": "cordova-plugin-file-opener2",
"escapedName": "cordova-plugin-file-opener2",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "http://r.cnpmjs.org/cordova-plugin-file-opener2/download/cordova-plugin-file-opener2-2.2.0.tgz",
"_shasum": "f562f1b02a2a66c6c4dbfd9e3b5d861bd99efe41",
"_spec": "cordova-plugin-file-opener2",
"_where": "/Users/ben/gitLab-project/party-build-cloud",
"author": {
"name": "pwlin05@gmail.com"
},
"bugs": {
"url": "https://github.com/pwlin/cordova-plugin-file-opener2/issues"
},
"bundleDependencies": false,
"cordova": {
"id": "cordova-plugin-file-opener2",
"platforms": [
"android",
"ios",
"wp8",
"windows"
]
},
"deprecated": false,
"description": "A File Opener Plugin for Cordova. (The Original Version)",
"engines": {
"cordova": ">=6.0.0"
},
"homepage": "https://github.com/pwlin/cordova-plugin-file-opener2#readme",
"keywords": [
"ecosystem:cordova",
"cordova-android",
"cordova-ios",
"cordova-wp8",
"cordova-windows"
],
"license": "MIT",
"name": "cordova-plugin-file-opener2",
"repository": {
"type": "git",
"url": "git+https://github.com/pwlin/cordova-plugin-file-opener2.git"
},
"version": "2.2.0"
}
<?xml version="1.0" encoding="UTF-8" ?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="cordova-plugin-file-opener2" version="2.2.0">
<name>File Opener2</name>
<description>A File Opener Plugin for Cordova. (The Original Version)</description>
<license>MIT</license>
<engines>
<engine name="cordova" version=">=3.0.0" />
</engines>
<js-module src="www/plugins.FileOpener2.js" name="FileOpener2">
<clobbers target="cordova.plugins.fileOpener2" />
</js-module>
<!-- Android -->
<platform name="android">
<source-file src="src/android/io/github/pwlin/cordova/plugins/fileopener2/FileOpener2.java" target-dir="src/io/github/pwlin/cordova/plugins/fileopener2" />
<source-file src="src/android/io/github/pwlin/cordova/plugins/fileopener2/FileProvider.java" target-dir="src/io/github/pwlin/cordova/plugins/fileopener2" />
<config-file target="res/xml/config.xml" parent="/*">
<feature name="FileOpener2">
<param name="android-package" value="io.github.pwlin.cordova.plugins.fileopener2.FileOpener2" />
</feature>
</config-file>
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<provider android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider" android:authorities="${applicationId}.opener.provider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/opener_paths" />
</provider>
</config-file>
<source-file src="src/android/res/xml/opener_paths.xml" target-dir="res/xml" />
<preference name="ANDROID_SUPPORT_V4_VERSION" default="27.+"/>
<framework src="com.android.support:support-v4:$ANDROID_SUPPORT_V4_VERSION"/>
</platform>
<!-- iOS -->
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="FileOpener2">
<param name="ios-package" value="FileOpener2" />
</feature>
</config-file>
<source-file src="src/ios/FileOpener2.m" />
<header-file src="src/ios/FileOpener2.h" />
</platform>
<!-- WP8 -->
<platform name="wp8">
<config-file target="config.xml" parent="/*">
<feature name="FileOpener2">
<param name="wp-package" value="FileOpener2" />
</feature>
</config-file>
<source-file src="src/wp8/FileOpener2.cs" />
</platform>
<!-- windows -->
<platform name="windows">
<js-module src="src/windows/fileOpener2Proxy.js" name="fileOpener2Proxy">
<merges target="" />
</js-module>
</platform>
</plugin>
/*
The MIT License (MIT)
Copyright (c) 2013 pwlin - pwlin05@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.pwlin.cordova.plugins.fileopener2;
import java.io.File;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import io.github.pwlin.cordova.plugins.fileopener2.FileProvider;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.apache.cordova.CordovaResourceApi;
public class FileOpener2 extends CordovaPlugin {
/**
* Executes the request and returns a boolean.
*
* @param action
* The action to execute.
* @param args
* JSONArry of arguments for the plugin.
* @param callbackContext
* The callback context used when calling back into JavaScript.
* @return boolean.
*/
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("open")) {
String fileUrl = args.getString(0);
String contentType = args.getString(1);
Boolean openWithDefault = true;
if(args.length() > 2){
openWithDefault = args.getBoolean(2);
}
this._open(fileUrl, contentType, openWithDefault, callbackContext);
}
else if (action.equals("uninstall")) {
this._uninstall(args.getString(0), callbackContext);
}
else if (action.equals("appIsInstalled")) {
JSONObject successObj = new JSONObject();
if (this._appIsInstalled(args.getString(0))) {
successObj.put("status", PluginResult.Status.OK.ordinal());
successObj.put("message", "Installed");
}
else {
successObj.put("status", PluginResult.Status.NO_RESULT.ordinal());
successObj.put("message", "Not installed");
}
callbackContext.success(successObj);
}
else {
JSONObject errorObj = new JSONObject();
errorObj.put("status", PluginResult.Status.INVALID_ACTION.ordinal());
errorObj.put("message", "Invalid action");
callbackContext.error(errorObj);
}
return true;
}
private void _open(String fileArg, String contentType, Boolean openWithDefault, CallbackContext callbackContext) throws JSONException {
String fileName = "";
try {
CordovaResourceApi resourceApi = webView.getResourceApi();
Uri fileUri = resourceApi.remapUri(Uri.parse(fileArg));
fileName = fileUri.getPath();
} catch (Exception e) {
fileName = fileArg;
}
File file = new File(fileName);
if (file.exists()) {
try {
Intent intent;
if (contentType.equals("application/vnd.android.package-archive")) {
// https://stackoverflow.com/questions/9637629/can-we-install-an-apk-from-a-contentprovider/9672282#9672282
intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
Uri path;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
path = Uri.fromFile(file);
} else {
Context context = cordova.getActivity().getApplicationContext();
path = FileProvider.getUriForFile(context, cordova.getActivity().getPackageName() + ".opener.provider", file);
}
intent.setDataAndType(path, contentType);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
intent = new Intent(Intent.ACTION_VIEW);
Context context = cordova.getActivity().getApplicationContext();
Uri path = FileProvider.getUriForFile(context, cordova.getActivity().getPackageName() + ".opener.provider", file);
intent.setDataAndType(path, contentType);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NO_HISTORY);
}
/*
* @see
* http://stackoverflow.com/questions/14321376/open-an-activity-from-a-cordovaplugin
*/
if(openWithDefault){
cordova.getActivity().startActivity(intent);
}
else{
cordova.getActivity().startActivity(Intent.createChooser(intent, "Open File in..."));
}
callbackContext.success();
} catch (android.content.ActivityNotFoundException e) {
JSONObject errorObj = new JSONObject();
errorObj.put("status", PluginResult.Status.ERROR.ordinal());
errorObj.put("message", "Activity not found: " + e.getMessage());
callbackContext.error(errorObj);
}
} else {
JSONObject errorObj = new JSONObject();
errorObj.put("status", PluginResult.Status.ERROR.ordinal());
errorObj.put("message", "File not found");
callbackContext.error(errorObj);
}
}
private void _uninstall(String packageId, CallbackContext callbackContext) throws JSONException {
if (this._appIsInstalled(packageId)) {
Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
intent.setData(Uri.parse("package:" + packageId));
cordova.getActivity().startActivity(intent);
callbackContext.success();
}
else {
JSONObject errorObj = new JSONObject();
errorObj.put("status", PluginResult.Status.ERROR.ordinal());
errorObj.put("message", "This package is not installed");
callbackContext.error(errorObj);
}
}
private boolean _appIsInstalled(String packageId) {
PackageManager pm = cordova.getActivity().getPackageManager();
boolean appInstalled = false;
try {
pm.getPackageInfo(packageId, PackageManager.GET_ACTIVITIES);
appInstalled = true;
} catch (PackageManager.NameNotFoundException e) {
appInstalled = false;
}
return appInstalled;
}
}
/*
The MIT License (MIT)
Copyright (c) 2013 pwlin - pwlin05@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package io.github.pwlin.cordova.plugins.fileopener2;
/*
* http://stackoverflow.com/questions/40746144/error-with-duplicated-fileprovider-in-manifest-xml-with-cordova/41550634#41550634
*/
public class FileProvider extends android.support.v4.content.FileProvider {
}
<?xml version="1.0" encoding="utf-8"?>
<!-- https://developer.android.com/reference/android/support/v4/content/FileProvider.html#SpecifyFiles -->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- cordova.file.dataDirectory -->
<files-path name="files" path="." />
<!-- cordova.file.cacheDirectory -->
<cache-path name="cache" path="." />
<!-- cordova.file.externalDataDirectory -->
<external-files-path name="external-files" path="." />
<!-- cordova.file.externalCacheDirectory -->
<external-cache-path name="external-cache" path="." />
<!-- cordova.file.externalRootDirectory -->
<external-path name="external" path="." />
</paths>
/*
The MIT License (MIT)
Copyright (c) 2013 pwlin - pwlin05@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Cordova/CDV.h>
@interface FileOpener2 : CDVPlugin <UIDocumentInteractionControllerDelegate> {
NSString *localFile;
}
@property(nonatomic, strong) UIDocumentInteractionController *controller;
@property(nonatomic, strong) CDVViewController *cdvViewController;
- (void) open: (CDVInvokedUrlCommand*)command;
@end
\ No newline at end of file
/*
The MIT License (MIT)
Copyright (c) 2013 pwlin - pwlin05@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import "FileOpener2.h"
#import <Cordova/CDV.h>
#import <QuartzCore/QuartzCore.h>
#import <MobileCoreServices/MobileCoreServices.h>
@implementation FileOpener2
@synthesize controller = docController;
- (void) open: (CDVInvokedUrlCommand*)command {
NSString *path = [[command.arguments objectAtIndex:0] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];
NSString *contentType = [command.arguments objectAtIndex:1];
BOOL showPreview = YES;
if ([command.arguments count] >= 3) {
showPreview = [[command.arguments objectAtIndex:2] boolValue];
}
CDVViewController* cont = (CDVViewController*)[super viewController];
self.cdvViewController = cont;
NSString *uti = nil;
if([contentType length] == 0){
NSArray *dotParts = [path componentsSeparatedByString:@"."];
NSString *fileExt = [dotParts lastObject];
uti = (__bridge NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExt, NULL);
} else {
uti = (__bridge NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)contentType, NULL);
}
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *fileURL = [NSURL URLWithString:[path stringByRemovingPercentEncoding]];
localFile = fileURL.path;
NSLog(@"looking for file at %@", fileURL);
NSFileManager *fm = [NSFileManager defaultManager];
if(![fm fileExistsAtPath:localFile]) {
NSDictionary *jsonObj = @{@"status" : @"9",
@"message" : @"File does not exist"};
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:jsonObj];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
return;
}
docController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
docController.delegate = self;
docController.UTI = uti;
CDVPluginResult* pluginResult = nil;
//Opens the file preview
BOOL wasOpened = NO;
if (showPreview) {
wasOpened = [docController presentPreviewAnimated: NO];
} else {
CDVViewController* cont = self.cdvViewController;
CGRect rect = CGRectMake(0, 0, cont.view.bounds.size.width, cont.view.bounds.size.height);
wasOpened = [docController presentOpenInMenuFromRect:rect inView:cont.view animated:YES];
}
if(wasOpened) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: @""];
//NSLog(@"Success");
} else {
NSDictionary *jsonObj = [ [NSDictionary alloc]
initWithObjectsAndKeys :
@"9", @"status",
@"Could not handle UTI", @"message",
nil
];
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:jsonObj];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
});
}
@end
@implementation FileOpener2 (UIDocumentInteractionControllerDelegate)
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller {
UIViewController *presentingViewController = self.viewController;
if (presentingViewController.view.window != [UIApplication sharedApplication].keyWindow){
presentingViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
}
while (presentingViewController.presentedViewController != nil && ![presentingViewController.presentedViewController isBeingDismissed]){
presentingViewController = presentingViewController.presentedViewController;
}
return presentingViewController;
}
@end
var cordova = require('cordova'),
fileOpener2 = require('./FileOpener2');
var schemes = [
{ protocol: 'ms-app', getFile: getFileFromApplicationUri },
{ protocol: 'cdvfile', getFile: getFileFromFileUri } //protocol cdvfile
]
function nthIndex(str, pat, n) {
var L = str.length, i = -1;
while (n-- && i++ < L) {
i = str.indexOf(pat, i);
if (i < 0) break;
}
return i;
}
function getFileFromApplicationUri(uri) {
/* bad path from a file entry due to the last '//'
example: ms-appdata:///local//path/to/file
*/
var index = nthIndex(uri, "//", 3);
var newUri = uri.substr(0, index) + uri.substr(index + 1);
var applicationUri = new Windows.Foundation.Uri(newUri);
return Windows.Storage.StorageFile.getFileFromApplicationUriAsync(applicationUri);
}
function getFileFromFileUri(uri) {
/* uri example:
cdvfile://localhost/persistent|temporary|another-fs-root/path/to/file
*/
var indexFrom = nthIndex(uri, "/", 3) + 1;
var indexTo = nthIndex(uri, "/", 4);
var whichFolder = uri.substring(indexFrom, indexTo);
var filePath = uri.substr(indexTo + 1);
var path = "\\" + filePath;
if (whichFolder == "persistent") {
path = Windows.Storage.ApplicationData.current.localFolder.path + path;
}
else { //temporary, note: no roaming management
path = Windows.Storage.ApplicationData.current.temporaryFolder.path + path;
}
return getFileFromNativePath(path);
}
function getFileFromNativePath(path) {
var nativePath = path.split("/").join("\\");
return Windows.Storage.StorageFile.getFileFromPathAsync(nativePath);
}
function getFileLoaderForScheme(path) {
var fileLoader = getFileFromNativePath;
schemes.some(function (scheme) {
return path.indexOf(scheme.protocol) === 0 ? ((fileLoader = scheme.getFile), true) : false;
});
return fileLoader;
}
module.exports = {
open: function (successCallback, errorCallback, args) {
var path = args[0];
var getFile = getFileLoaderForScheme(path);
getFile(path).then(function (file) {
var options = new Windows.System.LauncherOptions();
try{
Windows.System.Launcher.launchFileAsync(file, options).then(function (success) {
successCallback();
}, function (error) {
errorCallback(error);
});
}catch(error){
errorCallback(error);
}
}, function (error) {
console.log("Error while opening the file: "+error);
errorCallback(error);
});
}
};
require("cordova/exec/proxy").add("FileOpener2", module.exports);
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using Windows.Storage;
using System.Diagnostics;
using System.IO;
namespace WPCordovaClassLib.Cordova.Commands
{
public class FileOpener2 : BaseCommand
{
public async void open(string options)
{
string[] args = JSON.JsonHelper.Deserialize<string[]>(options);
string aliasCurrentCommandCallbackId = args[2];
try
{
// Get the file.
StorageFile file = await Windows.Storage.StorageFile.GetFileFromPathAsync(args[0]);
// Launch the bug query file.
await Windows.System.Launcher.LaunchFileAsync(file);
DispatchCommandResult(new PluginResult(PluginResult.Status.OK), aliasCurrentCommandCallbackId);
}
catch (FileNotFoundException)
{
DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION), aliasCurrentCommandCallbackId);
}
catch (Exception)
{
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR), aliasCurrentCommandCallbackId);
}
}
}
}
\ No newline at end of file
/*jslint browser: true, devel: true, node: true, sloppy: true, plusplus: true*/
/*global require, cordova */
/*
The MIT License (MIT)
Copyright (c) 2013 pwlin - pwlin05@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var exec = require('cordova/exec');
function FileOpener2() {}
FileOpener2.prototype.open = function (fileName, contentType, callbackContext) {
contentType = contentType || '';
callbackContext = callbackContext || {};
exec(callbackContext.success || null, callbackContext.error || null, 'FileOpener2', 'open', [fileName, contentType]);
};
FileOpener2.prototype.showOpenWithDialog = function (fileName, contentType, callbackContext) {
contentType = contentType || '';
callbackContext = callbackContext || {};
exec(callbackContext.success || null, callbackContext.error || null, 'FileOpener2', 'open', [fileName, contentType, false]);
};
FileOpener2.prototype.uninstall = function (packageId, callbackContext) {
callbackContext = callbackContext || {};
exec(callbackContext.success || null, callbackContext.error || null, 'FileOpener2', 'uninstall', [packageId]);
};
FileOpener2.prototype.appIsInstalled = function (packageId, callbackContext) {
callbackContext = callbackContext || {};
exec(callbackContext.success || null, callbackContext.error || null, 'FileOpener2', 'appIsInstalled', [packageId]);
};
module.exports = new FileOpener2();
# appveyor file
# http://www.appveyor.com/docs/appveyor-yml
max_jobs: 1
shallow_clone: true
init:
- git config --global core.autocrlf true
image:
- Visual Studio 2017
environment:
nodejs_version: "4"
matrix:
- PLATFORM: windows-10-store
install:
- npm cache clean -f
- node --version
- npm install -g cordova-paramedic@https://github.com/apache/cordova-paramedic.git
- npm install -g cordova
build: off
test_script:
- cordova-paramedic --config pr\%PLATFORM% --plugin . --justBuild
root: true
extends: semistandard
rules:
indent:
- error
- 4
camelcase: off
padded-blocks: off
operator-linebreak: off
no-throw-literal: off
\ No newline at end of file
<!--
Please make sure the checklist boxes are all checked before submitting the PR. The checklist
is intended as a quick reference, for complete details please see our Contributor Guidelines:
http://cordova.apache.org/contribute/contribute_guidelines.html
Thanks!
-->
### Platforms affected
### What does this PR do?
### What testing has been done on this change?
### Checklist
- [ ] [Reported an issue](http://cordova.apache.org/contribute/issues.html) in the JIRA database
- [ ] Commit message follows the format: "CB-3232: (android) Fix bug with resolving file paths", where CB-xxxx is the JIRA ID & "android" is the platform affected.
- [ ] Added automated test coverage as appropriate for this change.
{
"browser": true
, "devel": true
, "bitwise": true
, "undef": true
, "trailing": true
, "quotmark": false
, "indent": 4
, "unused": "vars"
, "latedef": "nofunc"
, "globals": {
"module": false,
"exports": false,
"require": false,
"cordova": false,
"File": true,
"FileSystem": true,
"FileReader": true,
"FileWriter": true,
"FileError": true,
"LocalFileSystem": true,
"Metadata": true,
"Flags": true,
"DirectoryEntry": true,
"resolveLocalFileSystemURL": false,
"requestFileSystem": true,
"FILESYSTEM_PREFIX": true,
"FILESYSTEM_PROTOCOL": true
}
}
#If ignorance is bliss, then somebody knock the smile off my face
*.csproj.user
*.suo
*.cache
Thumbs.db
*.DS_Store
*.bak
*.cache
*.log
*.swp
*.user
/.project
node_modules
sudo: false
addons:
jwt:
secure: JYUSu0UCRC8cpcuh39sn9RqkGBFbG7Hcil3NTpTWbnDRbNrlZeCzDDSirSRD9rPC+M3AEmTo3zKHuWusjUSV4NWLoad/Yd0JXgSNKmxxdESlN6stxCn7oK1I7DwcSlW7capx/44fEjOZ5hajO4mjM/QYuu7+QOuaKvhP5jQjong=
env:
global:
- SAUCE_USERNAME=snay
- TRAVIS_NODE_VERSION="4.2"
matrix:
include:
- env: PLATFORM=browser-firefox
os: linux
language: node_js
node_js: '4.2'
- env: PLATFORM=browser-safari
os: linux
language: node_js
node_js: '4.2'
- env: PLATFORM=browser-edge
os: linux
language: node_js
node_js: '4.2'
- env: PLATFORM=ios-9.3
os: osx
osx_image: xcode7.3
language: node_js
node_js: '4.2'
- env: PLATFORM=ios-10.0
os: osx
osx_image: xcode7.3
language: node_js
node_js: '4.2'
- env: PLATFORM=android-4.4
os: linux
language: android
jdk: oraclejdk8
android:
components:
- tools
- env: PLATFORM=android-5.1
os: linux
language: android
jdk: oraclejdk8
android:
components:
- tools
- env: PLATFORM=android-6.0
os: linux
language: android
jdk: oraclejdk8
android:
components:
- tools
- env: PLATFORM=android-7.0
os: linux
language: android
jdk: oraclejdk8
android:
components:
- tools
before_install:
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm
&& git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm
install $TRAVIS_NODE_VERSION
- node --version
- if [[ "$PLATFORM" =~ android ]]; then gradle --version; fi
- if [[ "$PLATFORM" =~ ios ]]; then npm install -g ios-deploy; fi
- if [[ "$PLATFORM" =~ android ]]; then echo y | android update sdk -u --filter android-22,android-23,android-24,android-25,android-26;
fi
- git clone https://github.com/apache/cordova-paramedic /tmp/paramedic && pushd /tmp/paramedic
&& npm install && popd
- npm install -g cordova
install:
- npm install
script:
- npm test
- node /tmp/paramedic/main.js --config pr/$PLATFORM --plugin $(pwd) --shouldUseSauce
--buildName travis-plugin-file-$TRAVIS_JOB_NUMBER
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
-->
# Contributing to Apache Cordova
Anyone can contribute to Cordova. And we need your contributions.
There are multiple ways to contribute: report bugs, improve the docs, and
contribute code.
For instructions on this, start with the
[contribution overview](http://cordova.apache.org/contribute/).
The details are explained there, but the important items are:
- Sign and submit an Apache ICLA (Contributor License Agreement).
- Have a Jira issue open that corresponds to your contribution.
- Run the tests so your patch doesn't break existing functionality.
We look forward to your contributions!
This diff is collapsed.
Apache Cordova
Copyright 2012 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
This diff is collapsed.
### 6.0.1 (Dec 27, 2017)
* [CB-13704](https://issues.apache.org/jira/browse/CB-13704) Fix to allow 6.0.0 version install
This diff is collapsed.
This diff is collapsed.
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Hinweise für Plugin-Entwickler
Diese Notizen sind hauptsächlich für Android und iOS-Entwickler, die Plugins welche Schnittstelle mit dem Dateisystem, mit dem Plugin Datei schreiben möchten.
## Arbeiten mit Cordova-Datei-System-URLs
Seit der Version 1.0.0, wurde dieses Plugin verwendet URLs mit einer `cdvfile` Regelung für die gesamte Kommunikation über die Brücke, sondern als raw-Device Dateisystempfade zu JavaScript auszusetzen.
Auf der Seite JavaScript bedeutet dies, dass FileEntries und DirectoryEntry-Objekt ein FullPath-Attribut haben, die relativ zum Stammverzeichnis des Dateisystems HTML ist. Wenn Ihr Plugins-JavaScript-API ein FileEntries oder DirectoryEntry-Objekt akzeptiert, rufen Sie `.toURL()` auf das Objekt vor der Übergabe an systemeigenen Code über die Brücke.
### Konvertieren von Cdvfile: / / URLs auf Fileystem Pfade
Plugins, die auf das Dateisystem schreiben müssen, sollten eine empfangene Datei-System-URL auf eine tatsächliche Stelle des Dateisystems zu konvertieren. Es gibt mehrere Wege, dies zu tun, je nach einheitlichen Plattform.
Es ist wichtig, daran erinnern, dass nicht alle `cdvfile://` URLs sind zuweisbaren real Dateien auf das Gerät. Einige URLs verweisen auf Vermögenswerte auf Gerät nicht durch Dateien dargestellt werden, oder sogar auf Remoteressourcen verweisen können. Aufgrund dieser Möglichkeiten sollten Plugins immer testen, ob sie ein sinnvolles Ergebnis zu erhalten, wieder bei dem Versuch, die URLs in Pfade umwandeln.
#### Android
Auf Android, konvertiert die einfachste Methode eine `cdvfile://` URL zu einem Dateisystempfad zu verwenden ist `org.apache.cordova.CordovaResourceApi` . `CordovaResourceApi`verfügt über mehrere Methoden der verarbeiten kann `cdvfile://` URLs:
WebView ist Mitglied der Plugin-Klasse CordovaResourceApi ResourceApi = webView.getResourceApi();
Erhalten eine file:/// URL, diese Datei auf dem Gerät / / oder die gleiche URL unverändert, wenn es eine Datei-Uri FileURL zugeordnet werden kann nicht = resourceApi.remapUri(Uri.parse(cdvfileURL));
Es ist auch möglich, das Plugin Datei direkt zu verwenden:
Import org.apache.cordova.file.FileUtils;
Import org.apache.cordova.file.FileSystem;
Import Java.net.MalformedURLException:;
Erhalten Sie das Datei-Plugin aus dem Plugin-Manager FileUtils FilePlugin = (FileUtils)webView.pluginManager.getPlugin("File");
Angesichts eine URL, einen Pfad zu erhalten, denn es versuchen {String Pfad = filePlugin.filesystemPathForURL(cdvfileURL);} catch (MalformedURLException e) {/ / die Dateisystem-Url war nicht erkannt}
Aus einem Pfad zu konvertieren eine `cdvfile://` URL:
Import org.apache.cordova.file.LocalFilesystemURL;
Rufen Sie ein LocalFilesystemURL-Objekt für einen Gerätepfad / / oder null, wenn sie nicht als URL Cdvfile dargestellt wird.
LocalFilesystemURL Url = filePlugin.filesystemURLforLocalPath(path);
Erhalten Sie die Zeichenfolgendarstellung der URL Objekt String CdvfileURL = url.toString();
Wenn Ihr Plugin eine Datei erstellt, und Sie dafür ein FileEntries-Objekt zurückgeben möchten, verwenden Sie das Datei-Plugin:
Zurückgeben eine JSON-Struktur geeignet für die Rückgabe an JavaScript, / / oder null, wenn diese Datei nicht als URL Cdvfile darstellbar ist.
JSONObject Eintrag = filePlugin.getEntryForFile(file);
#### iOS
Cordova auf iOS verwendet nicht das gleiche `CordovaResourceApi` Konzept als Android. Auf iOS sollten Sie das Datei-Plugin verwenden, zum Konvertieren von URLs und Dateisystem-Pfaden.
Rufen Sie ein CDVFilesystem URL-Objekt von einer URL-Zeichenfolge CDVFilesystemURL * Url = [CDVFilesystemURL FileSystemURLWithString:cdvfileURL];
Erhalten Sie einen Pfad für die URL-Objekt oder NULL, wenn es einen Dateipfad NSString * zugeordnet werden kann nicht = [FilePlugin FilesystemPathForURL:url];
Eine CDVFilesystem URL-Objekt für einen Gerätepfad abrufen oder / / gleich NULL, wenn sie nicht als URL Cdvfile dargestellt wird.
CDVFilesystemURL-Url = [FilePlugin FileSystemURLforLocalPath:path];
Erhalten Sie die Zeichenfolgendarstellung der URL Objekt NSString * CdvfileURL = [Url AbsoluteString];
Wenn Ihr Plugin eine Datei erstellt, und Sie dafür ein FileEntries-Objekt zurückgeben möchten, verwenden Sie das Datei-Plugin:
Eine CDVFilesystem URL-Objekt für einen Gerätepfad abrufen oder / / gleich NULL, wenn sie nicht als URL Cdvfile dargestellt wird.
CDVFilesystemURL-Url = [FilePlugin FileSystemURLforLocalPath:path];
Erhalten eine Struktur zurück nach JavaScript NSDictionary * Eintrag = [FilePlugin MakeEntryForLocalURL:url]
#### JavaScript
In JavaScript, bekommen eine `cdvfile://` URL aus einem FileEntries oder DirectoryEntry-Objekt, rufen Sie einfach `.toURL()` drauf:
Var CdvfileURL = entry.toURL();
Im Plugin Antwort Handler zur Konvertierung von einer zurückgegebenen FileEntries-Struktur in einem tatsächlichen Eintrag-Objekt sollte Handlercode importieren die Datei-Erweiterung und ein neues Objekt zu erstellen:
Erstellen Sie entsprechenden Eintrag Objekt Var Eintrag;
Wenn (entryStruct.isDirectory) {Eintrag = neues DirectoryEntry (entryStruct.name, entryStruct.fullPath, neue FileSystem(entryStruct.filesystemName));} sonst {Eintrag = neue FileEntries (entryStruct.name, entryStruct.fullPath, neue FileSystem(entryStruct.filesystemName));}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Notas para los desarrolladores del plugin
Estas notas están pensadas principalmente para desarrolladores de Android y el iOS que quieran escribir plugins que interfaz con el sistema de ficheros usando el plugin del archivo.
## Trabajar con URLs de sistema de archivo de Córdoba
Desde la versión 1.0.0, este plugin ha utilizado las direcciones URL con un `cdvfile` plan para todas las comunicaciones sobre el puente, en lugar de exponer rutas de sistema de archivos de dispositivos raw para JavaScript.
En el lado de JavaScript, esto significa que los objetos FileEntry y DirectoryEntry tienen un atributo fullPath que es relativo a la raíz del sistema de archivos HTML. Si JavaScript API de tu plugin acepta un objeto FileEntry o DirectoryEntry, usted debe llamar a `.toURL()` en ese objeto antes de pasar a través del puente al código nativo.
### Conversión de cdvfile: / / URL al fileystem caminos
Plugins que necesita escribir en el sistema de archivos puede convertir un archivo recibido sistema URL a una ubicación de sistema de archivos real. Hay varias formas de hacerlo, dependiendo de la plataforma nativa.
Es importante recordar que no todos `cdvfile://` las direcciones URL son asignables a reales archivos en el dispositivo. Algunas URLs pueden referirse a activos en dispositivos que no están representadas por archivos, o incluso pueden hacer referencia a recursos remotos. Debido a estas posibilidades, plugins siempre debe comprobar si consiguen un resultado significativo cuando tratando de convertir las URL en trazados.
#### Android
En Android, el método más simple para convertir un `cdvfile://` URL a una ruta de sistema de archivos es utilizar `org.apache.cordova.CordovaResourceApi` . `CordovaResourceApi`tiene varios métodos que pueden manejar `cdvfile://` URL:
webView es un miembro de la clase Plugin CordovaResourceApi resourceApi = webView.getResourceApi();
Obtener una URL file:/// representando este archivo en el dispositivo, / / o el mismo URL sin cambios si no se puede asignar a un archivo Uri fileURL = resourceApi.remapUri(Uri.parse(cdvfileURL));
También es posible utilizar el plugin de archivos directamente:
Import org.apache.cordova.file.FileUtils;
Import org.apache.cordova.file.FileSystem;
Import java.net.MalformedURLException;
Obtener el archivo plugin desde el administrador de plugin FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File");
Dada una URL, haz un camino para tratar de {camino de cadena = filePlugin.filesystemPathForURL(cdvfileURL);} catch (DD e) {/ / el sistema de archivos url no reconocida}
Para convertir de una ruta a un `cdvfile://` URL:
Import org.apache.cordova.file.LocalFilesystemURL;
Obtener un objeto LocalFilesystemURL para una ruta, / / o null si no se puede representar como una dirección URL cdvfile.
LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path);
Obtener la representación string de la URL objeto String cdvfileURL = url.toString();
Si tu plugin crea un archivo y desea devolver un objeto FileEntry para él, usar el plugin de archivos:
Devolver una estructura JSON adecuado para volver a JavaScript, / / o null si este archivo no es representable como una dirección URL cdvfile.
JSONObject entrada = filePlugin.getEntryForFile(file);
#### iOS
Cordova en iOS no utiliza la misma `CordovaResourceApi` concepto como Android. En iOS, debe usar el archivo plugin para convertir las direcciones URL y rutas de sistema de archivos.
Obtener un objeto URL CDVFilesystem de una URL string CDVFilesystemURL * url = [CDVFilesystemURL fileSystemURLWithString:cdvfileURL];
Obtener una ruta de acceso para el objeto URL, o nil si no puede ser asignado a una ruta de archivo NSString * = [filePlugin filesystemPathForURL:url];
Obtener un objeto URL CDVFilesystem para una ruta, o / / nula si no se puede representar como una dirección URL cdvfile.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
Obtener la representación string de la URL objetos NSString * cdvfileURL = [enlace absoluteString];
Si tu plugin crea un archivo y desea devolver un objeto FileEntry para él, usar el plugin de archivos:
Obtener un objeto URL CDVFilesystem para una ruta, o / / nula si no se puede representar como una dirección URL cdvfile.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
Conseguir una estructura para volver a JavaScript NSDictionary * entrada = [filePlugin makeEntryForLocalURL:url]
#### JavaScript
En JavaScript, para obtener un `cdvfile://` dirección URL de un objeto FileEntry o DirectoryEntry, simplemente llame al `.toURL()` en él:
var cdvfileURL = entry.toURL();
En manipuladores de la respuesta del plugin, para convertir de una estructura FileEntry devuelta a un objeto real de la entrada, su código de controlador debe importar el archivo plugin y crear un nuevo objeto:
crear apropiado objeto var ingreso;
Si (entryStruct.isDirectory) {entrada = new DirectoryEntry (entryStruct.name, entryStruct.fullPath, FileSystem(entryStruct.filesystemName)) nuevo;} else {entrada = nuevo FileEntry (entryStruct.name, entryStruct.fullPath, nuevo FileSystem(entryStruct.filesystemName));}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Notes pour les développeurs de plugins
Ces notes sont principalement destinés à des développeurs Android et iOS qui veulent écrire des plugins qui interface avec le système de fichiers en utilisant le fichier plugin.
## Travailler avec Cordova fichier système URL
Depuis la version 1.0.0, ce plugin utilise des URL avec un `cdvfile` guichet pour toutes les communications sur le pont, plutôt que d'exposer des chemins de système de fichiers de périphérique brut à JavaScript.
Du côté du JavaScript, cela signifie que les objets FileEntry et DirectoryEntry ont un attribut fullPath qui est relatif à la racine du système de fichiers HTML. Si votre plugin JavaScript API accepte un objet FileEntry ou DirectoryEntry, vous devez appeler `.toURL()` sur cet objet avant de le passer sur le pont en code natif.
### Conversion de cdvfile: / / URL aux chemins d'accès fileystem
Plugins qui ont besoin d'écrire dans le système de fichiers pouvez convertir un fichier reçu système URL vers un emplacement de système de fichiers réels. Il y a plusieurs façons de le faire, selon la plate-forme native.
Il est important de rappeler que pas tous les `cdvfile://` URL sont cartographiables à des fichiers sur le périphérique. Certaines URL peut faire référence aux actifs sur les périphériques qui ne sont pas représentés par des fichiers, ou peuvent même faire référence aux ressources distantes. En raison de ces possibilités, plugins devraient toujours tester si ils obtiennent un résultat significatif retour lorsque vous essayez de convertir les URL aux chemins d'accès.
#### Androïde
Sur Android, la méthode la plus simple pour convertir un `cdvfile://` URL vers un chemin d'accès de système de fichiers est d'utiliser `org.apache.cordova.CordovaResourceApi` . `CordovaResourceApi`possède plusieurs méthodes qui peuvent gérer `cdvfile://` URL :
webView est membre de la Plugin classe CordovaResourceApi resourceApi = webView.getResourceApi() ;
Obtenir une URL file:/// représentant ce fichier sur le périphérique, / / ou le même URL inchangée si elle ne peut pas être mappée à un fichier Uri fileURL = resourceApi.remapUri(Uri.parse(cdvfileURL)) ;
Il est également possible d'utiliser le fichier plugin directement :
Import org.apache.cordova.file.FileUtils ;
Import org.apache.cordova.file.FileSystem ;
java.net.MalformedURLException d'importation ;
Téléchargez le fichier plugin depuis le gestionnaire de plugin FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File") ;
En donnant une URL, obtenir un chemin d'accès pour essayer {String path = filePlugin.filesystemPathForURL(cdvfileURL);} catch (MalformedURLException e) {/ / l'url du système de fichiers n'a pas été reconnu}
Pour convertir un chemin d'accès à un `cdvfile://` URL :
Import org.apache.cordova.file.LocalFilesystemURL ;
Obtenir un objet LocalFilesystemURL pour un chemin de périphérique, / / ou null si elle ne peut être représentée sous forme d'URL cdvfile.
LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path) ;
Obtenir la chaîne représentant l'URL objet String cdvfileURL = url.toString() ;
Si votre plugin crée un fichier et que vous souhaitez renvoyer un objet FileEntry pour cela, utilisez le fichier plugin :
Retourne une structure JSON approprié pour revenir en JavaScript, / / ou null si ce fichier n'est pas représentable sous forme d'URL cdvfile.
JSONObject entrée = filePlugin.getEntryForFile(file) ;
#### iOS
Cordova sur iOS n'utilise pas le même `CordovaResourceApi` concept d'Android. Sur iOS, vous devez utiliser le fichier plugin pour convertir entre les URL et les chemins d'accès de système de fichiers.
Obtenir un objet URL CDVFilesystem partir d'une chaîne d'URL CDVFilesystemURL * url = [CDVFilesystemURL fileSystemURLWithString:cdvfileURL] ;
Obtenir un chemin d'accès de l'objet URL, ou zéro si elle ne peut pas être mappée à un chemin de fichier NSString * = [filePlugin filesystemPathForURL:url] ;
Obtenir un objet CDVFilesystem URL pour un chemin de périphérique, ou / / zéro si elle ne peut être représentée sous forme d'URL cdvfile.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path] ;
Obtenir la représentation de chaîne de l'objet NSString * cdvfileURL URL = [url absoluteString] ;
Si votre plugin crée un fichier et que vous souhaitez renvoyer un objet FileEntry pour cela, utilisez le fichier plugin :
Obtenir un objet CDVFilesystem URL pour un chemin de périphérique, ou / / zéro si elle ne peut être représentée sous forme d'URL cdvfile.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path] ;
Obtenir une structure pour revenir à JavaScript NSDictionary * entrée = [filePlugin makeEntryForLocalURL:url]
#### JavaScript
En JavaScript, pour obtenir un `cdvfile://` URL d'un objet FileEntry ou DirectoryEntry, il suffit d'appeler `.toURL()` à ce sujet :
var cdvfileURL = entry.toURL() ;
Dans gestionnaires de plugin de réponse, pour convertir une structure FileEntry retournée vers un objet réel de l'entrée, votre code de gestionnaire doit importer le fichier plugin et créer un nouvel objet :
créer l'entrée de var d'objet entrée appropriée ;
Si (entryStruct.isDirectory) {entrée = new DirectoryEntry (entryStruct.name, entryStruct.fullPath, nouveau FileSystem(entryStruct.filesystemName));} else {entrée = nouvelle FileEntry (entryStruct.name, entryStruct.fullPath, nouvelle FileSystem(entryStruct.filesystemName));}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Note per gli sviluppatori di plugin
Queste note sono destinate principalmente per gli sviluppatori di Android e iOS che vogliono scrivere plugin quale interfaccia con il sistema di file utilizzando il File plugin.
## Lavorando con URL di sistema file di Cordova
Dalla versione 1.0.0, questo plugin ha utilizzato gli URL con un `cdvfile` schema per tutte le comunicazioni oltre il ponte, piuttosto che esporre i percorsi del file system di dispositivo raw a JavaScript.
Sul lato JavaScript, questo significa che gli oggetti FileEntry e DirectoryEntry dispongano di un attributo fullPath che è relativo alla directory principale del sistema di file HTML. Se API JavaScript del vostro plugin accetta un oggetto FileEntry o DirectoryEntry, è necessario chiamare `.toURL()` su quell'oggetto prima di passarlo attraverso il ponte in codice nativo.
### Conversione cdvfile: / / URL ai percorsi fileystem
Plugin che hanno bisogno di scrivere il filesystem può essere necessario convertire un URL di sistema del file ricevuto in un percorso effettivo filesystem. Ci sono diversi modi di fare questo, a seconda della piattaforma nativa.
È importante ricordare che non tutti i `cdvfile://` URL sono mappabili ai veri file sul dispositivo. Alcuni URL può riferirsi a beni sul dispositivo che non sono rappresentate da file, o possono anche fare riferimento a risorse remote. A causa di queste possibilità, plugin dovrebbe sempre verificare se ottengono un risultato significativo indietro quando si tenta di convertire gli URL in percorsi.
#### Android
Su Android, il metodo più semplice per convertire un `cdvfile://` URL a un percorso di file System è quello di utilizzare `org.apache.cordova.CordovaResourceApi` . `CordovaResourceApi`dispone di diversi metodi che è possono gestire `cdvfile://` URL:
webView è un membro del Plugin classe CordovaResourceApi resourceApi = webView.getResourceApi();
Ottenere un URL file:/// che rappresenta questo file sul dispositivo, / / o lo stesso URL invariata se non può essere mappato a un file Uri fileURL = resourceApi.remapUri(Uri.parse(cdvfileURL));
È anche possibile utilizzare direttamente il File plugin:
importazione org.apache.cordova.file.FileUtils;
importazione org.apache.cordova.file.FileSystem;
importazione java.net.MalformedURLException;
Ottenere il File plugin dal gestore plugin FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File");
Dato un URL, ottenere un percorso per esso prova {String path = filePlugin.filesystemPathForURL(cdvfileURL);}} catch (MalformedURLException e) {/ / l'url del file System non è stato riconosciuto}
Convertire da un percorso a un `cdvfile://` URL:
importazione org.apache.cordova.file.LocalFilesystemURL;
Ottenere un oggetto LocalFilesystemURL per un percorso di dispositivo, / / oppure null se non può essere rappresentata come un URL di cdvfile.
LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path);
Ottenere la rappresentazione di stringa dell'URL oggetto String cdvfileURL = url.toString();
Se il vostro plugin crea un file e si desidera restituire un oggetto FileEntry per esso, utilizzare il File plugin:
Restituire una struttura JSON appropriato per restituire a JavaScript, / / o null se questo file non è rappresentabile come un URL di cdvfile.
Voce di JSONObject = filePlugin.getEntryForFile(file);
#### iOS
Cordova su iOS non utilizza lo stesso `CordovaResourceApi` concetto come Android. Su iOS, si dovrebbe utilizzare il plugin File per convertire tra URL e percorsi di file System.
Ottenere un oggetto CDVFilesystem URL da una stringa CDVFilesystemURL * url = [CDVFilesystemURL fileSystemURLWithString:cdvfileURL];
Ottenere un percorso per l'oggetto URL, o zero se non può essere mappato a un percorso di file NSString * = [filePlugin filesystemPathForURL:url];
Ottenere un oggetto CDVFilesystem URL per un percorso di dispositivo, o / / nullo se non può essere rappresentata come un URL di cdvfile.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
Ottenere la rappresentazione di stringa dell'URL oggetto NSString * cdvfileURL = [absoluteString url];
Se il vostro plugin crea un file e si desidera restituire un oggetto FileEntry per esso, utilizzare il File plugin:
Ottenere un oggetto CDVFilesystem URL per un percorso di dispositivo, o / / nullo se non può essere rappresentata come un URL di cdvfile.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
Ottenere una struttura per tornare alla voce JavaScript NSDictionary * = [filePlugin makeEntryForLocalURL:url]
#### JavaScript
In JavaScript, per ottenere un `cdvfile://` URL da un oggetto FileEntry o DirectoryEntry, semplicemente chiamare `.toURL()` su di esso:
var cdvfileURL = entry.toURL();
Nei gestori di risposta del plugin, per convertire da una struttura FileEntry restituita in un oggetto reale di voce, il codice del gestore dovrebbe importare il File plugin e creare un nuovo oggetto:
creare la voce appropriata a voce oggetto var;
Se (entryStruct.isDirectory) {voce = new DirectoryEntry (entryStruct.name, entryStruct.fullPath, nuovo FileSystem(entryStruct.filesystemName));} altro {voce = FileEntry nuovo (entryStruct.name, entryStruct.fullPath, nuovo FileSystem(entryStruct.filesystemName));}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# プラグイン開発者のためのメモ
これらのノートは主に Android と iOS 開発者インタ フェース ファイルのプラグインを使用してファイル システムでプラグインを書きたい人向け。
## コルドバのファイル システムの Url での作業
バージョン 1.0.0 では、以来、このプラグインを含む Url を使用する `cdvfile` JavaScript に raw デバイス ファイル システムのパスを公開するのではなく、橋の上のすべての通信方式します。
JavaScript 側では、これはファイルと DirectoryEntry オブジェクトに HTML ファイル システムのルートを基準として、fullPath 属性があることを意味します。 あなたのプラグインの JavaScript API がファイルまたは DirectoryEntry オブジェクトを受け入れる場合を呼び出す必要があります `.toURL()` 橋を渡ってそれをネイティブ コードに渡す前にそのオブジェクトの。
### Cdvfile に変換する://fileystem のパスに Url
ファイルシステムへの書き込みする必要があるプラグインは、実際のファイルシステムの場所に受信したファイル システム URL に変換する必要があります。ネイティブ プラットフォームによって、これを行うための複数の方法があります。
それを覚えていることが重要ですすべて `cdvfile://` の Url がデバイス上の実際のファイルをマッピング可能な。 いくつかの Url は、ファイルでは表されないまたはリモート リソースを参照することができますもデバイス上の資産を参照できます。 これらの可能性のためのプラグインは、戻るときにパスに Url を変換しようとして、彼らは意味のある結果を得るかどうか常にテスト必要があります。
#### アンドロイド
アンドロイド, に変換する最も簡単な方法で、 `cdvfile://` を使用するファイルシステムのパスに URL は `org.apache.cordova.CordovaResourceApi``CordovaResourceApi`扱うことができるいくつかの方法は、 `cdvfile://` の Url:
webView プラグイン クラス CordovaResourceApi resourceApi のメンバーである = webView.getResourceApi()。
デバイスでこのファイルを表す file:///URL を取得//ファイル Uri fileURL にマップできない場合、同じ URL は変更されません = resourceApi.remapUri(Uri.parse(cdvfileURL));
また、ファイルのプラグインを直接使用することが可能です。
インポート org.apache.cordova.file.FileUtils;
インポート org.apache.cordova.file.FileSystem;
インポート java.net.MalformedURLException;
プラグイン マネージャーからファイルのプラグインを入手してコマンド filePlugin = (FileUtils)webView.pluginManager.getPlugin("File");
それを試みるためにパスを取得 URL を指定すると、{文字列パス = filePlugin.filesystemPathForURL(cdvfileURL);} キャッチ (MalformedURLException e) {/ファイルシステムの url が認識されませんでした/}
パスから変換する、 `cdvfile://` URL:
インポート org.apache.cordova.file.LocalFilesystemURL;
デバイス ・ パスの LocalFilesystemURL オブジェクトを取得//cdvfile URL として表現できない場合は null。
LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path);
URL オブジェクトの文字列 cdvfileURL の文字列表現を取得する = url.toString();
あなたのプラグインは、ファイルを作成しをファイル オブジェクトを返す場合、ファイルのプラグインを使用します。
JavaScript を返すときに適した JSON 構造を返す//このファイルは cdvfile URL として表現できない場合は null。
JSONObject エントリ = filePlugin.getEntryForFile(file);
#### iOS
IOS のコルドバは同じを使用しない `CordovaResourceApi` アンドロイドとしての概念。IOS では、Url とファイルシステムのパスの間を変換するファイル プラグインを使用する必要があります。
URL の文字列 CDVFilesystemURL * url から CDVFilesystem URL オブジェクトを取得 [CDVFilesystemURL fileSystemURLWithString:cdvfileURL];
ファイル NSString * パスにマップできない場合は nil または URL オブジェクトのパスを取得 [filePlugin filesystemPathForURL:url];
デバイス ・ パスの CDVFilesystem の URL オブジェクトを取得または//cdvfile URL として表現できない場合は nil です。
CDVFilesystemURL の url = [filePlugin fileSystemURLforLocalPath:path];
URL オブジェクト NSString * cdvfileURL の文字列表現を取得する = [url absoluteString];
あなたのプラグインは、ファイルを作成しをファイル オブジェクトを返す場合、ファイルのプラグインを使用します。
デバイス ・ パスの CDVFilesystem の URL オブジェクトを取得または//cdvfile URL として表現できない場合は nil です。
CDVFilesystemURL の url = [filePlugin fileSystemURLforLocalPath:path];
JavaScript NSDictionary * エントリに戻る構造を得る = [filePlugin makeEntryForLocalURL:url]
#### Java スクリプトの設定
Java スクリプトの設定を取得するに、 `cdvfile://` ファイルまたは DirectoryEntry オブジェクトからの URL を呼び出して、 `.toURL()` それを。
var cdvfileURL = entry.toURL();
プラグイン応答ハンドラーに返された FileEntry 構造体の実際のエントリ オブジェクトを変換する、ハンドラーのコード ファイルのプラグインをインポート、新しいオブジェクトを作成します。
適切なエントリ オブジェクト var エントリを作成します。
場合 (entryStruct.isDirectory) {エントリ = 新しい DirectoryEntry (entryStruct.name、entryStruct.fullPath、新しい FileSystem(entryStruct.filesystemName));} 他 {エントリ = 新しいファイル (entryStruct.name、entryStruct.fullPath、新しい FileSystem(entryStruct.filesystemName));}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# 플러그인 개발자를 위한 노트
이 노트는 주로 파일 플러그인을 사용 하 여 파일 시스템 플러그인 인터페이스를 작성 하 고 싶은 안 드 로이드와 iOS 개발자를 위한 것입니다.
## 코르 도우 바 파일 시스템 Url 사용
버전 1.0.0, 이후이 플러그인과 Url 사용 하고있다는 `cdvfile` 교량, 모든 통신에 대 한 제도 보다는 자바 원시 장치 파일 시스템 경로 노출.
자바 스크립트 측면에서 즉 그 FileEntry 및 DirectoryEntry 개체 fullPath 속성을 HTML 파일 시스템의 루트에 상대적입니다. FileEntry 또는 DirectoryEntry 개체를 수락 하는 플러그인의 자바 API를 호출 해야 `.toURL()` 다리에 걸쳐 네이티브 코드에 전달 하기 전에 해당 개체에.
### Cdvfile 변환: / / fileystem 경로 Url
플러그인 파일 시스템을 작성 하는 실제 파일 시스템 위치에 받은 파일 시스템 URL을 변환 할 수 있습니다. 이렇게, 네이티브 플랫폼에 따라 여러 방법이 있다.
기억 하는 것이 중요 하다 모든 `cdvfile://` Url은 실제 파일 장치에 매핑. 일부 Url 파일에 의해 표현 되지 않는 또는 심지어 원격 리소스를 참조할 수 있는 장치에 자산을 참조할 수 있습니다. 이러한 가능성 때문에 플러그인 경로를 Url을 변환 하려고 할 때 다시 의미 있는 결과 얻을 지 여부를 항상 테스트 해야 합니다.
#### 안 드 로이드
안 드 로이드, 변환 하는 간단한 방법에는 `cdvfile://` URL을 파일 시스템 경로 사용 하는 `org.apache.cordova.CordovaResourceApi` . `CordovaResourceApi`처리할 수 있는 여러 가지 방법에는 `cdvfile://` Url:
webView 플러그인 클래스 CordovaResourceApi resourceApi의 멤버인 = webView.getResourceApi();
장치에이 파일을 나타내는 file:/// URL 얻기 / / 같은 URL 변경 파일 Uri fileURL에 매핑할 수 없는 경우 또는 = resourceApi.remapUri(Uri.parse(cdvfileURL));
그것은 또한 파일 플러그인을 직접 사용할 수 있습니다:
가져오기 org.apache.cordova.file.FileUtils;
가져오기 org.apache.cordova.file.FileSystem;
가져오기 java.net.MalformedURLException;
플러그인 관리자에서 파일 플러그인을 얻을 FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File");
그것 시도 대 한 경로 얻을 URL을 감안할 때, {문자열 경로 = filePlugin.filesystemPathForURL(cdvfileURL);} catch (MalformedURLException e) {/ / 파일 시스템 url 인식 되지 않았습니다}
경로를 변환 하는 `cdvfile://` URL:
가져오기 org.apache.cordova.file.LocalFilesystemURL;
장치 경로 대 한 LocalFilesystemURL 개체를 가져오기 / / cdvfile URL로 나타낼 수 없는 경우 null.
LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path);
URL 개체 문자열 cdvfileURL의 문자열 표현을 = url.toString();
플러그인 파일을 만들고 그것에 대 한 FileEntry 개체를 반환 하려면, 파일 플러그인을 사용.
JSON 구조를 JavaScript에 반환을 위한 적당 한 반환 / /이 파일은 cdvfile URL로 표현 하는 경우 null.
JSONObject 항목 = filePlugin.getEntryForFile(file);
#### iOS
IOS에서 코르도바 같은 사용 하지 않는 `CordovaResourceApi` 안 드 로이드 개념. Ios, Url 및 파일 시스템 경로 사이 변환 파일 플러그인을 사용 해야 합니다.
URL 문자열 CDVFilesystemURL * url에서 CDVFilesystem URL 개체를 가져오기 = [CDVFilesystemURL fileSystemURLWithString:cdvfileURL];
파일 NSString * 경로에 매핑할 수 없는 경우 URL 개체 또는 없음에 대 한 경로 얻을 = [filePlugin filesystemPathForURL:url];
장치 경로 대 한 CDVFilesystem URL 개체를 가져오기 또는 / / 없음 cdvfile URL로 나타낼 수 없는 경우.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
URL 개체 NSString * cdvfileURL의 문자열 표현을 = [url absoluteString];
플러그인 파일을 만들고 그것에 대 한 FileEntry 개체를 반환 하려면, 파일 플러그인을 사용.
장치 경로 대 한 CDVFilesystem URL 개체를 가져오기 또는 / / 없음 cdvfile URL로 나타낼 수 없는 경우.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
자바 스크립트 NSDictionary * 항목으로 돌아가려면 구조를 얻을 = [filePlugin makeEntryForLocalURL:url]
#### 자바 스크립트
자바 스크립트에는 `cdvfile://` FileEntry 또는 DirectoryEntry 개체에서 URL 호출 `.toURL()` 그것에:
var cdvfileURL = entry.toURL();
플러그인 응답 처리기에서 실제 항목 개체로 반환 된 FileEntry 구조에서 변환 처리기 코드 해야 파일 플러그인 가져오고 새 개체를 만들:
적절 한 항목 개체 var 항목;
경우 (entryStruct.isDirectory) {항목 = 새 DirectoryEntry (entryStruct.name, entryStruct.fullPath, 새로운 FileSystem(entryStruct.filesystemName));} 다른 {항목 = 새로운 FileEntry (entryStruct.name, entryStruct.fullPath, 새로운 FileSystem(entryStruct.filesystemName));}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Uwagi dla programistów wtyczki
Te notatki są przeznaczone przede wszystkim dla Androida i iOS deweloperów, którzy chcieli pisac pluginy które interfejs z systemu plików za pomocą wtyczki pliku.
## Praca z Cordova pliku system adresów URL
Od wersji 1.0.0, ten plugin ma używane adresy URL z `cdvfile` system dla wszystkich komunikacji przez most, a nie narażać urządzenia raw ścieżki systemu plików JavaScript.
Na stronie JavaScript oznacza to, że FileEntry i DirectoryEntry obiekty mają fullPath atrybut, który jest głównym systemie plików HTML. Jeśli twój plugin JavaScript API akceptuje obiektu FileEntry lub DirectoryEntry, należy zadzwonić `.toURL()` dla tego obiektu przed przekazaniem Altpradl do kodu macierzystego.
### Konwersja cdvfile: / / URL do ścieżki fileystem
Wtyczek, które trzeba pisać do systemu plików może chcesz przekonwertować odebranych plików systemu adres URL lokalizacji rzeczywistych plików. Istnieje wiele sposobów robi to, w zależności od macierzystego platformy.
Ważne jest, aby pamiętać, że nie wszystkie `cdvfile://` adresy URL są można zmapować na prawdziwe pliki w urządzeniu. Niektóre adresy URL może odnosić się do aktywów na urządzeniu, które nie są reprezentowane przez pliki, lub nawet może odnosić się do zasobów zdalnych. Ze względu na te możliwości wtyczki należy zawsze sprawdzić, czy się znaczącego wyniku powrót podczas próby konwersji adresów URL do ścieżki.
#### Androida
Na Android, najprostsza metoda konwersji `cdvfile://` URL do ścieżki systemu plików jest użycie `org.apache.cordova.CordovaResourceApi` . `CordovaResourceApi`jest kilka metod, które mogą obsługiwać `cdvfile://` adresów URL:
Widok sieci Web jest członkiem Plugin klasy CordovaResourceApi resourceApi = webView.getResourceApi();
Uzyskać URL file:/// reprezentujących ten plik na urządzeniu / / lub ten sam adres URL niezmienione, jeśli nie mogą być mapowane do pliku fileURL Uri = resourceApi.remapUri(Uri.parse(cdvfileURL));
Jest również możliwe, aby korzystać z wtyczki pliku bezpośrednio:
org.apache.cordova.file.FileUtils przywóz;
org.apache.cordova.file.FileSystem przywóz;
java.net.MalformedURLException przywóz;
Uzyskać pliku plugin manager wtyczki FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File");
Biorąc pod uwagę adres URL, uzyskać ścieżkę dla to spróbuj {String ścieżka = filePlugin.filesystemPathForURL(cdvfileURL);} catch (MalformedURLException e) {/ / url plików nie było uznane}
Do przeliczenia ścieżki do `cdvfile://` URL:
org.apache.cordova.file.LocalFilesystemURL przywóz;
Uzyskanie obiektu LocalFilesystemURL na ścieżkę urządzenia / / lub null, jeśli nie może być reprezentowana jako adres URL cdvfile.
LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path);
Dostać reprezentację ciąg adresu URL obiektu String cdvfileURL = url.toString();
Jeśli twój plugin tworzy plik, i chcesz zwraca obiekt FileEntry dla niego, użyj pliku plugin:
Zwraca JSON struktura nadaje się do powrotu do JavaScript, / / lub null, jeśli ten plik nie jest reprezentować jako adres URL cdvfile.
Wpis JSONObject = filePlugin.getEntryForFile(file);
#### iOS
Cordova na iOS nie korzystać z tego samego `CordovaResourceApi` koncepcji jak Android. Na iOS należy użyć pliku plugin do konwersji między adresach URL i ścieżkach plików.
Uzyskać obiekt CDVFilesystem URL URL url ciąg CDVFilesystemURL * = [CDVFilesystemURL fileSystemURLWithString:cdvfileURL];
Uzyskać ścieżkę dla URL obiektu, stawka zerowa, jeśli nie mogą być mapowane do ścieżki pliku NSString * = [filePlugin filesystemPathForURL:url];
Dostać CDVFilesystem URL obiektu na ścieżkę urządzenia lub / / zerowe, jeśli nie może być reprezentowana jako adres URL cdvfile.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
Dostać reprezentację ciąg adresu URL obiektu NSString * cdvfileURL = [url absoluteString];
Jeśli twój plugin tworzy plik, i chcesz zwraca obiekt FileEntry dla niego, użyj pliku plugin:
Dostać CDVFilesystem URL obiektu na ścieżkę urządzenia lub / / zerowe, jeśli nie może być reprezentowana jako adres URL cdvfile.
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
Struktura wrócić do JavaScript NSDictionary * wpis = [filePlugin makeEntryForLocalURL:url]
#### JavaScript
W JavaScript, aby uzyskać `cdvfile://` adres URL z obiektu FileEntry lub DirectoryEntry, wystarczy zadzwonić `.toURL()` na to:
var cdvfileURL = entry.toURL();
W plugin reakcji obsługi przerobić od zwróconych struktury FileEntry do rzeczywistego obiektu wejścia, kod obsługi należy zaimportować pliku plugin i utworzyć nowy obiekt:
utworzyć odpowiedni wpis obiektu var wpis;
Jeśli (entryStruct.isDirectory) {wpis = nowy DirectoryEntry (entryStruct.name, entryStruct.fullPath, nowe FileSystem(entryStruct.filesystemName));} jeszcze {wpis = nowy FileEntry (entryStruct.name, entryStruct.fullPath, nowe FileSystem(entryStruct.filesystemName));}
\ No newline at end of file
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
Notes for plugin developers
===========================
These notes are primarily intended for Android and iOS developers who want to write plugins which interface with the file system using the File plugin.
Working with Cordova file system URLs
-------------------------------------
Since version 1.0.0, this plugin has used URLs with a `cdvfile` scheme for all communication over the bridge, rather than exposing raw device file system paths to JavaScript.
On the JavaScript side, this means that FileEntry and DirectoryEntry objects have a fullPath attribute which is relative to the root of the HTML file system. If your plugin's JavaScript API accepts a FileEntry or DirectoryEntry object, you should call `.toURL()` on that object before passing it across the bridge to native code.
### Converting cdvfile:// URLs to fileystem paths
Plugins which need to write to the filesystem may want to convert a received file system URL to an actual filesystem location. There are multiple ways of doing this, depending on the native platform.
It is important to remember that not all `cdvfile://` URLs are mappable to real files on the device. Some URLs can refer to assets on device which are not represented by files, or can even refer to remote resources. Because of these possibilities, plugins should always test whether they get a meaningful result back when trying to convert URLs to paths.
#### Android
On Android, the simplest method to convert a `cdvfile://` URL to a filesystem path is to use `org.apache.cordova.CordovaResourceApi`. `CordovaResourceApi` has several methods which can handle `cdvfile://` URLs:
// webView is a member of the Plugin class
CordovaResourceApi resourceApi = webView.getResourceApi();
// Obtain a file:/// URL representing this file on the device,
// or the same URL unchanged if it cannot be mapped to a file
Uri fileURL = resourceApi.remapUri(Uri.parse(cdvfileURL));
It is also possible to use the File plugin directly:
import org.apache.cordova.file.FileUtils;
import org.apache.cordova.file.FileSystem;
import java.net.MalformedURLException;
// Get the File plugin from the plugin manager
FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File");
// Given a URL, get a path for it
try {
String path = filePlugin.filesystemPathForURL(cdvfileURL);
} catch (MalformedURLException e) {
// The filesystem url wasn't recognized
}
To convert from a path to a `cdvfile://` URL:
import org.apache.cordova.file.LocalFilesystemURL;
// Get a LocalFilesystemURL object for a device path,
// or null if it cannot be represented as a cdvfile URL.
LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path);
// Get the string representation of the URL object
String cdvfileURL = url.toString();
If your plugin creates a file, and you want to return a FileEntry object for it, use the File plugin:
// Return a JSON structure suitable for returning to JavaScript,
// or null if this file is not representable as a cdvfile URL.
JSONObject entry = filePlugin.getEntryForFile(file);
#### iOS
Cordova on iOS does not use the same `CordovaResourceApi` concept as Android. On iOS, you should use the File plugin to convert between URLs and filesystem paths.
// Get a CDVFilesystem URL object from a URL string
CDVFilesystemURL* url = [CDVFilesystemURL fileSystemURLWithString:cdvfileURL];
// Get a path for the URL object, or nil if it cannot be mapped to a file
NSString* path = [filePlugin filesystemPathForURL:url];
// Get a CDVFilesystem URL object for a device path, or
// nil if it cannot be represented as a cdvfile URL.
CDVFilesystemURL* url = [filePlugin fileSystemURLforLocalPath:path];
// Get the string representation of the URL object
NSString* cdvfileURL = [url absoluteString];
If your plugin creates a file, and you want to return a FileEntry object for it, use the File plugin:
// Get a CDVFilesystem URL object for a device path, or
// nil if it cannot be represented as a cdvfile URL.
CDVFilesystemURL* url = [filePlugin fileSystemURLforLocalPath:path];
// Get a structure to return to JavaScript
NSDictionary* entry = [filePlugin makeEntryForLocalURL:url]
#### JavaScript
In JavaScript, to get a `cdvfile://` URL from a FileEntry or DirectoryEntry object, simply call `.toURL()` on it:
var cdvfileURL = entry.toURL();
In plugin response handlers, to convert from a returned FileEntry structure to an actual Entry object, your handler code should import the File plugin and create a new object:
// create appropriate Entry object
var entry;
if (entryStruct.isDirectory) {
entry = new DirectoryEntry(entryStruct.name, entryStruct.fullPath, new FileSystem(entryStruct.filesystemName));
} else {
entry = new FileEntry(entryStruct.name, entryStruct.fullPath, new FileSystem(entryStruct.filesystemName));
}
This diff is collapsed.
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Примечания для разработчиков плагинов
Эти примечания предназначены прежде всего для Android и iOS разработчиков, которые хотят писать плагины какой интерфейс с файловой системой, с помощью файла плагина.
## Работа с Кордова файловой системы URL
Начиная с версии 1.0.0, этот плагин использует URL-адресов с `cdvfile` схема для всех коммуникации через мост, а не подвергая пути файловой системы raw устройства для JavaScript.
На стороне JavaScript это означает, что объекты DirectoryEntry и FileEntry fullPath атрибут, который является по отношению к корневой файловой системе HTML. Если ваш плагин JavaScript API принимает объект DirectoryEntry или FileEntry, необходимо вызвать `.toURL()` для этого объекта перед передачей их через мост в машинный код.
### Преобразование cdvfile: / / URL-адреса в пути fileystem
Плагины, которые нужно написать в файловой системе может потребоваться преобразовать URL-адреса системы полученный файл в место фактической файловой системы. Существует несколько способов сделать это, в зависимости от родной платформе.
Важно помнить, что не все `cdvfile://` URL-адреса являются отображаемыми файлами на устройстве. Некоторые URL может относиться к активам на устройстве, которые не представлены файлы, или может даже обратиться к удаленным ресурсам. Из-за эти возможности плагины следует всегда проверять ли они получают результат обратно при попытке преобразовать URL-адреса в пути.
#### Android
На Android, самый простой способ для преобразования `cdvfile://` URL-адрес к пути файловой системы заключается в использовании `cordova-plugin-CordovaResourceApi` . `CordovaResourceApi`Есть несколько методов, которые можно обработать `cdvfile://` URL-адреса:
// webView is a member of the Plugin class
CordovaResourceApi resourceApi = webView.getResourceApi();
// Obtain a file:/// URL representing this file on the device,
// or the same URL unchanged if it cannot be mapped to a file
Uri fileURL = resourceApi.remapUri(Uri.parse(cdvfileURL));
Это также можно использовать плагин файл непосредственно:
import cordova-plugin-file.FileUtils;
import cordova-plugin-file.FileSystem;
import java.net.MalformedURLException;
// Get the File plugin from the plugin manager
FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File");
// Given a URL, get a path for it
try {
String path = filePlugin.filesystemPathForURL(cdvfileURL);
} catch (MalformedURLException e) {
// The filesystem url wasn't recognized
}
Для преобразования пути к `cdvfile://` URL-адрес:
import cordova-plugin-file.LocalFilesystemURL;
// Get a LocalFilesystemURL object for a device path,
// or null if it cannot be represented as a cdvfile URL.
LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path);
// Get the string representation of the URL object
String cdvfileURL = url.toString();
Если ваш плагин создает файл, и вы хотите вернуть объект FileEntry для него, используйте файл плагина:
// Return a JSON structure suitable for returning to JavaScript,
// or null if this file is not representable as a cdvfile URL.
JSONObject entry = filePlugin.getEntryForFile(file);
#### iOS
Кордова на iOS не использовать те же `CordovaResourceApi` понятие, как Android. На iOS вы должны использовать файл плагин для преобразования URL-адреса и пути файловой системы.
// Get a CDVFilesystem URL object from a URL string
CDVFilesystemURL* url = [CDVFilesystemURL fileSystemURLWithString:cdvfileURL];
// Get a path for the URL object, or nil if it cannot be mapped to a file
NSString* path = [filePlugin filesystemPathForURL:url];
// Get a CDVFilesystem URL object for a device path, or
// nil if it cannot be represented as a cdvfile URL.
CDVFilesystemURL* url = [filePlugin fileSystemURLforLocalPath:path];
// Get the string representation of the URL object
NSString* cdvfileURL = [url absoluteString];
Если ваш плагин создает файл, и вы хотите вернуть объект FileEntry для него, используйте файл плагина:
// Get a CDVFilesystem URL object for a device path, or
// nil if it cannot be represented as a cdvfile URL.
CDVFilesystemURL* url = [filePlugin fileSystemURLforLocalPath:path];
// Get a structure to return to JavaScript
NSDictionary* entry = [filePlugin makeEntryForLocalURL:url]
#### JavaScript
В JavaScript, чтобы получить `cdvfile://` URL от объекта DirectoryEntry или FileEntry, просто позвоните `.toURL()` на него:
var cdvfileURL = entry.toURL();
В плагин обработчики ответ для преобразования из возвращаемой структуры FileEntry объект фактического вступления, код обработчика следует импортировать файл плагина и создайте новый объект:
// create appropriate Entry object
var entry;
if (entryStruct.isDirectory) {
entry = new DirectoryEntry(entryStruct.name, entryStruct.fullPath, new FileSystem(entryStruct.filesystemName));
} else {
entry = new FileEntry(entryStruct.name, entryStruct.fullPath, new FileSystem(entryStruct.filesystemName));
}
This diff is collapsed.
This diff is collapsed.
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# 外掛程式開發人員注意事項
這些筆記主要用於 Android 和 iOS 開發者想要編寫外掛程式的介面與使用檔外掛程式的檔案系統。
## 工作與科爾多瓦檔案系統 Url
自從版本 1.0.0,這個外掛程式一直使用 Url 與 `cdvfile` 大橋,計畫為所有通信,而不是揭露 JavaScript 的原始設備檔案系統路徑。
在 JavaScript 方面,這意味著 FileEntry 和 DirectoryEntry 的物件有一個完整路徑屬性是相對於 HTML 檔案系統的根目錄。 如果你的外掛程式的 JavaScript API 接受一個 FileEntry 或 DirectoryEntry 的物件,你應該打電話給 `.toURL()` 對該物件之前將它從橋上傳遞給本機代碼。
### 轉換 cdvfile: / / fileystem 路徑的 Url
需要寫入到檔案系統的外掛程式可能想要將接收的檔案系統 URL 轉換為實際的檔案系統位置。有做這,根據本機平臺的多種方式。
很重要的是要記住,並不是所有 `cdvfile://` Url 是可映射到設備上的實際檔。 某些 Url 可以指在設備上沒有代表的檔,或甚至可以引用遠端資源的資產。 由於這些可能性,外掛程式應始終測試是否回來時試圖將 Url 轉換成路徑得到有意義的結果。
#### 安卓系統
在 android 系統,最簡單的方法來轉換 `cdvfile://` 檔案系統路徑的 URL 是使用 `org.apache.cordova.CordovaResourceApi``CordovaResourceApi`有幾種方法,可處理 `cdvfile://` 網址:
web 視圖是成員的外掛程式類 CordovaResourceApi resourceApi = webView.getResourceApi();
獲取表示此檔在設備上,file:/// URL / / 或 URL 相同變的如果它不能映射到檔 Uri fileURL = resourceApi.remapUri(Uri.parse(cdvfileURL));
它也是可以直接使用檔外掛程式:
導入 org.apache.cordova.file.FileUtils;
導入 org.apache.cordova.file.FileSystem;
導入 java.net.MalformedURLException;
得到檔外掛程式外掛程式管理器從 FileUtils filePlugin = (FileUtils)webView.pluginManager.getPlugin("File");
給定 URL,得到的路徑,因為它嘗試 {字串路徑 = filePlugin.filesystemPathForURL(cdvfileURL);} 趕上 (MalformedURLException e) {/ / 檔案系統 url 不承認}
要轉換到的路徑從 `cdvfile://` URL:
導入 org.apache.cordova.file.LocalFilesystemURL;
獲取設備的路徑,一個 LocalFilesystemURL 物件 / / 或如果它不能表示為 cdvfile 的 URL,則為 null。
LocalFilesystemURL url = filePlugin.filesystemURLforLocalPath(path);
得到的字串表示形式的 URL 物件字串 cdvfileURL = url.toString();
如果你的外掛程式創建一個檔,並且您想要為它返回一個 FileEntry 物件,使用該檔的外掛程式:
返回一個 JSON 結構適合於回到 JavaScript,/ / 或如果此檔不是可表示為 cdvfile 的 URL,則為 null。
JSONObject 條目 = filePlugin.getEntryForFile(file);
#### iOS
科爾多瓦在 iOS 上的不使用相同 `CordovaResourceApi` 作為 android 系統的概念。在 iOS,應使用檔外掛程式 Url 和檔案系統路徑之間進行轉換。
獲取一個物件,CDVFilesystem URL 從 url 字串 CDVFilesystemURL * = [CDVFilesystemURL fileSystemURLWithString:cdvfileURL];
獲取路徑 URL 物件,或為零,如果它不能映射到檔 NSString * 路徑 = [filePlugin filesystemPathForURL:url];
CDVFilesystem URL 物件獲取設備的路徑,或 / / 為零,如果它不能表示為 cdvfile 的 URL。
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
得到的字串表示形式的 URL 物件 NSString * cdvfileURL = [url absoluteString];
如果你的外掛程式創建一個檔,並且您想要為它返回一個 FileEntry 物件,使用該檔的外掛程式:
CDVFilesystem URL 物件獲取設備的路徑,或 / / 為零,如果它不能表示為 cdvfile 的 URL。
CDVFilesystemURL * url = [filePlugin fileSystemURLforLocalPath:path];
得到一個結構來返回進入 JavaScript NSDictionary * = [filePlugin makeEntryForLocalURL:url]
#### JavaScript
在 JavaScript 中,得到 `cdvfile://` URL 從 FileEntry 或 DirectoryEntry 的物件,只需調用 `.toURL()` 對它:
var cdvfileURL = entry.toURL();
在外掛程式回應處理常式,將從返回的 FileEntry 結構轉換為實際的條目物件,處理常式代碼應該導入檔外掛程式和創建新的物件:
創建適當的條目物件 var 條目;
如果 (entryStruct.isDirectory) {條目 = 新目錄 (entryStruct.name,entryStruct.fullPath,新 FileSystem(entryStruct.filesystemName));} 其他 {條目 = 新的 FileEntry (entryStruct.name,entryStruct.fullPath,新 FileSystem(entryStruct.filesystemName));}
\ No newline at end of file
{
"_from": "cordova-plugin-file@6.0.1",
"_id": "cordova-plugin-file@6.0.1",
"_inBundle": false,
"_integrity": "sha1-SWBrjBWlaI1HKPkuSnMloGHeB/U=",
"_location": "/cordova-plugin-file",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "cordova-plugin-file@6.0.1",
"name": "cordova-plugin-file",
"escapedName": "cordova-plugin-file",
"rawSpec": "6.0.1",
"saveSpec": null,
"fetchSpec": "6.0.1"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "http://r.cnpmjs.org/cordova-plugin-file/download/cordova-plugin-file-6.0.1.tgz",
"_shasum": "49606b8c15a5688d4728f92e4a7325a061de07f5",
"_spec": "cordova-plugin-file@6.0.1",
"_where": "/Users/ben/gitLab-project/party-build-cloud",
"author": {
"name": "Apache Software Foundation"
},
"bugs": {
"url": "https://issues.apache.org/jira/browse/CB"
},
"bundleDependencies": false,
"cordova": {
"id": "cordova-plugin-file",
"platforms": [
"android",
"browser",
"ios",
"osx",
"windows"
]
},
"deprecated": false,
"description": "Cordova File Plugin",
"devDependencies": {
"eslint": "^3.19.0",
"eslint-config-semistandard": "^11.0.0",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-import": "^2.3.0",
"eslint-plugin-node": "^5.0.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1"
},
"engines": {
"cordovaDependencies": {
"5.0.0": {
"cordova-android": ">=6.3.0"
},
"7.0.0": {
"cordova": ">100"
}
}
},
"homepage": "https://github.com/apache/cordova-plugin-file#readme",
"keywords": [
"cordova",
"file",
"ecosystem:cordova",
"cordova-android",
"cordova-browser",
"cordova-ios",
"cordova-osx",
"cordova-windows"
],
"license": "Apache-2.0",
"name": "cordova-plugin-file",
"repository": {
"type": "git",
"url": "git+https://github.com/apache/cordova-plugin-file.git"
},
"scripts": {
"eslint": "node node_modules/eslint/bin/eslint www && node node_modules/eslint/bin/eslint src && node node_modules/eslint/bin/eslint tests",
"test": "npm run eslint"
},
"types": "./types/index.d.ts",
"version": "6.0.1"
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment