1 | /*
|
2 | *
|
3 | * Licensed to the Apache Software Foundation (ASF) under one
|
4 | * or more contributor license agreements. See the NOTICE file
|
5 | * distributed with this work for additional information
|
6 | * regarding copyright ownership. The ASF licenses this file
|
7 | * to you under the Apache License, Version 2.0 (the
|
8 | * "License"); you may not use this file except in compliance
|
9 | * with the License. You may obtain a copy of the License at
|
10 | *
|
11 | * http://www.apache.org/licenses/LICENSE-2.0
|
12 | *
|
13 | * Unless required by applicable law or agreed to in writing,
|
14 | * software distributed under the License is distributed on an
|
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
16 | * KIND, either express or implied. See the License for the
|
17 | * specific language governing permissions and limitations
|
18 | * under the License.
|
19 | *
|
20 | */
|
21 |
|
22 | // The last resume event that was received that had the result of a plugin call.
|
23 | var lastResumeEvent = null;
|
24 |
|
25 | module.exports = {
|
26 | id: 'android',
|
27 | bootstrap: function() {
|
28 | var channel = require('cordova/channel'),
|
29 | cordova = require('cordova'),
|
30 | exec = require('cordova/exec'),
|
31 | modulemapper = require('cordova/modulemapper');
|
32 |
|
33 | // Get the shared secret needed to use the bridge.
|
34 | exec.init();
|
35 |
|
36 | // TODO: Extract this as a proper plugin.
|
37 | modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
|
38 |
|
39 | var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
|
40 |
|
41 | // Inject a listener for the backbutton on the document.
|
42 | var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
|
43 | backButtonChannel.onHasSubscribersChange = function() {
|
44 | // If we just attached the first handler or detached the last handler,
|
45 | // let native know we need to override the back button.
|
46 | exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
|
47 | };
|
48 |
|
49 | // Add hardware MENU and SEARCH button handlers
|
50 | cordova.addDocumentEventHandler('menubutton');
|
51 | cordova.addDocumentEventHandler('searchbutton');
|
52 |
|
53 | function bindButtonChannel(buttonName) {
|
54 | // generic button bind used for volumeup/volumedown buttons
|
55 | var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
|
56 | volumeButtonChannel.onHasSubscribersChange = function() {
|
57 | exec(null, null, APP_PLUGIN_NAME, "overrideButton", [buttonName, this.numHandlers == 1]);
|
58 | };
|
59 | }
|
60 | // Inject a listener for the volume buttons on the document.
|
61 | bindButtonChannel('volumeup');
|
62 | bindButtonChannel('volumedown');
|
63 |
|
64 | // The resume event is not "sticky", but it is possible that the event
|
65 | // will contain the result of a plugin call. We need to ensure that the
|
66 | // plugin result is delivered even after the event is fired (CB-10498)
|
67 | var cordovaAddEventListener = document.addEventListener;
|
68 |
|
69 | document.addEventListener = function(evt, handler, capture) {
|
70 | cordovaAddEventListener(evt, handler, capture);
|
71 |
|
72 | if (evt === 'resume' && lastResumeEvent) {
|
73 | handler(lastResumeEvent);
|
74 | }
|
75 | };
|
76 |
|
77 | // Let native code know we are all done on the JS side.
|
78 | // Native code will then un-hide the WebView.
|
79 | channel.onCordovaReady.subscribe(function() {
|
80 | exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
|
81 | exec(null, null, APP_PLUGIN_NAME, "show", []);
|
82 | });
|
83 | }
|
84 | };
|
85 |
|
86 | function onMessageFromNative(msg) {
|
87 | var cordova = require('cordova');
|
88 | var action = msg.action;
|
89 |
|
90 | switch (action)
|
91 | {
|
92 | // Button events
|
93 | case 'backbutton':
|
94 | case 'menubutton':
|
95 | case 'searchbutton':
|
96 | // App life cycle events
|
97 | case 'pause':
|
98 | // Volume events
|
99 | case 'volumedownbutton':
|
100 | case 'volumeupbutton':
|
101 | cordova.fireDocumentEvent(action);
|
102 | break;
|
103 | case 'resume':
|
104 | if(arguments.length > 1 && msg.pendingResult) {
|
105 | if(arguments.length === 2) {
|
106 | msg.pendingResult.result = arguments[1];
|
107 | } else {
|
108 | // The plugin returned a multipart message
|
109 | var res = [];
|
110 | for(var i = 1; i < arguments.length; i++) {
|
111 | res.push(arguments[i]);
|
112 | }
|
113 | msg.pendingResult.result = res;
|
114 | }
|
115 |
|
116 | // Save the plugin result so that it can be delivered to the js
|
117 | // even if they miss the initial firing of the event
|
118 | lastResumeEvent = msg;
|
119 | }
|
120 | cordova.fireDocumentEvent(action, msg);
|
121 | break;
|
122 | default:
|
123 | throw new Error('Unknown event action ' + action);
|
124 | }
|
125 | }
|