1618904271
With Next.js, it is possible to load modules based on conditions with the help of dynamic import.
Typically, it is impossible to import modules based on the condition. Whenever a page loads, all the imported modules on that particular page also get loaded.
const allowImport = true;
if (allowImport) {
import DynamicComponent from "../components/hello";
}
export default function Home() {
return (
<div>
<DynamicComponent />
</div>
)
}
#javascript #software-development #programming #next #react
1649042880
React native bridge for AppAuth - an SDK for communicating with OAuth2 providers
This versions supports react-native@0.63+
. The last pre-0.63 compatible version is v5.1.3
.
React Native bridge for AppAuth-iOS and AppAuth-Android SDKS for communicating with OAuth 2.0 and OpenID Connect providers.
This library should support any OAuth provider that implements the OAuth2 spec.
We only support the Authorization Code Flow.
AppAuth is a mature OAuth client implementation that follows the best practices set out in RFC 8252 - OAuth 2.0 for Native Apps including using SFAuthenticationSession
and SFSafariViewController
on iOS, and Custom Tabs on Android. WebView
s are explicitly not supported due to the security and usability reasons explained in Section 8.12 of RFC 8252.
AppAuth also supports the PKCE ("Pixy") extension to OAuth which was created to secure authorization codes in public clients when custom URI scheme redirects are used.
To learn more, read this short introduction to OAuth and PKCE on the Formidable blog.
See Usage for example configurations, and the included Example application for a working sample.
authorize
This is the main function to use for authentication. Invoking this function will do the whole login flow and returns the access token, refresh token and access token expiry date when successful, or it throws an error when not successful.
import { authorize } from 'react-native-app-auth';
const config = {
issuer: '<YOUR_ISSUER_URL>',
clientId: '<YOUR_CLIENT_ID>',
redirectUrl: '<YOUR_REDIRECT_URL>',
scopes: ['<YOUR_SCOPES_ARRAY>'],
};
const result = await authorize(config);
prefetchConfiguration
ANDROID This will prefetch the authorization service configuration. Invoking this function is optional and will speed up calls to authorize. This is only supported on Android.
import { prefetchConfiguration } from 'react-native-app-auth';
const config = {
warmAndPrefetchChrome: true,
issuer: '<YOUR_ISSUER_URL>',
clientId: '<YOUR_CLIENT_ID>',
redirectUrl: '<YOUR_REDIRECT_URL>',
scopes: ['<YOUR_SCOPES_ARRAY>'],
};
prefetchConfiguration(config);
This is your configuration object for the client. The config is passed into each of the methods with optional overrides.
string
) base URI of the authentication server. If no serviceConfiguration
(below) is provided, issuer is a mandatory field, so that the configuration can be fetched from the issuer's OIDC discovery endpoint.object
) you may manually configure token exchange endpoints in cases where the issuer does not support the OIDC discovery protocol, or simply to avoid an additional round trip to fetch the configuration. If no issuer
(above) is provided, the service configuration is mandatory.string
) REQUIRED fully formed url to the OAuth authorization endpointstring
) REQUIRED fully formed url to the OAuth token exchange endpointstring
) fully formed url to the OAuth token revocation endpoint. If you want to be able to revoke a token and no issuer
is specified, this field is mandatory.string
) fully formed url to your OAuth/OpenID Connect registration endpoint. Only necessary for servers that require client registration.string
) fully formed url to your OpenID Connect end session endpoint. If you want to be able to end a user's session and no issuer
is specified, this field is mandatory.string
) REQUIRED your client id on the auth serverstring
) client secret to pass to token exchange requests. :warning: Read more about client secretsstring
) REQUIRED the url that links back to your app with the auth codearray<string>
) the scopes for your token, e.g. ['email', 'offline_access']
.object
) additional parameters that will be passed in the authorization request. Must be string values! E.g. setting additionalParameters: { hello: 'world', foo: 'bar' }
would add hello=world&foo=bar
to the authorization request.string
) ANDROID Client Authentication Method. Can be either basic
(default) for Basic Authentication or post
for HTTP POST body Authenticationboolean
) ANDROID whether to allow requests over plain HTTP or with self-signed SSL certificates. :warning: Can be useful for testing against local server, should not be used in production. This setting has no effect on iOS; to enable insecure HTTP requests, add a NSExceptionAllowsInsecureHTTPLoads exception to your App Transport Security settings.object
) ANDROID you can specify custom headers to pass during authorize request and/or token request.{ [key: string]: value }
) headers to be passed during authorization request.{ [key: string]: value }
) headers to be passed during token retrieval request.{ [key: string]: value }
) headers to be passed during registration request.{ [key: string]: value }
) IOS you can specify additional headers to be passed for all authorize, refresh, and register requests.boolean
) (default: true) optionally allows not sending the nonce parameter, to support non-compliant providersboolean
) (default: true) optionally allows not sending the code_challenge parameter and skipping PKCE code verification, to support non-compliant providers.boolean
) (default: false) just return the authorization response, instead of automatically exchanging the authorization code. This is useful if this exchange needs to be done manually (not client-side)number
) configure the request timeout interval in seconds. This must be a positive number. The default values are 60 seconds on iOS and 15 seconds on Android.This is the result from the auth server:
string
) the access tokenstring
) the token expiration dateObject
) additional url parameters from the authorizationEndpoint response.Object
) additional url parameters from the tokenEndpoint response.string
) the id tokenstring
) the refresh tokenstring
) the token type, e.g. Bearerstring
]) the scopes the user has agreed to be grantedstring
) the authorization code (only if skipCodeExchange=true
)string
) the codeVerifier value used for the PKCE exchange (only if both skipCodeExchange=true
and usePKCE=true
)refresh
This method will refresh the accessToken using the refreshToken. Some auth providers will also give you a new refreshToken
import { refresh } from 'react-native-app-auth';
const config = {
issuer: '<YOUR_ISSUER_URL>',
clientId: '<YOUR_CLIENT_ID>',
redirectUrl: '<YOUR_REDIRECT_URL>',
scopes: ['<YOUR_SCOPES_ARRAY>'],
};
const result = await refresh(config, {
refreshToken: `<REFRESH_TOKEN>`,
});
revoke
This method will revoke a token. The tokenToRevoke can be either an accessToken or a refreshToken
import { revoke } from 'react-native-app-auth';
const config = {
issuer: '<YOUR_ISSUER_URL>',
clientId: '<YOUR_CLIENT_ID>',
redirectUrl: '<YOUR_REDIRECT_URL>',
scopes: ['<YOUR_SCOPES_ARRAY>'],
};
const result = await revoke(config, {
tokenToRevoke: `<TOKEN_TO_REVOKE>`,
includeBasicAuth: true,
sendClientId: true,
});
logout
This method will logout a user, as per the OpenID Connect RP Initiated Logout specification. It requires an idToken
, obtained after successfully authenticating with OpenID Connect, and a URL to redirect back after the logout has been performed.
import { logout } from 'react-native-app-auth';
const config = {
issuer: '<YOUR_ISSUER_URL>',
};
const result = await logout(config, {
idToken: '<ID_TOKEN>',
postLogoutRedirectUrl: '<POST_LOGOUT_URL>',
});
register
This will perform dynamic client registration on the given provider. If the provider supports dynamic client registration, it will generate a clientId
for you to use in subsequent calls to this library.
import { register } from 'react-native-app-auth';
const registerConfig = {
issuer: '<YOUR_ISSUER_URL>',
redirectUrls: ['<YOUR_REDIRECT_URL>', '<YOUR_OTHER_REDIRECT_URL>'],
};
const registerResult = await register(registerConfig);
string
) same as in authorization configobject
) same as in authorization configarray<string>
) REQUIRED specifies all of the redirect urls that your client will use for authenticationarray<string>
) an array that specifies which OAuth 2.0 response types your client will use. The default value is ['code']
array<string>
) an array that specifies which OAuth 2.0 grant types your client will use. The default value is ['authorization_code']
string
) requests a specific subject type for your clientstring
) specifies which clientAuthMethod
your client will use for authentication. The default value is 'client_secret_basic'
object
) additional parameters that will be passed in the registration request. Must be string values! E.g. setting additionalParameters: { hello: 'world', foo: 'bar' }
would add hello=world&foo=bar
to the authorization request.boolean
) ANDROID same as in authorization configobject
) ANDROID same as in authorization confignumber
) configure the request timeout interval in seconds. This must be a positive number. The default values are 60 seconds on iOS and 15 seconds on Android.This is the result from the auth server
string
) the assigned client idstring
) OPTIONAL date string of when the client id was issuedstring
) OPTIONAL the assigned client secretstring
) date string of when the client secret expires, which will be provided if clientSecret
is provided. If new Date(clientSecretExpiresAt).getTime() === 0
, then the secret never expiresstring
) OPTIONAL uri that can be used to perform subsequent operations on the registrationstring
) token that can be used at the endpoint given by registrationClientUri
to perform subsequent operations on the registration. Will be provided if registrationClientUri
is providednpm install react-native-app-auth --save
To setup the iOS project, you need to perform three steps:
Install native dependencies
This library depends on the native AppAuth-ios project. To keep the React Native library agnostic of your dependency management method, the native libraries are not distributed as part of the bridge.
AppAuth supports three options for dependency management.
cd ios
pod install
2. Carthage
With Carthage, add the following line to your Cartfile
:
github "openid/AppAuth-iOS" "master"
Then run carthage update --platform iOS
.
Drag and drop AppAuth.framework
from ios/Carthage/Build/iOS
under Frameworks
in Xcode
.
Add a copy files build step for AppAuth.framework
: open Build Phases on Xcode, add a new "Copy Files" phase, choose "Frameworks" as destination, add AppAuth.framework
and ensure "Code Sign on Copy" is checked.
3. Static Library
You can also use AppAuth-iOS as a static library. This requires linking the library and your project and including the headers. Suggested configuration:
AppAuth.xcodeproj
to your Workspace.AppAuth-iOS/Source
to your search paths of your target ("Build Settings -> "Header Search Paths").Register redirect URL scheme
If you intend to support iOS 10 and older, you need to define the supported redirect URL schemes in your Info.plist
as follows:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.your.app.identifier</string>
<key>CFBundleURLSchemes</key>
<array>
<string>io.identityserver.demo</string>
</array>
</dict>
</array>
CFBundleURLName
is any globally unique string. A common practice is to use your app identifier.CFBundleURLSchemes
is an array of URL schemes your app needs to handle. The scheme is the beginning of your OAuth Redirect URL, up to the scheme separator (:
) character. E.g. if your redirect uri is com.myapp://oauth
, then the url scheme will is com.myapp
.Define openURL callback in AppDelegate
You need to retain the auth session, in order to continue the authorization flow from the redirect. Follow these steps:
RNAppAuth
will call on the given app's delegate via [UIApplication sharedApplication].delegate
. Furthermore, RNAppAuth
expects the delegate instance to conform to the protocol RNAppAuthAuthorizationFlowManager
. Make AppDelegate
conform to RNAppAuthAuthorizationFlowManager
with the following changes to AppDelegate.h
:
+ #import "RNAppAuthAuthorizationFlowManager.h"
- @interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
+ @interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, RNAppAuthAuthorizationFlowManager>
+ @property(nonatomic, weak)id<RNAppAuthAuthorizationFlowManagerDelegate>authorizationFlowManagerDelegate;
Add the following code to AppDelegate.m
(to support iOS <= 10 and React Navigation deep linking)
+ - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *, id> *) options {
+ if ([self.authorizationFlowManagerDelegate resumeExternalUserAgentFlowWithURL:url]) {
+ return YES;
+ }
+ return [RCTLinkingManager application:app openURL:url options:options];
+ }
If you want to support universal links, add the following to AppDelegate.m
under continueUserActivity
+ if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
+ if (self.authorizationFlowManagerDelegate) {
+ BOOL resumableAuth = [self.authorizationFlowManagerDelegate resumeExternalUserAgentFlowWithURL:userActivity.webpageURL];
+ if (resumableAuth) {
+ return YES;
+ }
+ }
+ }
The approach mentioned should work with Swift. In this case one should make AppDelegate
conform to RNAppAuthAuthorizationFlowManager
. Note that this is not tested/guaranteed by the maintainers.
Steps:
swift-Bridging-Header.h
should include a reference to #import "RNAppAuthAuthorizationFlowManager.h
, like so:#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTBridgeDelegate.h>
#import <React/RCTBridge.h>
#import "RNAppAuthAuthorizationFlowManager.h" // <-- Add this header
#if DEBUG
#import <FlipperKit/FlipperClient.h>
// etc...
2. AppDelegate.swift
should implement the RNAppAuthorizationFlowManager
protocol and have a handler for url deep linking. The result should look something like this:
@UIApplicationMain
class AppDelegate: UIApplicationDelegate, RNAppAuthAuthorizationFlowManager { //<-- note the additional RNAppAuthAuthorizationFlowManager protocol
public weak var authorizationFlowManagerDelegate: RNAppAuthAuthorizationFlowManagerDelegate? // <-- this property is required by the protocol
//"open url" delegate function for managing deep linking needs to call the resumeExternalUserAgentFlowWithURL method
func application(
_ app: UIApplication,
open url: URL,
options: [UIApplicationOpenURLOptionsKey: Any] = [:]) -> Bool {
return authorizationFlowManagerDelegate?.resumeExternalUserAgentFlowWithURL(with: url) ?? false
}
}
Note: for RN >= 0.57, you will get a warning about compile being obsolete. To get rid of this warning, use patch-package to replace compile with implementation as in this PR - we're not deploying this right now, because it would break the build for RN < 57.
To setup the Android project, you need to add redirect scheme manifest placeholder:
To capture the authorization redirect, add the following property to the defaultConfig in android/app/build.gradle
:
android {
defaultConfig {
manifestPlaceholders = [
appAuthRedirectScheme: 'io.identityserver.demo'
]
}
}
The scheme is the beginning of your OAuth Redirect URL, up to the scheme separator (:
) character. E.g. if your redirect uri is com.myapp://oauth
, then the url scheme will is com.myapp
. The scheme must be in lowercase.
NOTE: When integrating with React Navigation deep linking, be sure to make this scheme (and the scheme in the config's redirectUrl) unique from the scheme defined in the deep linking intent-filter. E.g. if the scheme in your intent-filter is set to com.myapp
, then update the above scheme/redirectUrl to be com.myapp.auth
as seen here.
import { authorize } from 'react-native-app-auth';
// base config
const config = {
issuer: '<YOUR_ISSUER_URL>',
clientId: '<YOUR_CLIENT_ID>',
redirectUrl: '<YOUR_REDIRECT_URL>',
scopes: ['<YOUR_SCOPE_ARRAY>'],
};
// use the client to make the auth request and receive the authState
try {
const result = await authorize(config);
// result includes accessToken, accessTokenExpirationDate and refreshToken
} catch (error) {
console.log(error);
}
Values are in the code
field of the rejected Error object.
service_configuration_fetch_error
- could not fetch the service configurationauthentication_failed
- user authentication failedtoken_refresh_failed
- could not exchange the refresh token for a new JWTregistration_failed
- could not registerbrowser_not_found
(Android only) - no suitable browser installedSome authentication providers, including examples cited below, require you to provide a client secret. The authors of the AppAuth library
strongly recommend you avoid using static client secrets in your native applications whenever possible. Client secrets derived via a dynamic client registration are safe to use, but static client secrets can be easily extracted from your apps and allow others to impersonate your app and steal user data. If client secrets must be used by the OAuth2 provider you are integrating with, we strongly recommend performing the code exchange step on your backend, where the client secret can be kept hidden.
Having said this, in some cases using client secrets is unavoidable. In these cases, a clientSecret
parameter can be provided to authorize
/refresh
calls when performing a token request.
Recommendations on secure token storage can be found here.
Active: Formidable is actively working on this project, and we expect to continue for work for the foreseeable future. Bug reports, feature requests and pull requests are welcome.
These providers are OpenID compliant, which means you can use autodiscovery.
These providers implement the OAuth2 spec, but are not OpenID providers, which means you must configure the authorization and token endpoints yourself.
Download Details:
Author: FormidableLabs
Source Code: https://github.com/FormidableLabs/react-native-app-auth
License: MIT License
1632537859
Not babashka. Node.js babashka!?
Ad-hoc CLJS scripting on Node.js.
Experimental. Please report issues here.
Nbb's main goal is to make it easy to get started with ad hoc CLJS scripting on Node.js.
Additional goals and features are:
Nbb requires Node.js v12 or newer.
CLJS code is evaluated through SCI, the same interpreter that powers babashka. Because SCI works with advanced compilation, the bundle size, especially when combined with other dependencies, is smaller than what you get with self-hosted CLJS. That makes startup faster. The trade-off is that execution is less performant and that only a subset of CLJS is available (e.g. no deftype, yet).
Install nbb
from NPM:
$ npm install nbb -g
Omit -g
for a local install.
Try out an expression:
$ nbb -e '(+ 1 2 3)'
6
And then install some other NPM libraries to use in the script. E.g.:
$ npm install csv-parse shelljs zx
Create a script which uses the NPM libraries:
(ns script
(:require ["csv-parse/lib/sync$default" :as csv-parse]
["fs" :as fs]
["path" :as path]
["shelljs$default" :as sh]
["term-size$default" :as term-size]
["zx$default" :as zx]
["zx$fs" :as zxfs]
[nbb.core :refer [*file*]]))
(prn (path/resolve "."))
(prn (term-size))
(println (count (str (fs/readFileSync *file*))))
(prn (sh/ls "."))
(prn (csv-parse "foo,bar"))
(prn (zxfs/existsSync *file*))
(zx/$ #js ["ls"])
Call the script:
$ nbb script.cljs
"/private/tmp/test-script"
#js {:columns 216, :rows 47}
510
#js ["node_modules" "package-lock.json" "package.json" "script.cljs"]
#js [#js ["foo" "bar"]]
true
$ ls
node_modules
package-lock.json
package.json
script.cljs
Nbb has first class support for macros: you can define them right inside your .cljs
file, like you are used to from JVM Clojure. Consider the plet
macro to make working with promises more palatable:
(defmacro plet
[bindings & body]
(let [binding-pairs (reverse (partition 2 bindings))
body (cons 'do body)]
(reduce (fn [body [sym expr]]
(let [expr (list '.resolve 'js/Promise expr)]
(list '.then expr (list 'clojure.core/fn (vector sym)
body))))
body
binding-pairs)))
Using this macro we can look async code more like sync code. Consider this puppeteer example:
(-> (.launch puppeteer)
(.then (fn [browser]
(-> (.newPage browser)
(.then (fn [page]
(-> (.goto page "https://clojure.org")
(.then #(.screenshot page #js{:path "screenshot.png"}))
(.catch #(js/console.log %))
(.then #(.close browser)))))))))
Using plet
this becomes:
(plet [browser (.launch puppeteer)
page (.newPage browser)
_ (.goto page "https://clojure.org")
_ (-> (.screenshot page #js{:path "screenshot.png"})
(.catch #(js/console.log %)))]
(.close browser))
See the puppeteer example for the full code.
Since v0.0.36, nbb includes promesa which is a library to deal with promises. The above plet
macro is similar to promesa.core/let
.
$ time nbb -e '(+ 1 2 3)'
6
nbb -e '(+ 1 2 3)' 0.17s user 0.02s system 109% cpu 0.168 total
The baseline startup time for a script is about 170ms seconds on my laptop. When invoked via npx
this adds another 300ms or so, so for faster startup, either use a globally installed nbb
or use $(npm bin)/nbb script.cljs
to bypass npx
.
Nbb does not depend on any NPM dependencies. All NPM libraries loaded by a script are resolved relative to that script. When using the Reagent module, React is resolved in the same way as any other NPM library.
To load .cljs
files from local paths or dependencies, you can use the --classpath
argument. The current dir is added to the classpath automatically. So if there is a file foo/bar.cljs
relative to your current dir, then you can load it via (:require [foo.bar :as fb])
. Note that nbb
uses the same naming conventions for namespaces and directories as other Clojure tools: foo-bar
in the namespace name becomes foo_bar
in the directory name.
To load dependencies from the Clojure ecosystem, you can use the Clojure CLI or babashka to download them and produce a classpath:
$ classpath="$(clojure -A:nbb -Spath -Sdeps '{:aliases {:nbb {:replace-deps {com.github.seancorfield/honeysql {:git/tag "v2.0.0-rc5" :git/sha "01c3a55"}}}}}')"
and then feed it to the --classpath
argument:
$ nbb --classpath "$classpath" -e "(require '[honey.sql :as sql]) (sql/format {:select :foo :from :bar :where [:= :baz 2]})"
["SELECT foo FROM bar WHERE baz = ?" 2]
Currently nbb
only reads from directories, not jar files, so you are encouraged to use git libs. Support for .jar
files will be added later.
The name of the file that is currently being executed is available via nbb.core/*file*
or on the metadata of vars:
(ns foo
(:require [nbb.core :refer [*file*]]))
(prn *file*) ;; "/private/tmp/foo.cljs"
(defn f [])
(prn (:file (meta #'f))) ;; "/private/tmp/foo.cljs"
Nbb includes reagent.core
which will be lazily loaded when required. You can use this together with ink to create a TUI application:
$ npm install ink
ink-demo.cljs
:
(ns ink-demo
(:require ["ink" :refer [render Text]]
[reagent.core :as r]))
(defonce state (r/atom 0))
(doseq [n (range 1 11)]
(js/setTimeout #(swap! state inc) (* n 500)))
(defn hello []
[:> Text {:color "green"} "Hello, world! " @state])
(render (r/as-element [hello]))
Working with callbacks and promises can become tedious. Since nbb v0.0.36 the promesa.core
namespace is included with the let
and do!
macros. An example:
(ns prom
(:require [promesa.core :as p]))
(defn sleep [ms]
(js/Promise.
(fn [resolve _]
(js/setTimeout resolve ms))))
(defn do-stuff
[]
(p/do!
(println "Doing stuff which takes a while")
(sleep 1000)
1))
(p/let [a (do-stuff)
b (inc a)
c (do-stuff)
d (+ b c)]
(prn d))
$ nbb prom.cljs
Doing stuff which takes a while
Doing stuff which takes a while
3
Also see API docs.
Since nbb v0.0.75 applied-science/js-interop is available:
(ns example
(:require [applied-science.js-interop :as j]))
(def o (j/lit {:a 1 :b 2 :c {:d 1}}))
(prn (j/select-keys o [:a :b])) ;; #js {:a 1, :b 2}
(prn (j/get-in o [:c :d])) ;; 1
Most of this library is supported in nbb, except the following:
:syms
.-x
notation. In nbb, you must use keywords.See the example of what is currently supported.
See the examples directory for small examples.
Also check out these projects built with nbb:
See API documentation.
See this gist on how to convert an nbb script or project to shadow-cljs.
Prequisites:
To build:
bb release
Run bb tasks
for more project-related tasks.
Download Details:
Author: borkdude
Download Link: Download The Source Code
Official Website: https://github.com/borkdude/nbb
License: EPL-1.0
#node #javascript
1636387040
Umeng Analytics&Push Flutter Plugins(umeng_analytics_push)
dependencies:
umeng_analytics_push: ^x.x.x #The latest version is shown above, plugin1.x supports flutter1.x, plugin2.x supports flutter2.x
# Or import through Git (choose one, Git version may be updated more timely)
dependencies:
umeng_analytics_push:
git:
url: https://github.com/zileyuan/umeng_analytics_push.git
package com.demo.umeng.app
import io.flutter.app.FlutterApplication
import io.github.zileyuan.umeng_analytics_push.UmengAnalyticsPushFlutterAndroid
class MyFlutterApplication: FlutterApplication() {
override fun onCreate() {
super.onCreate();
UmengAnalyticsPushFlutterAndroid.androidPreInit(this, "uemng_app_key", "channel", "uemng_message_secret")
}
}
package com.demo.umeng.app
import android.os.Handler
import android.os.Looper
import android.content.Intent
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
import io.github.zileyuan.umeng_analytics_push.UmengAnalyticsPushFlutterAndroid
import io.github.zileyuan.umeng_analytics_push.UmengAnalyticsPushPlugin
class MainActivity: FlutterActivity() {
var handler: Handler = Handler(Looper.myLooper())
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
}
override fun onNewIntent(intent: Intent) {
// Actively update and save the intent every time you go back to the front desk, and then you can get the latest intent
setIntent(intent);
super.onNewIntent(intent);
}
override fun onResume() {
super.onResume()
UmengAnalyticsPushFlutterAndroid.androidOnResume(this)
if (getIntent().getExtras() != null) {
var message = getIntent().getExtras().getString("message")
if (message != null && message != "") {
// To start the interface, wait for the engine to load, and send it to the interface with a delay of 5 seconds
handler.postDelayed(object : Runnable {
override fun run() {
UmengAnalyticsPushPlugin.eventSink.success(message)
}
}, 5000)
}
}
}
override fun onPause() {
super.onPause()
UmengAnalyticsPushFlutterAndroid.androidOnPause(this)
}
}
<application
android:name="com.demo.umeng.app.MyFlutterApplication">
</application>
Modify MyFlutterApplication
package com.demo.umeng.app
import io.flutter.app.FlutterApplication
import io.github.zileyuan.umeng_analytics_push.UmengAnalyticsPushFlutterAndroid
class MyFlutterApplication: FlutterApplication() {
override fun onCreate() {
super.onCreate();
UmengAnalyticsPushFlutterAndroid.androidInit(this, "uemng_app_key", "channel", "uemng_message_secret")
// Register Xiaomi Push (optional)
UmengAnalyticsPushFlutterAndroid.registerXiaomi(this, "xiaomi_app_id", "xiaomi_app_key")
// Register Huawei Push (optional, need add other infomation in AndroidManifest.xml)
UmengAnalyticsPushFlutterAndroid.registerHuawei(this)
// Register Oppo Push (optional)
UmengAnalyticsPushFlutterAndroid.registerOppo(this, "oppo_app_key", "oppo_app_secret")
// Register Vivo Push (optional, need add other infomation in AndroidManifest.xml)
UmengAnalyticsPushFlutterAndroid.registerVivo(this)
// Register Meizu Push (optional)
UmengAnalyticsPushFlutterAndroid.registerMeizu(this, "meizu_app_id", "meizu_app_key")
}
}
Modify the AndroidManifest.xml, fill in the real id or key
<application
android:name="com.demo.umeng.app.MyFlutterApplication">
<!-- Vivo push channel start (optional) -->
<meta-data
android:name="com.vivo.push.api_key"
android:value="vivo_api_key" />
<meta-data
android:name="com.vivo.push.app_id"
android:value="vivo_app_id" />
<!-- Vivo push channel end-->
<!-- Huawei push channel start (optional) -->
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="appid=huawei_app_id" />
<!-- Huawei push channel end-->
</application>
Use the following parameters to send, accept offline messages
"mipush": true
"mi_activity": "io.github.zileyuan.umeng_analytics_push.OfflineNotifyClickActivity"
If the App needs to use proguard for obfuscated packaging, please add the following obfuscated code
-dontwarn com.umeng.**
-dontwarn com.taobao.**
-dontwarn anet.channel.**
-dontwarn anetwork.channel.**
-dontwarn org.android.**
-dontwarn org.apache.thrift.**
-dontwarn com.xiaomi.**
-dontwarn com.huawei.**
-dontwarn com.meizu.**
-keepattributes *Annotation*
-keep class com.taobao.** {*;}
-keep class org.android.** {*;}
-keep class anet.channel.** {*;}
-keep class com.umeng.** {*;}
-keep class com.xiaomi.** {*;}
-keep class com.huawei.** {*;}
-keep class com.meizu.** {*;}
-keep class org.apache.thrift.** {*;}
-keep class com.alibaba.sdk.android.** {*;}
-keep class com.ut.** {*;}
-keep class com.ta.** {*;}
-keep public class **.R$* {
public static final int *;
}
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
GeneratedPluginRegistrant.register(with: self)
UmengAnalyticsPushFlutterIos.iosPreInit(launchOptions, appkey:"uemng_app_key", channel:"appstore");
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// If you need to handle Push clicks, use the following code
@available(iOS 10.0, *)
override func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
UmengAnalyticsPushFlutterIos.handleMessagePush(userInfo)
completionHandler()
}
}
#import "GeneratedPluginRegistrant.h"
#import <UMCommon/UMCommon.h>
#import <UMCommon/MobClick.h>
#import <UMPush/UMessage.h>
#import <UserNotifications/UserNotifications.h>
#import <umeng_analytics_push/UmengAnalyticsPushIos.h>
import 'package:umeng_analytics_push/umeng_analytics_push.dart';
UmengAnalyticsPush.initUmeng(false, true);
import 'package:umeng_analytics_push/umeng_analytics_push.dart';
import 'package:umeng_analytics_push/message_model.dart';
UmengAnalyticsPush.addPushMessageCallback((MessageModel message) {
print("UmengAnalyticsPush Message ======> $message");
});
import 'package:umeng_analytics_push/umeng_analytics_push.dart';
UmengAnalyticsPush.addAlias('1001', 'jobcode');
UmengAnalyticsPush.setAlias('1002', 'jobcode');
UmengAnalyticsPush.deleteAlias('1002', 'jobcode');
import 'package:umeng_analytics_push/umeng_analytics_push.dart';
UmengAnalyticsPush.addTags('manager');
UmengAnalyticsPush.deleteTags('manager');
import 'package:umeng_analytics_push/umeng_analytics_push.dart';
UmengAnalyticsPush.pageStart('memberPage');
UmengAnalyticsPush.pageEnd('memberPage');
import 'package:umeng_analytics_push/umeng_analytics_push.dart';
UmengAnalyticsPush.event('customEvent', '1000');
Run this command:
With Flutter:
$ flutter pub add umeng_analytics_push
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
umeng_analytics_push: ^2.1.3
Alternatively, your editor might support or flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:umeng_analytics_push/umeng_analytics_push.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
),
),
);
}
}
Download Details:
Author: zileyuan
Source Code: https://github.com/zileyuan/umeng_analytics_push
1625674200
In this video, we are going to implement Google Analytics to our Next JS application. Tracking page views of an application is very important.
Google analytics will allow us to track analytics information.
Frontend: https://github.com/amitavroy/video-reviews
API: https://github.com/amitavdevzone/video-review-api
App link: https://video-reviews.vercel.app
You can find me on:
Twitter: https://twitter.com/amitavroy7
Discord: https://discord.gg/Em4nuvQk
#next js #js #react js #react #next #google analytics
1625751960
In this video, I wanted to touch upon the functionality of adding Chapters inside a Course. The idea was to not think much and start the development and pick up things as they come.
There are places where I get stuck and trying to find answers to it up doing what every developer does - Google and get help. I hope this will help you understand the flow and also how developers debug while doing development.
App url: https://video-reviews.vercel.app
Github code links below:
Next JS App: https://github.com/amitavroy/video-reviews
Laravel API: https://github.com/amitavdevzone/video-review-api
You can find me on:
Twitter: https://twitter.com/amitavroy7
Discord: https://discord.gg/Em4nuvQk
#next js #api #react next js #next #frontend #development