Code Monkey home page Code Monkey logo

Comments (52)

kynora avatar kynora commented on September 28, 2024 2

I solve this problem in GDScript by call resize to remove banner from view before show Reward or Interstitial. And after banner ad loaded check to show banner if either Interstitial or Reward not showing.

func _on_admob_ad_loaded():
   if interstitialShowing || rewardShowing:
      yield(get_tree().create_timer(5.0), "timeout")
      _on_admob_ad_loaded()
   else:
      showBanner()

from godot-admob.

rolandoislas avatar rolandoislas commented on September 28, 2024 1

UIKit view modifications should be made only on the main thread. NSThread's isMainThread can be used to determine if the current thread is the main. If the current thread is not the main, the modifications can be delegated to it via Dispatch dispatch_async or dispatch_sync_f, using dispatch_get_main_queue as the queue.

from godot-admob.

gvdb avatar gvdb commented on September 28, 2024 1

I was getting this problem too when returning from a RewardAd. I used the code from the examples provided in this repo and the crash seemed to be occurring on the label text update i.e. get_node("CanvasLayer/LblRewarded").set_text("Reward: " + currency + ", " + str(amount))

UIKit view modifications should be made only on the main thread. NSThread's isMainThread can be used to determine if the current thread is the main. If the current thread is not the main, the modifications can be delegated to it via Dispatch dispatch_async or dispatch_sync_f, using dispatch_get_main_queue as the queue.

I wasn't sure how to do any of that within Godot, but the closest thing I could find that seemed in the right ballpark was the call_deferred method. I wrapped the label text update code (above) in a call_deferred method and it seems to have fixed it, though I'm not entirely sure why.

Is there a better way to fix this within Godot? I don't understand how we would modify a Godot app using Apple's libraries (unless there are "hooks" to them within the Godot API?).

from godot-admob.

rolandoislas avatar rolandoislas commented on September 28, 2024 1

Something like this should work.

#include <Foundation/Foundation.h>
#include <dispatch/dispatch.h>
     
if (![NSThread isMainThread]) {
    dispatch_async(dispatch_get_main_queue(), ^{
        [interstitial loadRequest:request];
    });
}
else {
    [interstitial loadRequest:request];
}

from godot-admob.

gvdb avatar gvdb commented on September 28, 2024 1

@Shin-NiL Yep, it all works fine when I remove the banner ad. I tested exiting the video early, and allowing it play all the way through to get the reward. Both were fine.

from godot-admob.

wombatwingdings avatar wombatwingdings commented on September 28, 2024 1

This problem isn't just related to reward video. I get exactly the same crash (Multiple locks on web thread not allowed) on Interstitial when used with banner ads even if I switch banner ad off before displaying.

from godot-admob.

cagdasc avatar cagdasc commented on September 28, 2024 1

@Shin-NiL I try it with different threads but result is same. Maybe we need to try this scenario in native iOS app.

from godot-admob.

cagdasc avatar cagdasc commented on September 28, 2024 1

@Shin-NiL I taken this crash on production environment for my game and I had to remove interstitial ads. There is no difference between simulator or real devices.

from godot-admob.

kynora avatar kynora commented on September 28, 2024 1

@wombatwingdings, resize() call from GodotAdMob class. In code when banner resize it remove from view and load request again.
Here is my GDScript to show rewarded video:

func showRewardVideo():
   if admob:
      rewardShowing = true
      bannerShowing = false
      admob.resize()
      admob.showRewardedVideo()

from godot-admob.

kynora avatar kynora commented on September 28, 2024 1

I not yet try hideBanner(). Because hideBanner is only hidden image of ads but view still remaining. Other solution is implement all ads in ViewController of engine, but it is not following with engine workflow.

from godot-admob.

Dridia1 avatar Dridia1 commented on September 28, 2024 1

Doesn't seem like the issue has been solved. I've recreated the same issue with what @yamshing changed.

from godot-admob.

alfredocova avatar alfredocova commented on September 28, 2024 1

found the answer here

You have to comment this line, I did this in the AdmobIntersertitial.mm and in AdmobRewarded.mm then you have to recompile again for the iOS

Now you can close the add without getting the banner, I have it running on Xcode 11 and Godot 3.1.1

Perhaps it would be better to remove that line from the module and tell the devs to manually call a banner after an Interstitial instead of calling it automatically

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

Which versions of Google Mobile Ads SDK, Xcode and iOS are you using?

Unfortunately I don't have any Apple hardware, so I'm afraid I can't help much here. I hope somebody from the community can help us to maintain this module for iOS.

