Initial version.

This commit is contained in:
Aloïs Deniel
2018-01-04 19:36:18 +01:00
parent e6c43ec60b
commit ef4257e2f1
81 changed files with 1852 additions and 179 deletions
-3
View File
@@ -1,3 +0,0 @@
## [0.0.1] - TODO: Add release date.
* TODO: Describe initial release.
-1
View File
@@ -1 +0,0 @@
TODO: Add your license here.
+55 -6
View File
@@ -1,10 +1,59 @@
# appcenter
# Visual Studio App Center Plugin for Flutter
A new flutter plugin project.
[![pub package](https://img.shields.io/pub/v/appcenter.svg)](https://pub.dartlang.org/packages/appcenter)
Several Flutter plugins to use the [Microsoft Visual Studio App Center SDKs](https://docs.microsoft.com/en-us/appcenter/sdk/).
*Note*: This plugin is still under development, and some APIs (*Distribute* and *Push* are still missing) might not be available yet. [Feedback](https://github.com/aloisdeniel/flutter_plugin_appcenter/issues) and [Pull Requests](https://github.com/aloisdeniel/flutter_plugin_appcenter/pulls) are most welcome!
## Setup
To use this plugin:
1. Connect to [Visual Studio App Center Portal](https://appcenter.ms/apps)
1. From the index page, select `Add new` and create a new **iOS application (Platform: Objective-C/Swift)**, and keep your iOS app secret (ex: `123cfac9-123b-123a-123f-123273416a48`).
1. From the index page, select `Add new` and create a new **Android application (Platform: Java)**, and keep your Android app secret (ex: `321cfac9-123b-123a-123f-123273416a48`).
1. Add those as [dependencies in your pubspec.yaml file](https://flutter.io/platform-plugins/):
* `appcenter`
* `appcenter_analytics`
* `appcenter_crashes`
## Usage
### Global
```dart
import 'package:appcenter/appcenter.dart';
import 'package:appcenter_analytics/appcenter_analytics.dart';
import 'package:appcenter_crashes/appcenter_crashes.dart';
```
#### Starting services
```dart
final ios = defaultTargetPlatform == TargetPlatform.iOS;
var app_secret = ios ? "123cfac9-123b-123a-123f-123273416a48" : "321cfac9-123b-123a-123f-123273416a48";
await AppCenter.start(app_secret, [AppCenterAnalytics.id, AppCenterCrashes.id]);
```
#### Enabling or disabling services
```dart
await AppCenter.setEnabled(false); // global
await AppCenterAnalytics.setEnabled(false); // just a service
await AppCenterCrashes.setEnabled(false); // just a service
```
### Analytics
#### Track events
```dart
AppCenterAnalytics.trackEvent("map");
AppCenterAnalytics.trackEvent("casino", { "dollars" : "10" }); // with custom properties
```
## Getting Started
For help getting started with Flutter, view our online
[documentation](http://flutter.io/).
For help on editing plugin code, view the [documentation](https://flutter.io/platform-plugins/#edit-code).
See the `example` directory for a complete sample app using Visual Studio App Center.
@@ -1,29 +0,0 @@
package com.yourcompany.appcenter;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.PluginRegistry.Registrar;
/**
* AppcenterPlugin
*/
public class AppcenterPlugin implements MethodCallHandler {
/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "appcenter");
channel.setMethodCallHandler(new AppcenterPlugin());
}
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else {
result.notImplemented();
}
}
}
+36
View File
@@ -0,0 +1,36 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
if ENV['FLUTTER_FRAMEWORK_DIR'] == nil
abort('Please set FLUTTER_FRAMEWORK_DIR to the directory containing Flutter.framework')
end
target 'Runner' do
# Pods for Runner
# Flutter Pods
pod 'Flutter', :path => ENV['FLUTTER_FRAMEWORK_DIR']
if File.exists? '../.flutter-plugins'
flutter_root = File.expand_path('..')
File.foreach('../.flutter-plugins') { |line|
plugin = line.split(pattern='=')
if plugin.length == 2
name = plugin[0].strip()
path = plugin[1].strip()
resolved_path = File.expand_path("#{path}/ios", flutter_root)
pod name, :path => resolved_path
else
puts "Invalid plugin specification: #{line}"
end
}
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end
+46
View File
@@ -0,0 +1,46 @@
PODS:
- appcenter (0.0.1):
- AppCenter
- Flutter
- AppCenter (1.0.1):
- AppCenter/Analytics (= 1.0.1)
- AppCenter/Crashes (= 1.0.1)
- AppCenter/Analytics (1.0.1):
- AppCenter/Core
- AppCenter/Core (1.0.1)
- AppCenter/Crashes (1.0.1):
- AppCenter/Core
- appcenter_analytics (0.0.1):
- AppCenter/Analytics
- Flutter
- appcenter_crashes (0.0.1):
- AppCenter/Crashes
- Flutter
- Flutter (1.0.0)
DEPENDENCIES:
- appcenter (from `/Users/alois/flutter_plugin_appcenter/src/appcenter/ios`)
- appcenter_analytics (from `/Users/alois/flutter_plugin_appcenter/src/appcenter_analytics/ios`)
- appcenter_crashes (from `/Users/alois/flutter_plugin_appcenter/src/appcenter_crashes/ios`)
- Flutter (from `/Users/alois/flutter/bin/cache/artifacts/engine/ios`)
EXTERNAL SOURCES:
appcenter:
:path: /Users/alois/flutter_plugin_appcenter/src/appcenter/ios
appcenter_analytics:
:path: /Users/alois/flutter_plugin_appcenter/src/appcenter_analytics/ios
appcenter_crashes:
:path: /Users/alois/flutter_plugin_appcenter/src/appcenter_crashes/ios
Flutter:
:path: /Users/alois/flutter/bin/cache/artifacts/engine/ios
SPEC CHECKSUMS:
AppCenter: 1d9e08e4ffe7a8eab6e9741a12d27e44074e73a7
appcenter: ec63d9079174977ead44a0040ff083d6dd4c94c5
appcenter_analytics: 46cd35cb5fac57f7a4b2ae5d5040f984b4ad4b5a
appcenter_crashes: 1b06d86617183e4778779b59f85a25c4bbc89493
Flutter: d674e78c937094a75ac71dd77e921e840bea3dbf
PODFILE CHECKSUM: 351e02e34b831289961ec3558a535cbd2c4965d2
COCOAPODS: 1.3.1
+74 -1
View File
@@ -11,6 +11,7 @@
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
513419C92C83CB08834F5354 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 54CE9D792210C22D5C6E8F8E /* libPods-Runner.a */; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
@@ -43,6 +44,7 @@
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
54CE9D792210C22D5C6E8F8E /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -65,12 +67,28 @@
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
513419C92C83CB08834F5354 /* libPods-Runner.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0AF805DA95AB24C0E846AF07 /* Frameworks */ = {
isa = PBXGroup;
children = (
54CE9D792210C22D5C6E8F8E /* libPods-Runner.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
655B30EC1DAC555983B099AB /* Pods */ = {
isa = PBXGroup;
children = (
);
name = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
@@ -91,7 +109,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
655B30EC1DAC555983B099AB /* Pods */,
0AF805DA95AB24C0E846AF07 /* Frameworks */,
);
sourceTree = "<group>";
};
@@ -134,12 +153,15 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
51044FEB4B5932DC48FE2B1F /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
96D9A8465C60EEE798E7F303 /* [CP] Embed Pods Frameworks */,
18512D816A7A23D58E333AC8 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -200,6 +222,21 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
18512D816A7A23D58E333AC8 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -214,6 +251,42 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
};
51044FEB4B5932DC48FE2B1F /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
96D9A8465C60EEE798E7F303 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../../../../flutter/bin/cache/artifacts/engine/ios/Flutter.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
+3
View File
@@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
+44 -14
View File
@@ -1,6 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:appcenter/appcenter.dart';
import 'package:appcenter_analytics/appcenter_analytics.dart';
import 'package:appcenter_crashes/appcenter_crashes.dart';
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
import 'package:flutter/foundation.dart' show TargetPlatform;
void main() => runApp(new MyApp());
@@ -10,7 +14,15 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
String _app_secret;
String _installId = 'Unknown';
bool _areAnalyticsEnabled = false, _areCrashesEnabled = false;
_MyAppState() {
final ios = defaultTargetPlatform == TargetPlatform.iOS;
_app_secret = ios ? "a8a33033-ef2f-4911-a664-a7d118287ce7" : "3f1f3b0e-24ff-436a-b42d-3c08b117d46a";
}
@override
initState() {
@@ -20,22 +32,20 @@ class _MyAppState extends State<MyApp> {
// Platform messages are asynchronous, so we initialize in an async method.
initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await Appcenter.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
await AppCenter.start(_app_secret, [AppCenterAnalytics.id, AppCenterCrashes.id]);
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted)
return;
var installId = await AppCenter.installId;
var areAnalyticsEnabled = await AppCenterAnalytics.isEnabled;
var areCrashesEnabled = await AppCenterCrashes.isEnabled;
setState(() {
_platformVersion = platformVersion;
_installId = installId;
_areAnalyticsEnabled = areAnalyticsEnabled;
_areCrashesEnabled = areCrashesEnabled;
});
}
@@ -46,8 +56,28 @@ class _MyAppState extends State<MyApp> {
appBar: new AppBar(
title: new Text('Plugin example app'),
),
body: new Center(
child: new Text('Running on: $_platformVersion\n'),
body: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Text('Install identifier: $_installId'),
new Text('Analytics: $_areAnalyticsEnabled'),
new Text('Crashes: $_areCrashesEnabled'),
new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Text('Send events'),
new IconButton(
icon: new Icon(Icons.map),
tooltip: 'map',
onPressed: () { AppcenterAnalytics.trackEvent("map"); },
),
new IconButton(
icon: new Icon(Icons.casino),
tooltip: 'casino',
onPressed: () { AppcenterAnalytics.trackEvent("casino", { "dollars" : "10" }); },
),
])
]
),
),
);
+6 -42
View File
@@ -4,9 +4,6 @@ description: Demonstrates how to use the appcenter plugin.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.0
dev_dependencies:
@@ -14,46 +11,13 @@ dev_dependencies:
sdk: flutter
appcenter:
path: ../
path: ../src/appcenter
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
appcenter_analytics:
path: ../src/appcenter_analytics
appcenter_crashes:
path: ../src/appcenter_crashes
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.io/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.io/custom-fonts/#from-packages
-20
View File
@@ -1,20 +0,0 @@
#import "AppcenterPlugin.h"
@implementation AppcenterPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"appcenter"
binaryMessenger:[registrar messenger]];
AppcenterPlugin* instance = [[AppcenterPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"getPlatformVersion" isEqualToString:call.method]) {
result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
} else {
result(FlutterMethodNotImplemented);
}
}
@end
-11
View File
@@ -1,11 +0,0 @@
import 'dart:async';
import 'package:flutter/services.dart';
class Appcenter {
static const MethodChannel _channel =
const MethodChannel('appcenter');
static Future<String> get platformVersion =>
_channel.invokeMethod('getPlatformVersion');
}
-49
View File
@@ -1,49 +0,0 @@
name: appcenter
description: A new flutter plugin project.
version: 0.0.1
author:
homepage:
dependencies:
flutter:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
plugin:
androidPackage: com.yourcompany.appcenter
pluginClass: AppcenterPlugin
# To add assets to your plugin package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.io/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.
# To add custom fonts to your plugin package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.io/custom-fonts/#from-packages
+1
View File
@@ -0,0 +1 @@
## [0.0.1] - Initial release
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Aloïs Deniel
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.
+59
View File
@@ -0,0 +1,59 @@
# Visual Studio App Center Plugin for Flutter
[![pub package](https://img.shields.io/pub/v/appcenter.svg)](https://pub.dartlang.org/packages/appcenter)
Several Flutter plugins to use the [Microsoft Visual Studio App Center SDKs](https://docs.microsoft.com/en-us/appcenter/sdk/).
*Note*: This plugin is still under development, and some APIs (*Distribute* and *Push* are still missing) might not be available yet. [Feedback](https://github.com/aloisdeniel/flutter_plugin_appcenter/issues) and [Pull Requests](https://github.com/aloisdeniel/flutter_plugin_appcenter/pulls) are most welcome!
## Setup
To use this plugin:
1. Connect to [Visual Studio App Center Portal](https://appcenter.ms/apps)
1. From the index page, select `Add new` and create a new **iOS application (Platform: Objective-C/Swift)**, and keep your iOS app secret (ex: `123cfac9-123b-123a-123f-123273416a48`).
1. From the index page, select `Add new` and create a new **Android application (Platform: Java)**, and keep your Android app secret (ex: `321cfac9-123b-123a-123f-123273416a48`).
1. Add those as [dependencies in your pubspec.yaml file](https://flutter.io/platform-plugins/):
* `appcenter`
* `appcenter_analytics`
* `appcenter_crashes`
## Usage
### Global
```dart
import 'package:appcenter/appcenter.dart';
import 'package:appcenter_analytics/appcenter_analytics.dart';
import 'package:appcenter_crashes/appcenter_crashes.dart';
```
#### Starting services
```dart
final ios = defaultTargetPlatform == TargetPlatform.iOS;
var app_secret = ios ? "123cfac9-123b-123a-123f-123273416a48" : "321cfac9-123b-123a-123f-123273416a48";
await AppCenter.start(app_secret, [AppCenterAnalytics.id, AppCenterCrashes.id]);
```
#### Enabling or disabling services
```dart
await AppCenter.setEnabled(false); // global
await AppCenterAnalytics.setEnabled(false); // just a service
await AppCenterCrashes.setEnabled(false); // just a service
```
### Analytics
#### Track events
```dart
AppCenterAnalytics.trackEvent("map");
AppCenterAnalytics.trackEvent("casino", { "dollars" : "10" }); // with custom properties
```
## Getting Started
See the `example` directory for a complete sample app using Visual Studio App Center.
@@ -1,4 +1,4 @@
group 'com.yourcompany.appcenter'
group 'com.aloisdeniel.flutter.appcenter'
version '1.0-SNAPSHOT'
buildscript {
@@ -39,4 +39,8 @@ android {
lintOptions {
disable 'InvalidPackage'
}
dependencies {
def appCenterSdkVersion = '1.1.0'
compile "com.microsoft.appcenter:appcenter:${appCenterSdkVersion}"
}
}
View File
@@ -0,0 +1,101 @@
package com.aloisdeniel.flutter.appcenter;
import java.util.UUID;
import java.util.List;
import java.util.ArrayList;
import android.app.Application;
import com.microsoft.appcenter.AppCenter;
import com.microsoft.appcenter.utils.async.AppCenterConsumer;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.PluginRegistry.Registrar;
/**
* AppcenterPlugin
*/
public class AppcenterPlugin implements MethodCallHandler {
private Registrar registrar;
private AppcenterPlugin(Registrar registrar) {
this.registrar = registrar;
}
/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "aloisdeniel.github.com/flutter_plugin_appcenter/appcenter");
final AppcenterPlugin plugin = new AppcenterPlugin(registrar);
channel.setMethodCallHandler(plugin);
}
@Override
public void onMethodCall(MethodCall call, final Result result) {
Application app = this.registrar.activity().getApplication();
switch (call.method) {
case "installId":
AppCenter.getInstallId().thenAccept(new AppCenterConsumer<UUID>() {
@Override
public void accept(UUID uuid) {
result.success(uuid.toString());
}
});
break;
case "isEnabled":
AppCenter.isEnabled().thenAccept(new AppCenterConsumer<Boolean>() {
@Override
public void accept(Boolean enabled) {
result.success(enabled.booleanValue());
}
});
break;
case "setEnabled":
Boolean isEnabled = call.argument("isEnabled");
AppCenter.setEnabled(isEnabled).thenAccept(new AppCenterConsumer<Void>() {
@Override
public void accept(Void v) {
result.success(null);
}
});
break;
case "configure":
String secret = call.argument("app_secret");
AppCenter.configure(app, secret);
result.success(null);
break;
case "start":
String start_secret = call.argument("app_secret");
List<String> services = call.argument("services");
List<Class> servicesClasses = new ArrayList<Class>();
for (String name : services) {
try {
Class c = Class.forName(name);
servicesClasses.add(c);
}
catch(ClassNotFoundException notFound) {
}
}
Class[] servicesClassesArray = new Class[servicesClasses.size()];
servicesClassesArray = servicesClasses.toArray(servicesClassesArray);
AppCenter.start(app, start_secret, servicesClassesArray);
result.success(null);
break;
default:
result.notImplemented();
break;
}
}
}
@@ -0,0 +1,66 @@
#import "AppcenterPlugin.h"
#import <AppCenter/AppCenter.h>
@implementation AppcenterPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar
{
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"aloisdeniel.github.com/flutter_plugin_appcenter/appcenter"
binaryMessenger:[registrar messenger]];
AppcenterPlugin* instance = [[AppcenterPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
{
if([@"installId" isEqualToString:call.method])
{
result([[MSAppCenter installId] UUIDString]);
}
else if([@"isEnabled" isEqualToString:call.method])
{
result([NSNumber numberWithBool:[MSAppCenter isEnabled]]);
}
else if([@"setEnabled" isEqualToString:call.method])
{
// Arguments
NSNumber *isEnabled = call.arguments[@"isEnabled"];
// Invoking plugin method
[MSAppCenter setEnabled:isEnabled.boolValue];
result(nil);
}
else if([@"configure" isEqualToString:call.method])
{
// Arguments
NSString *secret = call.arguments[@"app_secret"];
// Invoking plugin method
[MSAppCenter configureWithAppSecret:secret];
result(nil);
}
else if([@"start" isEqualToString:call.method])
{
// Arguments
NSString *secret = call.arguments[@"app_secret"];
NSArray *services = call.arguments[@"services"];
// Processing arguments
NSMutableArray *serviceClasses = [[NSMutableArray alloc]init];
for (NSString* name in services) {
[serviceClasses addObject: NSClassFromString(name)];
}
// Invoking plugin method
[MSAppCenter start:secret withServices:serviceClasses];
result(nil);
}
else
{
result(FlutterMethodNotImplemented);
}
}
@end
@@ -8,13 +8,14 @@ Pod::Spec.new do |s|
s.description = <<-DESC
A new flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.homepage = 'http://github.com/aloisdeniel/flutter_plugin_appcenter'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.author = { 'Aloïs Deniel' => 'alois.deniel@outlook.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.dependency 'AppCenter'
s.ios.deployment_target = '8.0'
end
+27
View File
@@ -0,0 +1,27 @@
import 'dart:async';
import 'package:flutter/services.dart';
class AppCenter {
static const MethodChannel _channel = const MethodChannel('aloisdeniel.github.com/flutter_plugin_appcenter/appcenter');
/// Starts App Center services
static Future<String> configure(String app_secret) => _channel.invokeMethod('configure', <String, dynamic>{
'app_secret': app_secret,
});
static Future<String> start(String app_secret, List<String> services) => _channel.invokeMethod('start', <String, dynamic>{
'app_secret': app_secret,
'services': services
});
static Future<String> get installId => _channel.invokeMethod('installId');
static Future<bool> get isEnabled => _channel.invokeMethod('isEnabled');
static Future setEnabled(bool isEnabled) => _channel.invokeMethod('setEnabled', <String, bool>{
'isEnabled': isEnabled,
});
}
+12
View File
@@ -0,0 +1,12 @@
name: appcenter
description: Visual Studio App Center plugin for Flutter applications.
version: 0.0.1
author: Aloïs Deniel<alois.deniel@outlook.com>
homepage: https://github.com/aloisdeniel/flutter_plugin_appcenter
dependencies:
flutter:
sdk: flutter
flutter:
plugin:
androidPackage: com.aloisdeniel.flutter.appcenter
pluginClass: AppcenterPlugin
+9
View File
@@ -0,0 +1,9 @@
.DS_Store
.atom/
.idea
.packages
.pub/
build/
ios/.generated/
packages
pubspec.lock
+1
View File
@@ -0,0 +1 @@
## [0.0.1] - Initial release
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Aloïs Deniel
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.
+56
View File
@@ -0,0 +1,56 @@
# Visual Studio App Center (Analytics) Plugin for Flutter
[![pub package](https://img.shields.io/pub/v/appcenter.svg)](https://pub.dartlang.org/packages/appcenter)
Several Flutter plugins to use the [Microsoft Visual Studio App Center SDKs](https://docs.microsoft.com/en-us/appcenter/sdk/).
*Note*: This plugin is still under development, and some APIs (*Distribute* and *Push* are still missing) might not be available yet. [Feedback](https://github.com/aloisdeniel/flutter_plugin_appcenter/issues) and [Pull Requests](https://github.com/aloisdeniel/flutter_plugin_appcenter/pulls) are most welcome!
## Setup
To use this plugin:
1. Connect to [Visual Studio App Center Portal](https://appcenter.ms/apps)
1. From the index page, select `Add new` and create a new **iOS application (Platform: Objective-C/Swift)**, and keep your iOS app secret (ex: `123cfac9-123b-123a-123f-123273416a48`).
1. From the index page, select `Add new` and create a new **Android application (Platform: Java)**, and keep your Android app secret (ex: `321cfac9-123b-123a-123f-123273416a48`).
1. Add those as [dependencies in your pubspec.yaml file](https://flutter.io/platform-plugins/):
* `appcenter`
* `appcenter_analytics`
## Usage
### Global
```dart
import 'package:appcenter/appcenter.dart';
import 'package:appcenter_analytics/appcenter_analytics.dart';
```
#### Starting services
```dart
final ios = defaultTargetPlatform == TargetPlatform.iOS;
var app_secret = ios ? "123cfac9-123b-123a-123f-123273416a48" : "321cfac9-123b-123a-123f-123273416a48";
await AppCenter.start(app_secret, [AppCenterAnalytics.id]);
```
#### Enabling or disabling services
```dart
await AppCenter.setEnabled(false); // global
await AppCenterAnalytics.setEnabled(false); // just a service
```
### Analytics
#### Track events
```dart
AppCenterAnalytics.trackEvent("map");
AppCenterAnalytics.trackEvent("casino", { "dollars" : "10" }); // with custom properties
```
## Getting Started
See the `example` directory for a complete sample app using Visual Studio App Center.
@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
@@ -0,0 +1,46 @@
group 'com.aloisdeniel.flutter.appcenter_analytics'
version '1.0-SNAPSHOT'
buildscript {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
rootProject.allprojects {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 25
buildToolsVersion '25.0.3'
defaultConfig {
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
dependencies {
def appCenterSdkVersion = '1.1.0'
compile "com.microsoft.appcenter:appcenter-analytics:${appCenterSdkVersion}"
}
}
@@ -0,0 +1 @@
org.gradle.jvmargs=-Xmx1536M
Binary file not shown.
@@ -0,0 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
+160
View File
@@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+90
View File
@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@@ -0,0 +1 @@
rootProject.name = 'appcenter_analytics'
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yourcompany.appcenteranalytics">
</manifest>
@@ -0,0 +1,68 @@
package com.aloisdeniel.flutter.appcenter_analytics;
import java.util.UUID;
import java.util.Map;
import android.app.Application;
import com.microsoft.appcenter.analytics.Analytics;
import com.microsoft.appcenter.utils.async.AppCenterConsumer;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.PluginRegistry.Registrar;
/**
* AppcenterAnalyticsPlugin
*/
public class AppcenterAnalyticsPlugin implements MethodCallHandler {
private Registrar registrar;
private AppcenterAnalyticsPlugin(Registrar registrar) {
this.registrar = registrar;
}
/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "aloisdeniel.github.com/flutter_plugin_appcenter/appcenter_analytics");
final AppcenterAnalyticsPlugin plugin = new AppcenterAnalyticsPlugin(registrar);
channel.setMethodCallHandler(plugin);
}
@Override
public void onMethodCall(MethodCall call, final Result result) {
switch (call.method) {
case "isEnabled":
Analytics.isEnabled().thenAccept(new AppCenterConsumer<Boolean>() {
@Override
public void accept(Boolean enabled) {
result.success(enabled.booleanValue());
}
});
break;
case "setEnabled":
Boolean isEnabled = call.argument("isEnabled");
Analytics.setEnabled(isEnabled).thenAccept(new AppCenterConsumer<Void>() {
@Override
public void accept(Void v) {
result.success(null);
}
});
break;
case "trackEvent":
String name = call.argument("name");
Map<String, String> properties = call.argument("properties");
Analytics.trackEvent(name, properties);
break;
default:
result.notImplemented();
break;
}
}
}
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/build" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart Packages" level="project" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" />
</component>
</module>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android" name="Android">
<configuration>
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/android/gen" />
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/android/gen" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/android/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/android/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/android/assets" />
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/android/libs" />
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/android/proguard_logs" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$/android">
<sourceFolder url="file://$MODULE_DIR$/android/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/android/gen" isTestSource="false" generated="true" />
</content>
<content url="file://$MODULE_DIR$/example/android">
<sourceFolder url="file://$MODULE_DIR$/example/android/app/src/main/java" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Flutter for Android" level="project" />
</component>
</module>
+31
View File
@@ -0,0 +1,31 @@
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
@@ -0,0 +1,4 @@
#import <Flutter/Flutter.h>
@interface AppcenterAnalyticsPlugin : NSObject<FlutterPlugin>
@end
@@ -0,0 +1,55 @@
#import "AppCenterAnalyticsPlugin.h"
#import <AppCenterAnalytics/AppCenterAnalytics.h>
@implementation AppcenterAnalyticsPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar
{
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"aloisdeniel.github.com/flutter_plugin_appcenter/appcenter_analytics"
binaryMessenger:[registrar messenger]];
AppcenterAnalyticsPlugin* instance = [[AppcenterAnalyticsPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
{
if([@"isEnabled" isEqualToString:call.method])
{
result([NSNumber numberWithBool:[MSAnalytics isEnabled]]);
}
else if([@"setEnabled" isEqualToString:call.method])
{
// Arguments
NSNumber *isEnabled = call.arguments[@"isEnabled"];
// Invoking plugin method
[MSAnalytics setEnabled:isEnabled.boolValue];
result(nil);
}
else if([@"trackEvent" isEqualToString:call.method])
{
// Arguments
NSString *name = call.arguments[@"name"];
NSDictionary *properties = call.arguments[@"properties"];
// Invoking plugin method
if([properties count] == 0)
{
[MSAnalytics trackEvent:name];
}
else
{
[MSAnalytics trackEvent:name withProperties:properties];
}
result(nil);
}
else
{
result(FlutterMethodNotImplemented);
}
}
@end
@@ -0,0 +1,22 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'appcenter_analytics'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
A new flutter plugin project.
DESC
s.homepage = 'http://github.com/aloisdeniel/flutter_plugin_appcenter'
s.license = { :file => '../LICENSE' }
s.author = { 'Aloïs Deniel' => 'alois.deniel@outlook.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.dependency 'AppCenter/Analytics'
s.ios.deployment_target = '8.0'
end
@@ -0,0 +1,23 @@
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
import 'package:flutter/foundation.dart' show TargetPlatform;
class AppCenterAnalytics {
static String get id => (defaultTargetPlatform == TargetPlatform.iOS) ? "MSAnalytics" : "com.microsoft.appcenter.analytics.Analytics";
static const MethodChannel _channel = const MethodChannel('aloisdeniel.github.com/flutter_plugin_appcenter/appcenter_analytics');
static Future<bool> get isEnabled => _channel.invokeMethod('isEnabled');
static Future setEnabled(bool isEnabled) => _channel.invokeMethod('setEnabled', <String, bool>{
'isEnabled': isEnabled,
});
static Future trackEvent(String name, [Map<String,String> properties]) => _channel.invokeMethod('trackEvent', <String, dynamic>{
'name': name,
'properties' : properties ?? <String,String>{},
});
}
+14
View File
@@ -0,0 +1,14 @@
name: appcenter_analytics
description: Visual Studio App Center (Analytics) plugin for Flutter applications.
version: 0.0.1
author: Aloïs Deniel<alois.deniel@outlook.com>
homepage: https://github.com/aloisdeniel/flutter_plugin_appcenter
dependencies:
flutter:
sdk: flutter
flutter:
plugin:
androidPackage: com.aloisdeniel.flutter.appcenter_analytics
pluginClass: AppcenterAnalyticsPlugin
+9
View File
@@ -0,0 +1,9 @@
.DS_Store
.atom/
.idea
.packages
.pub/
build/
ios/.generated/
packages
pubspec.lock
+1
View File
@@ -0,0 +1 @@
## [0.0.1] - Initial release
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Aloïs Deniel
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.
+46
View File
@@ -0,0 +1,46 @@
# Visual Studio App Center (Crash) Plugin for Flutter
[![pub package](https://img.shields.io/pub/v/appcenter.svg)](https://pub.dartlang.org/packages/appcenter)
Several Flutter plugins to use the [Microsoft Visual Studio App Center SDKs](https://docs.microsoft.com/en-us/appcenter/sdk/).
*Note*: This plugin is still under development, and some APIs (*Distribute* and *Push* are still missing) might not be available yet. [Feedback](https://github.com/aloisdeniel/flutter_plugin_appcenter/issues) and [Pull Requests](https://github.com/aloisdeniel/flutter_plugin_appcenter/pulls) are most welcome!
## Setup
To use this plugin:
1. Connect to [Visual Studio App Center Portal](https://appcenter.ms/apps)
1. From the index page, select `Add new` and create a new **iOS application (Platform: Objective-C/Swift)**, and keep your iOS app secret (ex: `123cfac9-123b-123a-123f-123273416a48`).
1. From the index page, select `Add new` and create a new **Android application (Platform: Java)**, and keep your Android app secret (ex: `321cfac9-123b-123a-123f-123273416a48`).
1. Add those as [dependencies in your pubspec.yaml file](https://flutter.io/platform-plugins/):
* `appcenter`
* `appcenter_crashes`
## Usage
### Global
```dart
import 'package:appcenter/appcenter.dart';
import 'package:appcenter_crashes/appcenter_crashes.dart';
```
#### Starting service
```dart
final ios = defaultTargetPlatform == TargetPlatform.iOS;
var app_secret = ios ? "123cfac9-123b-123a-123f-123273416a48" : "321cfac9-123b-123a-123f-123273416a48";
await AppCenter.start(app_secret, [AppCenterCrashes.id]);
```
#### Enabling or disabling service
```dart
await AppCenterCrashes.setEnabled(false); // just a service
```
## Getting Started
See the `example` directory for a complete sample app using Visual Studio App Center.
+8
View File
@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
@@ -0,0 +1,46 @@
group 'com.yourcompany.appcentercrashes'
version '1.0-SNAPSHOT'
buildscript {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
rootProject.allprojects {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 25
buildToolsVersion '25.0.3'
defaultConfig {
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
dependencies {
def appCenterSdkVersion = '1.1.0'
compile "com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}"
}
}
@@ -0,0 +1 @@
org.gradle.jvmargs=-Xmx1536M
Binary file not shown.
@@ -0,0 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
+160
View File
@@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+90
View File
@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@@ -0,0 +1 @@
rootProject.name = 'appcenter_crashes'
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yourcompany.appcentercrashes">
</manifest>
@@ -0,0 +1,62 @@
package com.aloisdeniel.flutter.appcenter_crashes;
import java.util.UUID;
import android.app.Application;
import com.microsoft.appcenter.crashes.Crashes;
import com.microsoft.appcenter.utils.async.AppCenterConsumer;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.PluginRegistry.Registrar;
/**
* AppcenterCrashesPlugin
*/
public class AppcenterCrashesPlugin implements MethodCallHandler {
private Registrar registrar;
private AppcenterCrashesPlugin(Registrar registrar) {
this.registrar = registrar;
}
/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "aloisdeniel.github.com/flutter_plugin_appcenter/appcenter_crashes");
final AppcenterCrashesPlugin plugin = new AppcenterCrashesPlugin(registrar);
channel.setMethodCallHandler(plugin);
}
@Override
public void onMethodCall(MethodCall call, final Result result) {
switch (call.method) {
case "isEnabled":
Crashes.isEnabled().thenAccept(new AppCenterConsumer<Boolean>() {
@Override
public void accept(Boolean enabled) {
result.success(enabled.booleanValue());
}
});
break;
case "setEnabled":
Boolean isEnabled = call.argument("isEnabled");
Crashes.setEnabled(isEnabled).thenAccept(new AppCenterConsumer<Void>() {
@Override
public void accept(Void v) {
result.success(null);
}
});
break;
default:
result.notImplemented();
break;
}
}
}
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/build" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart Packages" level="project" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" />
</component>
</module>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android" name="Android">
<configuration>
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/android/gen" />
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/android/gen" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/android/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/android/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/android/assets" />
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/android/libs" />
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/android/proguard_logs" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$/android">
<sourceFolder url="file://$MODULE_DIR$/android/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/android/gen" isTestSource="false" generated="true" />
</content>
<content url="file://$MODULE_DIR$/example/android">
<sourceFolder url="file://$MODULE_DIR$/example/android/app/src/main/java" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Flutter for Android" level="project" />
</component>
</module>
+31
View File
@@ -0,0 +1,31 @@
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
@@ -0,0 +1,4 @@
#import <Flutter/Flutter.h>
@interface AppcenterCrashesPlugin : NSObject<FlutterPlugin>
@end
@@ -0,0 +1,37 @@
#import "AppcenterCrashesPlugin.h"
#import <AppCenterCrashes/AppCenterCrashes.h>
@implementation AppcenterCrashesPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar
{
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"aloisdeniel.github.com/flutter_plugin_appcenter/appcenter_crashes"
binaryMessenger:[registrar messenger]];
AppcenterCrashesPlugin* instance = [[AppcenterCrashesPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
{
if([@"isEnabled" isEqualToString:call.method])
{
result([NSNumber numberWithBool:[MSCrashes isEnabled]]);
}
else if([@"setEnabled" isEqualToString:call.method])
{
// Arguments
NSNumber *isEnabled = call.arguments[@"isEnabled"];
// Invoking plugin method
[MSCrashes setEnabled:isEnabled.boolValue];
result(nil);
}
else
{
result(FlutterMethodNotImplemented);
}
}
@end
@@ -0,0 +1,22 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'appcenter_crashes'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
A new flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.dependency 'AppCenter/Crashes'
s.ios.deployment_target = '8.0'
end
@@ -0,0 +1,18 @@
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
import 'package:flutter/foundation.dart' show TargetPlatform;
class AppCenterCrashes {
static String get id => (defaultTargetPlatform == TargetPlatform.iOS) ? "MSCrashes" : "com.microsoft.appcenter.crashes.Crashes";
static const MethodChannel _channel = const MethodChannel('aloisdeniel.github.com/flutter_plugin_appcenter/appcenter_crashes');
static Future<bool> get isEnabled => _channel.invokeMethod('isEnabled');
static Future setEnabled(bool isEnabled) => _channel.invokeMethod('setEnabled', <String, bool>{
'isEnabled': isEnabled,
});
}
+14
View File
@@ -0,0 +1,14 @@
name: appcenter_crashes
description: Visual Studio App Center (Crashes) plugin for Flutter applications.
version: 0.0.1
author: Aloïs Deniel<alois.deniel@outlook.com>
homepage: https://github.com/aloisdeniel/flutter_plugin_appcenter
dependencies:
flutter:
sdk: flutter
flutter:
plugin:
androidPackage: com.aloisdeniel.flutter.appcenter_crashes
pluginClass: AppcenterCrashesPlugin