I am currently working on a Gmail Contextual Gadget for a non-profit organization.
We followed the official Google tutorials on https://developers.google.com/gmail/contextual_gadgets with the goal of building a Hello World app.
We did the following:
Create an app on https://console.developers.google.com/
Activate Google Marketplace SDK
Activate GMail contextual gadget with appropriate Extractor and Gadget URLs.
Deploy the app for the Non-Profit organization users.
Send us emails containing "Hello World".
However, we are not able to make it work (it should print Hello World below the emails). We checked our servers hosting the XMs, and Google definitely hits our gadget_helloworld.xml file.
Hereby are the files content. Could someone please give a hand on this subject?
It is hard to find up to date documentation on this topic, as a lot of things changed with the Google API. I think it would be helpful for the community to give an open source working sample of code updated on last-2015.
Best,
Content of the Extractor - manifest_helloworld.xml
<?xml version="1.0" encoding="UTF-8"?>
<ApplicationManifest xmlns="http://schemas.google.com/ApplicationManifest/2009">
<script id="tinyhippos-injected" />
<Extension id="HelloWorldExtractor" type="contextExtractor">
<Name>Hello World Extractor</Name>
<Url>google.com:HelloWorld</Url>
<Triggers ref="HelloWorld" />
<Scope ref="emailBody" />
<Scope ref="emailSubject" />
<Container name="mail" />
</Extension>
<Extension id="HelloWorld" type="gadget">
<Name>HelloWorld Gadget</Name>
<Url>XXXX_MY_DOMAIN/gadget_files/gadget_helloworld.xml</Url>
<Container name="mail" />
<!-- Uncomment this to enable Caja. -->
<!-- Param name="caja" value="enabled"/> -->
</Extension>
<Scope id="emailBody">
<Url>tag:google.com,2010:auth/contextual/extractor/BODY</Url>
<Reason>Necessary for reason 1</Reason>
</Scope>
<Scope id="emailSubject">
<Url>tag:google.com,2010:auth/contextual/extractor/SUBJECT</Url>
<Reason>Necessary for reason 2</Reason>
</Scope>
</ApplicationManifest>
Content of the Gadget - gadget_helloworld.xml
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<script id="tinyhippos-injected" />
<ModulePrefs title="Hello World" description="Matches and echoes 'Hello World' string in emails" height="20" author="ACME" author_email="test#example.com" author_location="Bermuda">
<!-- Declare feature dependencies. -->
<!--
This one is not specific to Gmail contextual gadgets.
-->
<Require feature="dynamic-height" />
<!--
The next feature, Caja, is optional, and is supported for
use only within test domains. Uncomment the tag only for
non-production gadgets.
-->
<!-- <Require feature="caja"/> -->
<!--
The next feature, google.contentmatch, is required for all
Gmail contextual gadgets.
<Param> - specify one or more comma-separated extractor IDs in
a param named "extractors". This line is overridden by the extractor ID
in the manifest, but is still expected to be present.
-->
<Require feature="google.contentmatch">
<Param name="extractors">google.com:HelloWorld</Param>
</Require>
</ModulePrefs>
<!--
Define the content type and display location. The settings
"html" and "card" are required for all Gmail contextual gadgets.
-->
<Content type="html" view="card"><![CDATA[<p>Hello World</p>
<script type="text/javascript">
<!-- Fetch the array of content matches. -->
matches = google.contentmatch.getContentMatches();
var matchList = document.createElement('UL');
var listItem;
var extractedText;
<!-- Iterate through the array and display output for each match. -->
for (var match in matches) {
for (var key in matches[match]) {
listItem = document.createElement('LI');
extractedText = document.createTextNode(key + ": " + matches[match][key]);
listItem.appendChild(extractedText);
matchList.appendChild(listItem);
}
}
document.body.appendChild(matchList);
gadgets.window.adjustHeight(100);
</script>]]></Content>
</Module>
I had a similar issue of it not activating and the solution for me was to make the "Extractor param name" set to "hello" and and the "Extractor param value" set to ".*" -- According to the docs the important part is the value field:
If you really do want your gadget to be triggered by all possible
values in the extractor's default output, explicitly set the regular
expression as value=".*". This makes it clear that you have cast a
wide net by design.
Related
So I am building (a) webpage(s) using the SAP Hana Cloud Portal.
I have defined a template that looks roughly like this:
<mvc:View
controllerName="cpv2.templates.custom.Template"
height="100%"
xmlns:cpControls="sap.hana.uis.flp.control"
xmlns:l="sap.ui.layout"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns:u="sap.ui.unified"
xmlns="sap.m">
<Page showFooter="false" showHeader="false" enableScrolling="true">
<u:SplitContainer id="mySplitContainer" showSecondaryContent="false">
<u:secondaryContent>
<core:Fragment fragmentName="cpv2.templates.custom.SideNavigationPanel"
type="XML" id="idSideNav"/>
</u:secondaryContent>
<u:content>
<cpControls:Section alias="custom.shellHeader"></cpControls:Section>
<cpControls:Section alias="custom.header"></cpControls:Section>
<cpControls:Section alias="custom.content"></cpControls:Section>
<cpControls:Section alias="custom.footerbanner"></cpControls:Section>
<cpControls:Section alias="custom.footer"></cpControls:Section>
</u:content>
</u:SplitContainer>
</Page>
</mvc:View>
I then develop multiple SAPUI5 applications which I convert to SAP Portal Components. My app-widgets' views all have this basic format:
<mvc:View [namespaces, controller, etc.]>
<App>
<!-- most of them have VBox or HBox in their view -->
<Vbox>
<!-- some content here -->
</VBox>
</App>
</mvc:View>
I deploy these applications to the Cloud Portal.
finally I create a webpage, use the above template and fill the defined sections with these app-widgets.
Now for some reason the height of these app-widgets are all 0. Inspecting the page shows me they are there, but their height is rendered zero.
Is there a fix for this?
I am trying to develop one gmail gadget. I have prepared my gadget.xml file after reading all the required peoint mentioned in the google documents. But after that they ask to make a manifest file. But as far I have searched, now we don't need to prepare any manifest file. Now, we can prepare it through Google Apps Marketplace SDK. I have prepared a manifest here and saved it and enabled it from console.developers.google.com.
But after that also, I am not able to see my gadget in Gmail. Please any experienced developer help me in this problem. I trying to solve this problem from long time.
Here is my gadget.xml code:
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs author="Company Name" height="500" author_email="abc#example.com" author_location="India">
<Require feature="dynamic-height"/>
<Require feature="views" />
<Require feature="google.contentmatch">
<Param name="extractors">google.com:MessageIDExtractor</Param>
<Param name="extractors">google.com:SenderEmailExtractor</Param>
</Require>
</ModulePrefs>
<Content type="html" view="card">
<![CDATA[
<p> Pragmatic Odoo Gmail Integration</p>
<script>console.log('Hello from gadget.')</script>
]]>
</Content>
</Module>
Here is my Google Apps Marketplace SDK settings for gadget:
enter image description here
Pay attention to below hints:
Add an app to chrome web store and link it to your Google project, which you describe contextual gadget, with project ID.Here's a sample of web store manifest.json:
{
"manifest_version": 2,
"name": "Sample App",
"short_name": "Dev",
"version": "1.0.0",
"default_locale": "en",
"description": "Sample app",
"app" : {
"launch" : {
"web_url" : "http://yourcompany.com"
}
},
"icons": {
"128": "icons/128x128-icon.png",
"16": "icons/16x16-icon.png"
},
"container": ["DOMAIN_INSTALLABLE"],
"api_console_project_id": "your-project-id"
}
After publish this app, add it to test Google Domain. Since your gadget is in development stage so, don’t publish your app to Public. There are different "Visibility options" that you can choose.
To disable cache use nogadgetcache=1 (e.g. https://mail.google.com/?nogadgetcache=1)
Login with admin account which you want to test it, otherwise take more time to update manifest.
After Modify “Google Apps Marketplace SDK” click on “Test Installation Flow” to be sure there is no new permission.
I did these part and works for me:
Define google.com:MessageIDExtractor as first extension, however you don’t need that.
I recommend that select every scopes which you want to use in other
extensions here! I don’t know why put it seems the google just ask
these permission for my gadget
Define Param extractor in gadget.xml separately not with comma:
<Require feature="google.contentmatch">
<Param name="extractors">
google.com:MessageIDExtractor
</Param>
<Param name="extractors">
google.com:SenderEmailExtractor
</Param>
</Require>
I bounced against a very troubling issue when porting my app to iOS 10. I had been reinstalling it without problems on already present copies. Yet when I tried to delete it and install it from Xcode, the app quite silently crashed soon after executing:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
With the simple final log item:
[access] "<"private">"
If I conversly download it from the published copy on the AppStore and execute it thereafter from Xcode, the app does not crash any longer.
If I execute it on the iPad it even shows a message to enable localization that remains stuck on the window until I reboot the device.
The app also crashes on the simulator.
What might it be and how to know more, given I have no crash report returned?
App will crash if its accessing any private data like below with out defining them in plist(Getting permission from User)
Calendar Events
Location
If you are using any like above, then you need to add Privacy statements to info.plist file.
Below one is to access Calendar:
Privacy - Calendars Usage Description = "some text"
key = Privacy - Calendars Usage Description
value = "some Text"
iOS 10 has continued the privacy policy and has implemented new privacy rules. And we should remember to implement them in our next projects.
For your issue you need to add following line into info.plist
<!-- 📆 Calendars -->
<key>NSCalendarsUsageDescription</key>
<string><Your description goes here></string>
Below are the rest of the privacy rules :
<!-- 🖼 Photo Library -->
<key>NSPhotoLibraryUsageDescription</key>
<string><Your description goes here></string>
<!-- 📷 Camera -->
<key>NSCameraUsageDescription</key>
<string><Your description goes here></string>
<!-- 🎤 Microphone -->
<key>NSMicrophoneUsageDescription</key>
<string><Your description goes here></string>
<!-- 📍 Location -->
<key>NSLocationUsageDescription</key>
<string><Your description goes here></string>
<!-- 📍 Location When In Use -->
<key>NSLocationWhenInUseUsageDescription</key>
<string><Your description goes here></string>
<!-- 📍 Location Always -->
<key>NSLocationAlwaysUsageDescription</key>
<string><Your description goes here></string>
<!-- 📆 Calendars -->
<key>NSCalendarsUsageDescription</key>
<string><Your description goes here></string>
<!-- ⏰ Reminders -->
<key>NSRemindersUsageDescription</key>
<string><Your description goes here></string>
<!-- 🏊 Motion -->
<key>NSMotionUsageDescription</key>
<string><Your description goes here></string>
<!-- 💊 Health Update -->
<key>NSHealthUpdateUsageDescription</key>
<string><Your description goes here></string>
<!-- 💊 Health Share -->
<key>NSHealthShareUsageDescription</key>
<string><Your description goes here></string>
<!-- ᛒ🔵 Bluetooth Peripheral -->
<key>NSBluetoothPeripheralUsageDescription</key>
<string><Your description goes here></string>
<!-- 🎵 Media Library -->
<key>NSAppleMusicUsageDescription</key>
<string><Your description goes here></string>
Hope this helps. :)
I cannot manage to see a contextual gadget in Gmail after Test Install Flow in Google Apps Marketplace SDK.
These are the steps I took to create the project, logged as a domain administrator:
create Google Apps console project
create OAuth2 client
enable GAM SDK
configure the SDK page with COB extension:
Extractor Url: google.com:HelloWorld
GadgetUrl: URL of gadget spec
Extractor param name: Test
Extractor param value: .*
Scopes: Mail - Subject Line, Mail - Message Body
I didn't add any additional Oauth2 scopes than the userinfo.email and userinfo.profile that are already there, and the Universal Navigation link is just a file that redirects to Gmail( since I am trying a very simple variant of the project to see if I can get it to work ).
I press Test Install flow, I am asked to give permissions in a Oauth combined window, I am redirected to my Universal navigation link, then Gmail. The app appears in the Google Apps Admin control panel and seems to have installed successfully, it is ON for all domain users.
I tried Gmail with different domain users, cleared cache, logged out and back in to Gmail, I am probably missing a configuration somewhere.
This is the gadget spec:
<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="Title" description="Desc" author="" author_email="" author_location="" scrolling="false" height="20">
<Require feature="dynamic-height"/>
<Require feature="google.contentmatch">
<Param name="extractors">
google.com:HelloWorld
</Param>
</Require>
</ModulePrefs>
<Content type="html" view="card">
<![CDATA[
<script type="text/javascript">
<!-- Fetch the array of content matches. -->
matches = google.contentmatch.getContentMatches();
var matchList = document.createElement('UL');
var listItem;
var extractedText;
for (var match in matches) {
for (var key in matches[match]) {
listItem = document.createElement('LI');
extractedText = document.createTextNode(key + ": " + matches[match][key]);
listItem.appendChild(extractedText); matchList.appendChild(listItem); }
}
document.body.appendChild(matchList);
gadgets.window.adjustHeight(100);
</script>
]]>
</Content>
</Module>
Couple of suggestions -
Use the nocache option to force your Gmail UI to update. Use this link - https://mail.google.com/mail/u/0/?nogadgetcache=1#inbox
Try as a different account on the domain. I've seen some cases where the "developer/admin" inbox takes time to update
I'm playing with this Azure web role sample. It contains a class derived from RoleEntryPoint and a .aspx page that contains a button click handler.
I test it in Azure Emulator. I put the following code (taken from here)
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
in both role OnStart() and the button click handler. When role OnStart() is invoked it happens to run in WaIISHost.exe under MachineName\\MyLogin account and when button handler code is invoked it happens to run in w3wp.exe under MachineName\\NETWORK SERVICE account. That's surprising.
Why are these pieces of code from the same role project run inside different processes and under different accounts? Can I change that?
David is correct. In addition to that, you can turn off this behavior and run everything in the hostable web core (as it worked before SDK 1.4). You just need to comment out the "Sites" section in the services definition like in the example below:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="aExpense.Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="aExpense" vmsize="Medium">
<Sites>
<Site name="Web">
<Bindings>
<Binding name="HttpsIn" endpointName="HttpsIn" />
</Bindings>
</Site>
</Sites>
<ConfigurationSettings>
<Setting name="DiagnosticsConnectionString" />
<Setting name="DataConnectionString" />
<Setting name="allowInsecureRemoteEndpoints" />
</ConfigurationSettings>
With Windows Azure v1.3 and beyond, a Web Role takes advantage of the full IIS, rather than Hosted Web Core. IIS runs in a separate appdomain.
See this blog post from the Windows Azure team for the gory details.