from godot-admob.

zettyfactory avatar zettyfactory commented on September 28, 2024

The same thing happens in the iOS simulator.
I saw the source for you, but I am not an iOS developer, so I can not tell you exactly what the problem is.
Compared to the admob sample code, it looks like no problem. But the error still occurs.

Version info

XCode : Version 10.1 (10B61)
simulator : iPhone X / iOS 12.1(16B91)
device : IPone6 / iOS 12.1
Admob SDK : 7.29, 7.35

0x1215f1e37 <+215>: leaq   0x1738026(%rip), %rdi     ; webLock + 12
0x1215f1e3e <+222>: callq  0x1229abad2               ; symbol stub for: WTF::Lock::lockSlow()
0x1215f1e43 <+227>: jmp    0x1215f1dd2               ; <+114>
0x1215f1e45 <+229>: callq  0x1215f30e0               ; CurrentThreadContext()
0x1215f1e4a <+234>: movq   %rax, %rcx
0x1215f1e4d <+237>: leaq   0x170d85c(%rip), %rdi     ; @"%s, %p: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now..."
0x1215f1e54 <+244>: leaq   0x13fb86f(%rip), %rsi     ; "void _WebThreadLock()"
0x1215f1e5b <+251>: xorl   %eax, %eax
0x1215f1e5d <+253>: movq   %rcx, %rdx
0x1215f1e60 <+256>: callq  0x1229aae2a               ; symbol stub for: NSLog
0x1215f1e65 <+261>: int3   
0x1215f1e66 <+262>: ud2    
0x1215f1e68 <+264>: callq  0x1215f30e0               ; CurrentThreadContext()
0x1215f1e6d <+269>: movq   %rax, %rcx
0x1215f1e70 <+272>: leaq   0x170d859(%rip), %rdi     ; @"%s, %p: Multiple locks on web thread not allowed! Please file a bug. Crashing now..."
0x1215f1e77 <+279>: leaq   0x13fb84c(%rip), %rsi     ; "void _WebThreadLock()"
0x1215f1e7e <+286>: xorl   %eax, %eax
0x1215f1e80 <+288>: movq   %rcx, %rdx
0x1215f1e83 <+291>: callq  0x1229aae2a               ; symbol stub for: NSLog
0x1215f1e88 <+296>: int3   

-> 0x1215f1e89 <+297>: ud2
0x1215f1e8b <+299>: nopl (%rax,%rax)


2018-11-14 10:11:06.834799+0900 hoonword[8709:112399] Main -> onReward Button click
Main -> onReward Button click
2018-11-14 10:11:06.835200+0900 hoonword[8709:112399] Calling showInterstitial
2018-11-14 10:11:06.836666+0900 hoonword[8709:112399] interstitialWillPresentScreen
******** screen size 1125, 2436
2018-11-14 10:11:07.288325+0900 hoonword[8709:112399] ERROR: Index p_index=0 out of size (s=0)
2018-11-14 10:11:07.288610+0900 hoonword[8709:112399] At: core/dvector.h:378:remove() - Index p_index=0 out of size (s=0)
ERROR: Index p_index=0 out of size (s=0)
At: core/dvector.h:378:remove() - Index p_index=0 out of size (s=0)
2018-11-14 10:11:09.525277+0900 hoonword[8709:112399] interstitialWillDismissScreen
******** screen size 1125, 2436
2018-11-14 10:11:10.063225+0900 hoonword[8709:113095] void _WebThreadLock(), 0x13e2ef040: Multiple locks on web thread not allowed! Please file a bug. Crashing now...
(lldb)

from godot-admob.

lukasmican avatar lukasmican commented on September 28, 2024

I have encountered similar problem, on Android it works fine, but on iOS after terminating Interstitial Ad the application exits. Unfortunately I am not an iOS developer too and I don't own Mac or any iOS device, so debugging iOS apps is pretty hard for me.

Version Info:
Godot 3.0.6
XCode 10.1 (10B61)
Admob SDK 7.36
iPhone 6 (iOS 11.4)

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

Yeah, we need help from any iOS developer from the community to figure out a solution :(
I'll update the README with this "Known Issue".

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

I wrapped the label text update code (above) in a call_deferred method and it seems to have fixed it, though I'm not entirely sure why.

Thank you @gvdb, this is interesting information. Can you guys (@zettyfactory , @vinchi9 , @rolandoislas) try this workaround? If it really works, we can try fix the code.

from godot-admob.

gvdb avatar gvdb commented on September 28, 2024

I wrapped the label text update code (above) in a call_deferred method and it seems to have fixed it, though I'm not entirely sure why.

Thank you @gvdb, this is interesting information. Can you guys (@zettyfactory , @vinchi9 , @rolandoislas) try this workaround? If it really works, we can try fix the code.

I tested it a little more this morning, and it still appears to be happening. Seems to be an intermittent issue. By luck I must've had a few instances where it didn't crash last night.

Will investigate more.

from godot-admob.

gvdb avatar gvdb commented on September 28, 2024

I can't find any way to fix this within the Godot application.

Do the changes suggested by @rolandoislas need to be implemented in the code of this repo itself?

I've attempted to make changes to AdmobRewarded.mm using these links as guidance, but my knowledge of the Apple code base is even worse than my knowledge of Godot. I've tried something like this:

if (Thread.isMainThread) { obj->call_deferred("_on_rewarded", [reward.type UTF8String], reward.amount.doubleValue); } else { dispatch_async(dispatch_get_main_queue(), ^{obj->call_deferred("_on_rewarded", [reward.type UTF8String], reward.amount.doubleValue);}); } }

But when I try to recompile the Godot engine source, I get errors I'm not sure how to fix, such as the undeclared identifier Thread. Trying to figure out how I instantiate a variable for the "current thread" so I can query whether it's the "main thread".

Will keep trying and update if I make any progress.

edit: By the way @Shin-NiL, I have an iPhone 6 running iOS 12 that I can test this on if needed.

from godot-admob.

rolandoislas avatar rolandoislas commented on September 28, 2024

I think the loading of the ad needs to be done on the main thread. For example, this line. I do not have hardware on hand to test at the moment, but I will in a week.

from godot-admob.

gvdb avatar gvdb commented on September 28, 2024

I think the loading of the ad needs to be done on the main thread. For example, this line. I do not have hardware on hand to test at the moment, but I will in a week.

If you can give an example of the code that I would need to add to that line to get it to run on the main thread, I'm happy to test that on my iPhone now.

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

I've applied the changes suggested by @rolandoislas on this branch https://github.com/Shin-NiL/godot-admob/tree/issue_53
Can any of you with access to Mac & iOS test it? I can't even know if it's compiling :(

from godot-admob.

gvdb avatar gvdb commented on September 28, 2024

Ok so I changed the loading code for banner ads and reward ads like so:

    if (![NSThread isMainThread]) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [bannerView loadRequest:request];
        });
    }
    else {
        [bannerView loadRequest:request];
    }
    if(!isReal) {
        if (![NSThread isMainThread]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [[GADRewardBasedVideoAd sharedInstance] loadRequest:[GADRequest request]
                                                       withAdUnitID:@"ca-app-pub-3940256099942544/1712485313"];
            });
        }
        else {
            [[GADRewardBasedVideoAd sharedInstance] loadRequest:[GADRequest request]
                                                   withAdUnitID:@"ca-app-pub-3940256099942544/1712485313"];
        }
    }
    else {
        if (![NSThread isMainThread]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [[GADRewardBasedVideoAd sharedInstance] loadRequest:[GADRequest request] withAdUnitID:rewardedId];
            });
        }
        else {
            [[GADRewardBasedVideoAd sharedInstance] loadRequest:[GADRequest request] withAdUnitID:rewardedId];
        }
    }

Then I followed the steps for installing the admob module (i.e. recompiling Godot source etc.). It compiled no problems. The game I've built has a banner ad and a reward ad in it, however the web lock crash still occurs when exiting the reward ad.

edit: I also tried having the "main thread" stuff on the Rewarded ad only, and had the banner loaded as it did previously, and the crash still occurs.

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

@gvdb Well, it's basically what I did. Can you tell me if you don't use banner the app still crash?
Maybe we need to instance the ads on the main thread, not only the loading.

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

@gvdb could you try my new commit https://github.com/Shin-NiL/godot-admob/tree/issue_53? I'm trying to putting everything on the main thread (similar to what happens in the Android code). The code is very ugly, but first we need to know if it works.

from godot-admob.

gvdb avatar gvdb commented on September 28, 2024

Got this when trying to compile:

[ 11%] Compiling ==> modules/admob/ios/src/godotAdmob.mm
modules/admob/ios/src/godotAdmob.mm:175:13: error: return type 'uintptr_t' (aka 'unsigned long') must match previous return type 'int' when block literal has unspecified explicit return type [2]
             return (uintptr_t)[banner getBannerWidth];
             ^
modules/admob/ios/src/godotAdmob.mm:170:9:{170:9-170:23}: error: no matching function for call to 'dispatch_async' [2]
         dispatch_async(dispatch_get_main_queue(), ^{
         ^~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/dispatch/queue.h:219:1: note: candidate function not viable: no known conversion from 'int (^)()' to 'dispatch_block_t _Nonnull' (aka 'void (^)()') for 2nd argument [2]
 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
 ^
modules/admob/ios/src/godotAdmob.mm:195:13: error: return type 'uintptr_t' (aka 'unsigned long') must match previous return type 'int' when block literal has unspecified explicit return type [2]
             return (uintptr_t)[banner getBannerHeight];
             ^
modules/admob/ios/src/godotAdmob.mm:190:9:{190:9-190:23}: error: no matching function for call to 'dispatch_async' [2]
         dispatch_async(dispatch_get_main_queue(), ^{
         ^~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/dispatch/queue.h:219:1: note: candidate function not viable: no known conversion from 'int (^)()' to 'dispatch_block_t _Nonnull' (aka 'void (^)()') for 2nd argument [2]
 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
 ^
4 errors generated.
scons: *** [modules/admob/ios/src/godotAdmob.iphone.opt.debug.arm64.o] Error 1
scons: building terminated because of errors.

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

getBannerWidth and height should not be in the main thread, reverted. Could you try again, please?

from godot-admob.

gvdb avatar gvdb commented on September 28, 2024

Ok, it compiles now, but the crash still occurs.

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

It's really sad :(

from godot-admob.

cagdasc avatar cagdasc commented on September 28, 2024

Are there any changes?

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

@cagdasc nope, seems like there is not so much iOS devs using Godot :(

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

@cagdasc unfortunately nothing we've tried has worked so far ;(

Edit: maybe this is a thing.

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

Please, can someone test this branch? I've changed how the module gets the rootController.

from godot-admob.

wombatwingdings avatar wombatwingdings commented on September 28, 2024

@Shin-NiL I have tested your branch. Rebuilt the export templates, but unfortunately, no difference:

image

Sorry, but thanks for trying!
EDIT: Oh, wait. I'm on wrong branch. Let me retest...
EDIT2: Built and re-testested. Definitely got rootController = [AppDelegate getViewController]; in source. Unfortunately, the above crash still stands :-(

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

Thank you very much for testing @wombatwingdings

I did more changes on that branch, could you, or another person following this topic, please make a new test?

from godot-admob.

wombatwingdings avatar wombatwingdings commented on September 28, 2024

@Shin-NiL , glad to be able to help in some small way.
I'm afraid new version crashes in the same place too.

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

Thanks again @wombatwingdings!
It's really weird, because a friend of mine have told me it worked fine but on simulator and using godot 2.1.5. Anyways, I'll merge these changes to master, as it seems to not broke anything.

from godot-admob.

wombatwingdings avatar wombatwingdings commented on September 28, 2024

@kynora, what class did you call resize() on to remove the banner?

from godot-admob.

kynora avatar kynora commented on September 28, 2024

@wombatwingdings , full GDScript:


extends Node
var isReal = true

var admob = null
var isTop = true


# bug with closing interstitial and reward crash with banner
var rewardLoaded = false
var intLoaded = false

var bannerShowing = false
var rewardShowing = false
var intShowing = false

var bannerId
var interstitialId
var rewardedId

func _ready():
   initAdMob()

func initAdMob():

   if Engine.has_singleton("GodotAdMob"):
      admob = Engine.get_singleton("GodotAdMob")
      admob.init(isReal, get_instance_id())
   loadBanner()
   loadInterstitial()
   loadRewardedVideo()
   
   get_tree().connect("screen_resized", self, "onResize")

func loadBanner():
   var bannerShowing = false
   if admob:
      admob.loadBanner(bannerId, isTop)
      

func loadInterstitial():
   intShowing = false
   intLoaded = false
   if admob:
      admob.loadInterstitial(interstitialId)
      
func loadRewardedVideo():
   rewardShowing = false
   rewardLoaded = false
   if admob:
      admob.loadRewardedVideo(rewardedId)

func showBanner():
   if bannerShowing:
      return
   if admob:
         bannerShowing = true
         admob.showBanner()
      
func showInterstitial():
   if admob:
      if intLoaded:
         intShowing = true
         bannerShowing = false
         admob.resize()
         admob.showInterstitial()

   
func showRewardVideo():
   if admob:
      rewardShowing = true
      bannerShowing = false
      admob.resize()
      admob.showRewardedVideo()


func _on_admob_network_error():
   print("Network Error")
   yield(get_tree().create_timer(20.0), "timeout")
   loadBanner()
   

func _on_admob_ad_loaded():
   print("Ad loaded success")
   if intShowing || rewardShowing:
      yield(get_tree().create_timer(5.0), "timeout")
      _on_admob_ad_loaded()
   else:
      showBanner()

func _on_interstitial_not_loaded():
   print("Error: Interstitial not loaded")
   yield(get_tree().create_timer(20.0), "timeout")
   loadInterstitial()

func _on_interstitial_loaded():
   print("Interstitial loaded")
   intLoaded = true
   

func _on_interstitial_close():
   print("Interstitial closed")
   loadInterstitial()


func _on_rewarded_video_ad_failed_to_load():
   yield(get_tree().create_timer(20.0), "timeout")
   loadRewardedVideo()

func _on_rewarded_video_ad_loaded():
   print("Rewarded loaded success")
   rewardLoaded = true
   
func _on_rewarded_video_ad_closed():
   print("Rewarded closed")
   loadRewardedVideo()
   

   
func _on_rewarded(currency, amount):
   print("Reward: " + currency + ", " + str(amount))

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

@kynora for the first time it makes sense. So the conflict seems to be with the banner on screen. Did you try only hideBanner() instead of resize()?

from godot-admob.

Shin-NiL avatar Shin-NiL commented on September 28, 2024

Could you guys please test the latest commit from our friend @yamshing? It should finally fix this issue.

from godot-admob.

yamshing avatar yamshing commented on September 28, 2024

@Dridia1 Could you test with delay bigger than 0 at
https://github.com/kloder-games/godot-admob/blob/master/admob/ios/src/AdmobRewarded.mm#L83
? If it does nothing tell me more about your environnement ( ios version etc... simulator or real device ?)

from godot-admob.

Dridia1 avatar Dridia1 commented on September 28, 2024

@yamshing I were using the interstitial ad, so I changed the following line instead:

[self performSelector:@selector(bannerEnable) withObject:nil afterDelay:0];

This works perfect, and I'm running iOS 12.4 on an iPhone X

from godot-admob.

yamshing avatar yamshing commented on September 28, 2024

@Dridia1 thanks for your test. I will change the delay and commit the change

from godot-admob.

canvasbushi avatar canvasbushi commented on September 28, 2024

you should also wrap your bannerEnable method with a

dispatch_async(dispatch_get_main_queue(), ^{
// enable banner
});

so the ui gets updated on the main thread.

from godot-admob.

yamshing avatar yamshing commented on September 28, 2024

@canvasbushi thank you for your suggestion I will test this

from godot-admob.

gumaciel avatar gumaciel commented on September 28, 2024

Someone can test?

I tested on #124 , and its working fine!

Ps: I tested on version 3.1.2, the version 3.2.1 i doesnt test yet

from godot-admob.

gumaciel avatar gumaciel commented on September 28, 2024

This issue is fixed on 3.1.2, if someone is still facing this issue, please comment here

from godot-admob.

pchasco avatar pchasco commented on September 28, 2024

On 2.1 I continue to get this error. In fact, I have stripped everything from the module except the bare minimum of code required by Google to implement a rewarded ad and still receive the error. The issue must be in the engine itself. I have also tried with both Google Ads Frameworks versions 7.41 and 7.60. Same result.

My clone

Edit:
I spoke too soon. Updating to the latest SDK, 7.60 seems to correct the issue. You must alter the link flags to link against the new dependencies required by the SDK. The provided frameworks are XCFramework packages, which are not directly supported by the -framework flag as far as I could tell. I had to add the ios-armv7_arm64 directories under each .xcframework to the link path. I don't know of a better way. If this is the best way, then the link flags in config.py will need to be configured per architecture to include the appropriate subdirectory under the .xcframework directories. This is something I can work on. I expect this will solve #135 also.

from godot-admob.

pchasco avatar pchasco commented on September 28, 2024

Godot 3 should now have this issue fixed, as a patch has been merged. The fix has also been picked into the 2.1.7 branch, though at this time it hasn't been officially released. I manually applied the fixes to my own Godot fork.

from godot-admob.

gumaciel avatar gumaciel commented on September 28, 2024

Hey @pchasco , yes, on Godot 3 this issue is fixed, i dont know if 2.1.X still happens.

2.1.X version is still in working by Godot contributors?

from godot-admob.

pchasco avatar pchasco commented on September 28, 2024

from godot-admob.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.