3766 stories
·
1 follower

Microsoft Universal Apps & Continuum: Why Did Microsoft Not Squeeze their Potential?

1 Share

Microsoft is one company that has hands on many, many things. To an extent, this has worked for them, but then, on some other fronts they have failed so woefully. The list of failed projects from Microsoft are endless, only rivaled by Google’s — on PC, mobile, and the list of failed startups under their belt

Its no longer news that Microsoft wants to dominate the mobile space just as they do on the PC/Desktop world, starting with Windows Phone 6.5, which was fairly good, then the horrible experience on the Windows Phone 7. Despite the annoying trend of no-forward-compatibility, things got better with the next iteration, Windows Phone 8. I used a few Windows Phone 8 devices, and was truly impressed by their performance, coupled with the very good camera experience.

With the coming of Windows 10, some of the attractive selling points Microsoft brought to the table were Universal Windows Apps and Continuum. These two ideas are brilliant but not fully realized; we’ll look at them briefly before highlighting what it could be missing.

The Universal Apps Conundrum

The idea behind Universal Apps was to give users a similar experience across all their devices, be it on a PC, tablet or on a phone. It was to offer one app package and one app store to go across the board. Brilliant! Right…? This was also extended to bringing in apps from other platforms. Last year, Microsoft unveiled porting tools for converting apps from other ecosystems to be supported on the Windows 10 platform. Below are the four porting tools that were to be made available to developers:

  • Project Westminster – to port Web apps
  • Project Centennial – to port Classic Win32 apps
  • Project Islandwood – to port iOS apps
  • Project Astoria – to emulate Android apps.

This news brought joy to almost everyone that heard it. Personally, I finally found a reason to invest in a Windows phone. So far so good, but we haven’t seen or heard of these new ideas come into full fruition. For the Universal Apps project, developers are gradually porting their apps to support the cause, but there is still a very long way to go.

I was heavily disappointed after hearing news that Microsoft has discontinued Project Astoria. It appears, somewhere along the line, Android app support was disabled in the Insider builds of Windows 10 mobile… Sad really. We’ve heard some encouraging news and developments with Project Islandwood (iOS app porting) but so far, nothing serious has come out of it.

The case of Continuum

This is the part that thrilled me the most. As a feature, Continuum is cool, you can imagine having a phone and PC all in one package. Turning your phone into a big-screen projector, then using your apps on the big screen. As a further convenience, you can also connect your mouse and keyboard.

After briefly trying this out in a real life setting, you truly understand its usefulness despite the fact that some apps are not supported, and some other apps didn’t align properly on the screen. We can forgive these maladies by saying the feature is still in its early stages, but it’s clear to see that this concept can be a goldmine if tapped right.

In Conclusion

In today’s highly competitive world of mobile technology, you wouldn’t need a soothsayer to tell you that there is a lot of potential in Microsoft’s new ideas. The issue here is that they might end up shooting themselves in the foot with lethargy. This Universal Apps concept, if  applied with sense, can gain Microsoft a lot in terms of usage and sales.

lumiaBut so far, much of that perfect image has been lost, and the aforementioned lethargy undermined their great plans. Imagine having a phone that would support both Android and iOS apps… As if that wasn’t enough, the same device would also run same apps on your PC and tablet. There are many marketing lines to be gleaned from here, but then, this has not been realized after a year since its announcement.

Microsoft should put more efforts in enticing and sensitizing developers to get on this new plan. More should also be done in marketing, especially in developing countries. I say this because that’s where the larger number of untapped population can be found, and technologies like Continuum can greatly benefit the third world by providing affordable all-purpose devices.

The focus Microsoft had with the Lumia 950 has been in developed markets, which I think is wrong. People there, for the most part, already own smartphones and PC’s, therefore selling them a phone that can acts as a PC might not be the kind of feature they need, whereas the third world would be enamored with the concept.

Developing countries are the ideal places for Microsoft to be singing the phone-PC song. That’s a place where Continuum supported phones should be pushed, but not in the frame of the “expensive” Lumia 950/950XL. I was gutted when discovering that the Lumia 650 didn’t have support for Continuum — that would have been the ideal device for this region!

Best case scenario is Microsoft finally making a low end or mid-range device, priced not more than $200, with Continuum. We have heard that MediaTek chips would soon be supported by Windows 10 Mobile, so this should further reduce costs. Throw in support for Continuum followed by a good battery life, then market it aggressively in developing markets. I can assure you, that would be a hit!

Why do you think Microsoft didn’t squeeze the potential of these features? Would you like to see them become mainstream in your region? Let us know below!





March 12, 2016 at 03:25PM
Read the whole story
Share this story
Delete

新华社记者公开信斥责中国网管部门践踏言论自由

1 Share
华盛顿—

中国一名新闻工作者发表公开信,批评网管部门违反宪法,践踏公民基本权利。虽然网管已将这一公开信删除,但该信还是流到了海外。评论人士说:这种现象表明中共党内两方在“对打”。

网管部门粗暴统治,网民前所未有恐慌

在新华社从事英文编译工作的周方,近日在其新浪博客上实名发表公开信说,中国网络主管部门严重违反中国宪法和有关法律,粗暴践踏公民基本权利、侵犯公民言论自由权。这是继财新网公开发表文章对中国网络监管部门删除其一篇报道表示异议后,又有中国体制内媒体人对当局打压言论和新闻自由表达不满。

周方1989年社科院新闻系毕业后一直在新华社工作,他在(其博客)这封写给中国全国人大常委会、最高人民法院、最高人民检察院和中国共产党纪律检查委员会的举报信中指责“媒体主管部门特别是网络媒体管理部门长期存在玩忽职守、滥用公权、侵犯人权等严重的违宪违法行为。”

他写道,“有关部门的违法行为已经造成了极大的思想混乱和舆论误导,严重威胁了国家的安全和稳定,极大地阻碍了改革开放事业的深入,严重损害了执政党、政府和国家形象,损害了中华民族的长远利益。”

公开信还指责网管部门无视“依法治国”原则扮演舆论法官角色,常常在未经任何司法程序、缺乏足够法律证据的情况下关闭个人博客和微博,以长官意志取代法律,在公安、央视等政府部门和媒体配合下,迫使当事人屈服并上央视认罪。

信中说,“在网管部门的粗暴统治下,网络舆论受到极大的压制,人民群众的言论自由收到了极其严重的侵犯。一时间,我国广大人民特别是网民陷入了一种前所未有的恐怖之中。许多人对中央产生了怀疑,担心文革重来。更为严重的是,网管部门公权私用,在网民中大搞‘顺我者昌,逆我者亡’,以关闭博客和微博等方式非法剥夺公民言论自由权。”

这封公开信目前已被新浪微博删除,但已被海外媒体广泛转载。从谷歌搜索的网页快照可以看到公开信的发布时间是2016年3月7日。在此之前,周方还于2月26日发表了一篇批评“围攻任志强”的博客。那篇博客也被删除。

设在美国的明镜集团总裁何频认为,周方的这封信代表了很多网民的看法。他说:“中国出了一个莫名其妙的网络办公室,居然任意地把人家的微博关掉,可以随意地关闭一些网站,甚至把一些在网络上发言的网民下令抓起来。这到底是一个什么样的部门,谁赋予这个部门这么大的权力?”

公开信剑有所指

周方的公开信还把矛头对准北京市,称“北京市曾经有一段时间大肆宣传有极少数人编造的所谓‘北京精神’,对抗宣传中央依法治国精神以及‘社会主义核心价值观’。”作者要求全面调查“围攻任志强”事件,追究网络办、团中央网络部门、千龙网等有关部门负责人的刑事责任。

2月末,以敢言著称的中国网络名人、房地产大亨任志强因发微博对中共总书记习近平提出的“官媒姓党”的说法提出质疑而遭到官媒的口诛笔伐,他的新浪和腾讯微博帐号也被关闭,还禁止以“换马甲”的方式改头换面再次注册。

当时,北京市委宣传部主管的千龙网刊登一篇了措辞激烈的文章抨击任志强,标题是《谁给了任志强反党的底气》,把矛头指向其背后的人。文章说,“一个连党章都无视的党员,公然反党的底气何来?一个半夜三更给领导打电话的任志强,究竟谁给了他跳出来推墙的‘勇气’?”

共青团中央机关报中国青年报旗下的中国青年网也发表了王德华的署名评论文章,抨击任志强反驳习近平的媒体姓党的言论是搞党民对立、其用心险恶。

任志强事件后,中国国家网信办还以“违法违规”为由,关闭了包括演员孙海英在内的一批网络大V的微博帐号。

背后有权斗大戏?

近代历史学家章立凡2月29日在VOA卫视《时事大家谈》节目中曾提出,任志强事件背后或许有权力斗争的影子。他说:“这次炮轰任志强最为猛烈的一个是包括网信办在内的中共宣传系统,还有一个是北京市。刚好2016年中纪委要进驻、派巡视组的就是这两个系统。我们也看到一个现象就是现在网络上一些炮轰任志强的文章就是要抓任志强的后台。任志强在他的自传《野心优雅》里提到他和王岐山的关系。”

就在任志强事件闹得沸沸扬扬之际,中共中央纪委网站3月1日发表了一篇《千人之诺诺,不如一士之谔谔》的文章,立即受到海内外舆论广泛关注。文章引述习近平在参加河北省委常委班子“专题民主生活会”时的讲话,“小问题没人提醒,大问题无人批评,以致酿成大错,正所谓‘千人之诺诺,不如一士之谔谔’啊!”

有报道称,在这篇文章之后,原本打算要惩处任志强的北京市西城区委暂停了有关媒体姓党的讨论和处理工作。据北京知识界和微信圈流传的消息,“北京市西城区委讨论给任志强处分问题,当天下午被叫停”。

不过,总部在美国的博讯新闻3月9日援引北京消息人士的话发布“独家”消息称,是习近平亲自叫停了对任志强的“大批判运动”,与中纪委王岐山无关。文章说,是中共中央办公厅发文给北京市委和中宣部,理由是“避免干扰全国两会举行”。

何频:中宣部与中纪委对打

但明镜集团的何频不认同这种说法。“因为习近平有没有叫停,我们没有任何证据。但是说中纪委叫停,我们是有明确的证据的,就是中纪委发表了一篇文章,强烈暗示了不能再搞个人性的批斗。”他说。

何频认为,从财新传媒旗下的财新网公开叫板国家网信办,到新华社记者周方发公开信将矛头指向网络监管部门和北京市委,其背后两大系统斗争的意味浓重。财新传媒由中国最有声望的媒体人之一胡舒立创办。坊间广泛传言,胡舒立与中纪委书记王岐山关系密切。

“胡舒立就是王岐山的延伸嘛,”何频说,“所以从这个意义上也就印证了中宣部有能力收拾胡舒立,这是一种对打。你有权力管我,我也可以反制你。”何频说。





March 12, 2016 at 03:25PM
Read the whole story
Share this story
Delete

RIP Google PageRank score: A retrospective on how it ruined the web

1 Share
google-pagerank-green-1920

PageRank — the secret sauce that Google used to become the giant of the search world — is no more. No more for the public, that is. Google’s numeric rating of how important it considers pages to be will soon no longer be accessible to the public.

Good riddance.

Ever gotten a crappy email asking for links? Blame PageRank.

Ever had garbage comments with link drops? Blame PageRank.

Ever had to ferret out the how and why you should make use of the nofollow attribute on links? Blame PageRank.

More appropriately, blame Google for ever making the PageRank score visible. When Google first started, PageRank was something it talked about as part of its research paperspress releases and technology pages to promote itself as a smarter search engine than well-established and bigger rivals at the time — players like Yahoo, AltaVista and Lycos, to name a few.

When Google unleashed PageRank scores

Where it went wrong for the web was in 2000, when Google released the first version of its Google Toolbar for Internet Explorer. The toolbar made it easy to search Google directly from within IE. It also gave those who enabled the PageRank meter to see the PageRank score of any page they were viewing:

Google PageRank Meter

The screenshot above is from a later version of the Google Toolbar, one that eventually came out for Firefox. It shows how the PageRank meter looked. The more green in the bar, the more important Google deemed your page to be for ranking purposes. If you hovered over the meter, you got a score from 0 to 10:

PageRank Meter scores

Most people who used the Google Toolbar probably never went through the effort of enabling the PageRank meter, which Google offered as an incentive to web surfers, a way for them to understand the quality of pages encountered when browsing (and a way for Google to understand what people were viewing beyond Google itself). But one group was very inclined to make the effort: SEOs.

Wanna buy a PageRank boost?

For those doing search engine optimization, the toolbar was an amazing present, a numeric rating of how important Google considered any of their pages to be. It was also a terrible trap for many SEOs and a disaster for the web as a whole.

PageRank always was and remains only one part of the Google search algorithm, the system that determines how to rank pages. There are many other ranking factors that are also considered. A high PageRank score did NOT mean that a page would rank well for any topic. Pages with lower scores could beat pages with higher scores if they had other factors in their favor.

If you want even more background about this, see my primer from a few years ago: What Is Google PageRank? A Guide For Searchers & Webmasters. The short story is that by giving out a PageRank score, many SEOs obsessed on that one metric. In response, a market emerged to serve them.

Google had positioned links as votes cast by the “democratic nature of the web.” Link networks were the Super PACs of this election, where money could influence those votes.

You want better PageRank? Then you want links, and so the link-selling economy emerged. Networks developed so that people could buy links and improve their PageRank scores, in turn potentially improving their ability to rank on Google for different terms. Google had positioned links as votes cast by the “democratic nature of the web.” Link networks were the Super PACs of this election, where money could influence those votes.

Google wasn’t happy with the Pandora’s Box it had opened. It began to fight back, with its most famous action against a network known as SearchKing, penalizing the site and some of those in the network with PageRank score reductions or actual removal from Google. SearchKing sued Google. Google won, a judge ruling that its search results were entitled to First Amendment protection as opinions.

That didn’t stop link selling. The quest for boosting PageRank scores quickly, rather than earning them naturally, continued for many. Link networks went underground or at least claimed Google couldn’t find them, until it did. No matter. As one closed, another came up in its place.

And then, the link spam

Meanwhile, the link spam began. People chasing higher PageRank scores began dropping links wherever they could, including into blog posts and forums. Eventually, it became such an issue that demands were raised that Google itself should do something about it. Google did in 2005, getting behind the nofollow tag, a way to prevent links from passing along PageRank credit.

If you want to know more about nofollow, see our What Is The Nofollow Tag; When & How To Use It page. The short story here is that nofollow certainly didn’t end link spam. It did, however, give enough of an impression that Google tried to fight it in some quarters that Google was no longer held so accountable for it.

The slow death of PageRank score

Ironically, the Google Toolbar that launched PageRank hysteria in 2000 is a fading memory. After a decade of growth, it suffered when Google launched its own Chrome browser with search from the address bar built-in. That left little reason to get the Google Toolbar, not that you could — Google never released a version for Chrome.

PageRank in the toolbar took other blows. Firefox support was dropped in 2011. Google took 10 months in 2013 to finally update the PageRank scores it was feeding into the toolbar for IE users. To our knowledge, it never updated the scores after that.

Meanwhile, PageRank scores reported through Google Search Console were dropped in 2009. The Google Directory, a hierarchical guide to the web based on the Open Directory, was closed in 2010, taking the PageRank scores it displayed with it.

PageRank as a visible score has been dying a slow death since around 2010, I’d say. Pulling it from the Google Toolbar makes it official, puts the final nail in the visible PageRank score coffin. The few actually viewing it within Internet Explorer, itself a depreciated browser, aren’t many. The real impact in dropping it from the toolbar means that third parties can no longer find ways to pull those scores automatically.

The post-PageRank score world

PageRank, Google’s original secret sauce, finally goes back to being secret. Only Google will know the scores, which it will continue to use mixed in with the many other factors that make up its ranking algorithm.

The absence of PageRank scores may cause some to seek alternatives, estimates from third parties about how authoritative pages might be. These remain, of course, just guesses. Only Google itself knows the actual PageRank score for a page — and as can’t be said enough, the score alone isn’t the only thing that determines if a page ranks well.

In other words, don’t fixate on scores, either Google’s scores, for the remaining few weeks they’ll be around, or third-party scores. For some, they can be a useful way to focus. But for too many, they can become an obsession that pulls away from other types of SEO work that can be done.

Finally, with PageRank scores going away, we all can enjoy a peaceful web where no one’s dropping links in comments, emailing pitches to buy links or causing publishers to fear they haven’t applied nofollow properly in sponsored content to avoid a possible Google penalty. No PageRank scores, no pressure about links!

Heh. Of course, none of that is going away. PageRank scores launched the link economy, but that economy long left the actual scores behind. It may make it harder for some to value the links they want to buy and sell, but links will continue to be brokered as long as people know that Google depends so much on them.



About The Author

(Some images used under license from Shutterstock.com.)





March 12, 2016 at 02:57PM
Read the whole story
Share this story
Delete

DeepMind founder Demis Hassabis on how AI will shape the future

1 Share
"Go has always been a holy grail for AI research."

Sam Byford: So for someone who doesn’t know a lot about AI or Go, how would you characterize the cultural resonance of what happened yesterday?

Demis Hassabis: There are several things I’d say about that. Go has always been the pinnacle of perfect information games. It’s way more complicated than chess in terms of possibility, so it’s always been a bit of a holy grail or grand challenge for AI research, especially since Deep Blue. And you know, we hadn’t got that far with it, even though there’d been a lot of efforts. Monte Carlo tree search was a big innovation ten years ago, but I think what we’ve done with AlphaGo is introduce with the neural networks this aspect of intuition, if you want to call it that, and that’s really the thing that separates out top Go players: their intuition. I was quite surprised that even on the live commentary Michael Redmond was having difficulty counting out the game, and he’s a 9-dan pro! And that just shows you how hard it is to write a valuation function for Go.

Were you surprised by any of the specific moves that you saw AlphaGo play?

Yeah. We were pretty shocked — and I think Lee Se-dol was too, from his facial expression — by the one where AlphaGo waded into the left deep into Lee’s territory. I think that was quite an unexpected move.

Because of the aggression?

Well, the aggression and the audacity! Also, it played Lee Se-dol at his own game. He’s famed for creative fighting and that’s what he delivered, and we were sort of expecting something like that. The beginning of the game he just started fights across the whole board with nothing really settled. And traditionally Go programs are very poor at that kind of game. They’re not bad at local calculations but they’re quite poor when you need whole board vision.

Read more: Why Google's Go win is such a big deal

A big reason for holding these matches in the first place was to evaluate AlphaGo’s capabilities, win or lose. What did you learn from last night?

Well, I guess we learned that we’re further along the line than — well, not than we expected, but as far as we’d hoped, let’s say. We were telling people that we thought the match was 50-50. I think that’s still probably right; anything could still happen from here and I know Lee’s going to come back with a different strategy today. So I think it’s going to be really interesting to find out.

Just talking about the significance for AI, to finish your first question, the other big thing you’ve heard me talk about is the difference between this and Deep Blue. So Deep Blue is a hand-crafted program where the programmers distilled the information from chess grandmasters into specific rules and heuristics, whereas we’ve imbued AlphaGo with the ability to learn and then it’s learnt it through practice and study, which is much more human-like.

If the series continues this way with AlphaGo winning, what’s next — is there potential for another AI-vs-game showdown in the future?

I think for perfect information games, Go is the pinnacle. Certainly there are still other top Go players to play. There are other games — no-limit poker is very difficult, multiplayer has its challenges because it’s an imperfect information game. And then there are obviously all sorts of video games that humans play way better than computers, like StarCraft is another big game in Korea as well. Strategy games require a high level of strategic capability in an imperfect information world — "partially observed," it’s called. The thing about Go is obviously you can see everything on the board, so that makes it slightly easier for computers.

Is beating StarCraft something that you would personally be interested in?

Maybe. We’re only interested in things to the extent that they are on the main track of our research program. So the aim of DeepMind is not just to beat games, fun and exciting though that is. And personally you know, I love games, I used to write computer games. But it’s to the extent that they’re useful as a testbed, a platform for trying to write our algorithmic ideas and testing out how far they scale and how well they do and it’s just a very efficient way of doing that. Ultimately we want to apply this to big real-world problems.

I grew up in the UK in the late ‘90s and would see your name in PC magazines, associated with very ambitious games. And when I first started hearing about DeepMind and saw your name there I thought, "That kind of fits." Can you draw a line from your previous career in the games industry to what you do now?

Yeah, so something like DeepMind was always my ultimate goal. I’d been planning it for more than 20 years, in a way. If you view all the things I’ve done through a prism of eventually starting an AI effort, then it kind of makes sense what I chose to do. If you’re familiar with my stuff at Bullfrog and so on, you’ll know that AI was a core part of everything I wrote and was involved with, and obviously Peter Molyneux’s games are all AI games as well. Working on Theme Park when I was 16 or 17 years old was quite a seminal moment for me in terms of realizing how powerful AI could be if we really tried to extend it. We sold millions of copies, and so many people enjoyed playing that game, and it was because of the AI that adapted to the way you played. We took that forward and I tried to extend that for the rest of my games career, and then I switched out of that back to academia and neuroscience because I felt around the mid-2000s that we’d gone as far as we could trying to sneak in AI research through the back door while you’re actually supposed to be making a game. And that’s hard to do, because publishers just want the game, right?

Was it just that games of the era were the most obvious application of AI?

Yeah, I think so, and I actually think we were doing unbelievably cutting-edge AI. I would say at that stage academia was on hold in the 90s, and all these new techniques hadn’t really been popularized or scaled yet — neural networking, deep learning, reinforcement learning. So actually the best AI was going on in games. It wasn’t this kind of learning AI we work on now, it was more finite-state machines, but they were pretty complex and they did adapt. Games like Black & White had reinforcement learning — I think it’s still the most complex example of that in a game. But then around 2004-5 it was clear that the games industry was going a different way from the '90s when it was really fun and creative and you could just think up any idea and build it. It became more about graphics and franchises and FIFA games and this kind of thing, so it wasn’t that interesting any more — I’d done everything I could in games and it was time to gather different information ready for the launch of DeepMind. And that was neuroscience; I wanted to get inspiration from how the brain solves problems, so what better way than doing a neuroscience PhD? ?

This may be fruit so low-hanging as to already be on the ground, but if you were to take AI advances and apply them to games today?

Oh yeah, I think it’d be amazing, actually. I was contacted recently by someone from EA and... [wistfully] we should do that. It’s just that there’s so many things to do! [laughs] It really is pretty general, using these techniques, and I would love to do that. But it’s just having the bandwidth to do it, and we’re concentrating on the moment on things like healthcare and recommendation systems, these kinds of things. But probably at some point we’ll do that, because it’d close the loop for me. And I think it would be a huge market, actually, having smart adaptable AI opponents, and I think games developers would love it instead of having to build a new AI each time for every game, maybe they could just train an AI on their game.

I just imagine you playing video games at home, getting so much more frustrated by non-player characters than I might.

Sure [laughs] Yes, that always used to frustrate me incredibly about massively multiplayer games and things like that. I never really got into that because the non-player characters were just so dumb. They didn’t have any memory, they didn’t change, they didn’t have any context. I think you could go to a whole other level of games if you had this learning AI.

The main future uses of AI that you’ve brought up this week have been healthcare, smartphone assistants, and robotics. Let’s unpack some of those. To bring up healthcare, IBM with Watson has done some things with cancer diagnosis for example — what can DeepMind bring to the table?

Well, it’s early days in that. We announced a partnership with the NHS a couple of weeks ago but that was really just to start building a platform that machine learning can be used in. I think Watson’s very different than what we do, from what I understand of it — it’s more like an expert system, so it’s a very different style of AI. I think the sort of things you’ll see this kind of AI do is medical diagnosis of images and then maybe longitudinal tracking of vital signs or quantified self over time, and helping people have healthier lifestyles. I think that’ll be quite suitable for reinforcement learning.

With the NHS partnership, you’ve announced an app which doesn’t seem to use much in the way of AI or machine learning. What’s the thought behind that? Why is the NHS using this rather than software from anybody else?

Well, NHS software as I understand it is pretty terrible, so I think the first step is trying to bring that into the 21st century. They’re not mobile, they’re not all the things we take for granted as consumers today. And it’s very frustrating, I think, for doctors and clinicians and nurses and it slows them down. So I think the first stage is to help them with more useful tools, like visualizations and basic stats. We thought we’ll just build that, we’ll see where we are, and then more sophisticated machine learning techniques could then come into play.

How easy a sell is all of this? Obviously funding for healthcare in the UK can be a contentious topic.

Yeah, uh, well, we’re just doing it all for free [laughs] which makes it an easier sell! And this is very different from most software companies. It’s mostly big multinational corporations that are doing this software so they don’t really pay attention to the users, whereas we’re designing it more in a startup sort of way where you really listen to the feedback from your users and you’re kind of co-designing it with them.

So let’s move onto smartphone assistants. I saw you put up a slide from Her in your presentation on the opening day — is that really the endgame here?

No, I mean Her is just an easy popular mainstream view of what that sort of thing is. I just think we would like these smartphone assistant things to actually be smart and contextual and have a deeper understanding of what you’re trying to do. At the moment most of these systems are extremely brittle — once you go off the templates that have been pre-programmed then they’re pretty useless. So it’s about making that actually adaptable and flexible and more robust.

What’s the breakthrough that’s needed to improve these? Why couldn’t we work on it tomorrow?

Well, we can — I just think you need a different approach. Again, it’s this dichotomy between pre-programmed and learnt. At the moment pretty much all smartphone assistants are special-cased and pre-programmed and that means they’re brittle because they can only do the things they were pre-programmed for. And the real world’s very messy and complicated and users do all sorts of unpredictable things that you can’t know ahead of time. Our belief at DeepMind, certainly this was the founding principle, is that the only way to do intelligence is to do learning from the ground up and be general.

AlphaGo got off the ground by being taught a lot of game patterns — how is that applicable to smartphones where the input is so much more varied?

Yeah, so there’s tons of data on that, you could learn from that. Actually, the AlphaGo algorithm, this is something we’re going to try in the next few months — we think we could get rid of the supervised learning starting point and just do it completely from self-play, literally starting from nothing. It’d take longer, because the trial and error when you’re playing randomly would take longer to train, maybe a few months. But we think it’s possible to ground it all the way to pure learning.

Is that possible because of where the algorithm has reached now?

No, no, we could have done that before. It wouldn’t have made the program stronger, it just would have been pure learning. so there would’ve been no supervised part. We think this algorithm can work without any supervision. The Atari games that we did last year, playing from the pixels — that didn’t bootstrap from any human knowledge, that started literally from doing random things on screen.

Is it easier for that because the fail states are more obvious, and so on?

It’s easier for that because the scores are more regular. In Go, you really only get one score, whether you’ve won or lost at the end of the game. It’s called the credit assignment problem; the problem is you’ve made a hundred actions or moves in Go, and you don’t know exactly which ones were responsible for winning or losing, so the signal’s quite weak. Whereas in most Atari games most of the things you’re doing give you some score, so you’ve got more breadcrumbs to follow.

Could you give a timeframe for when some of these things might start making a noticeable difference to the phones that people use?

I think in the next two to three years you’ll start seeing it. I mean, it’ll be quite subtle to begin with, certain aspects will just work better. Maybe looking four to five, five-plus years away you’ll start seeing a big step change in capabilities.

Of all the future possibilities you’ve identified, this is the one that’s most obviously connected to Google as a whole.

Yep.

Have you been given any indication as to how all of this is expected to fit into Google’s product roadmap or business model in general?

No, we have a pretty free rein over what we want to do to optimize the research progress. That’s our mission, and that’s why we joined Google, so that we could turbocharge that. And that’s happened over the last couple of years. Of course, we actually work on a lot of internal Google product things, but they’re all quite early stage, so they’re not ready to be talked about. Certainly a smartphone assistant is something I think is very core — I think Sundar [Pichai] has talked a lot about that as very core to Google’s future.

Google's support was "very important" to AlphaGo

Google has other initiatives like Google Brain, and it’s rolled out machine learning features like Google Photos and in search and a whole bunch of user-facing things.

Everywhere.

Do you find yourselves interacting with Google Brain and is there any overlap?

Sure, so we’re very complementary, actually. We talk every week. Brain focuses mainly on deep learning, and it’s got incredible engineers like Jeff Dean, so they’ve rolled that out to every corner of the company, and that’s why we get amazing things like Google Photos search. And they’re doing a phenomenal job of that. Also they’re based in Mountain View, so they’re closer to the product groups and they have more like 12 to 18 month research cycles, whereas we’re more about algorithmic development and we tend to go for things that are two to three years long and don’t necessarily have a direct product focus at the start.

How important was Google’s support to AlphaGo — could you have done it without them?

It was very important. AlphaGo doesn’t actually use that much hardware in play, but we needed a lot of hardware to train it and do all the different versions and have them play each other in tournaments on the cloud. That takes quite a lot of hardware to do efficiently, so we couldn’t have done it in this time frame without those resources.

Moving onto robotics. I’m based in Japan, which would like to think of itself as the spiritual home of robots. I see robots now in the country being used in two ways. You have companies like Fanuc making industrial robots that do amazing things for a very fixed purpose, and then you have these concierge-style robots like SoftBank’s Pepper and so on, and in some ways they’re kind of ambitious but the use cases are limited. What are your thoughts on the state of this space?

Yeah, I think as you say with Fanuc they’re pretty capable physically, what they’re missing is intelligence. And concierge robots are a little like smartphone assistants — the ones I’ve seen, anyway, are pre-programmed with template responses, and if you do something that goes off-piste they get confused.

So I guess the obvious question is how machine learning and so on will boost robots’ capabilities.

Well, it’s just a completely different approach. You’re building in from the ground up the ability to learn new things and deal with the unexpected, and I think that’s what you need for any robot or software application in the real world interacting with real users — they’re going to need to have that kind of capability to be properly useful. I think the learning route ultimately has to be the right way.

What are the most immediate use cases for learning robots that you can see?

We haven’t thought much about that, actually. Obviously the self-driving cars are kind of robots but they’re mostly narrow AI currently, although they use aspects of learning AI for the computer vision — Tesla uses pretty much standard off-the-shelf computer vision technology which is based on deep learning. I’m sure Japan’s thinking a lot about things like elderly care bots, or household cleaning bots, I think, would be extremely useful for society. Especially in demographics with an aging population, which I think is quite a pressing problem.

Why is this the sort of use case that a more learning-based approach is so dramatically better for?

Well, you just have to think "Why don’t we have those things yet?" Why don’t we have a robot that can clean up your house after you? The reason is, everyone’s house is very different in terms of layout, furniture, and so on, and even within your own house, the house state is different from day to day — sometimes it’ll be messy, sometimes it’ll be clean. So there’s no way you can pre-program a robot with the solution for sorting out your house, right? And you also might want to take into account your personal preferences about how you want your clothes folded. That’s actually a very complicated problem. We think of these things as really easy for people to do, but actually we’re dealing with hugely complex things.

Just as a matter of personal interest, do you have a robot vacuum cleaner?

Uh... we did have one, but it wasn’t very useful so... [laughs]

Because I do, and it is not super useful, but I find myself kind of learning its quirks and working around it, because I am lazy and the benefits are worth it. So I wonder about when we get to more advanced robots, where the tipping point of "good enough" is going to be. Are we going to stop before meaningful human-level interaction and work around the quirks?

Yeah, I mean, probably. I think everyone would buy a reasonably priced robot that could stack the dishes and clean up after you — these pretty dumb vacuum cleaners are quite popular anyway, and they don’t have any intelligence really. So yeah, I think every step of the way, incrementally, there’ll be useful things.

So what are your far-off expectations for how humans, robots, and AIs will interact in the future? Obviously people’s heads go to pretty wild sci-fi places.

I don’t think much about robotics myself personally. What I’m really excited to use this kind of AI for is science, and advancing that faster. I’d like to see AI-assisted science where you have effectively AI research assistants that do a lot of the drudgery work and surface interesting articles, find structure in vast amounts of data, and then surface that to the human experts and scientists who can make quicker breakthroughs. I was giving a talk at CERN a few months ago; obviously they create more data than pretty much anyone on the planet, and for all we know there could be new particles sitting on their massive hard drives somewhere and no-one’s got around to analyzing that because there’s just so much data. So I think it’d be cool if one day an AI was involved in finding a new particle.

I think that’s a pretty dramatic way to end.

The Verge is in Seoul for the entire Google DeepMind Challenge Match series — follow our coverage at this dedicated hub, and watch the matches live on YouTube.





March 12, 2016 at 02:54PM
Read the whole story
Share this story
Delete

Pushbullet API

1 Share

Pushbullet's API enables developers to build on the Pushbullet infrastructure. Our goal is to provide a full API that enables anything to tap into the Pushbullet network.

This is important to us because we believe everything, not just smartphones and computers, should be able to exchange information in real time. Here are some of the things you can build with Pushbullet:

  • Have a website and want to offer push notifications? We've built everything you need.
  • Want to build a Pushbullet client for a platform we don't officially support yet? Everything you need is here.
  • Working on a home automation system? Pushbullet can get everything chatting.
  • Working with sensors and want to send messages to another device? Pushbullet is just what you need.
  • Manage IT/servers and want to get updates and alerts no matter where you are or what device you're using? Pushbullet makes it easy.

Sections

  • API - Send/receive pushes using the Pushbullet server.

Problems/Feedback

For everything else (including incorrect things or suggested changes to these docs) feel free to contact us at [email protected].

All of our examples use the curl command line tool already available on most systems.

  • If you use Mac, it should already be installed, just open the Terminal app and run it.
  • If you are using Linux, it should already be installed, just open the Console and run it.
  • On Windows you're going to have to download it here or from the curl download page.
The Pushbullet API lets you send/receive pushes and do everything else the official Pushbullet clients can do. To access the API you'll need an access token so the server knows who you are. You can get one from your Account Settings page.

Once you have that access token, you can use it to access your Pushbullet account using the Pushbullet API:

Example: Get Current User

Request

curl --header 'Access-Token: <your_access_token_here>' \
     <a href="https://api.pushbullet.com/v2/users/me" rel="nofollow">https://api.pushbullet.com/v2/users/me</a>

Response

{
  "created": 1.381092887398433e+09,
  "email": "[email protected]",
  "email_normalized": "[email protected]",
  "iden": "ujpah72o0",
  "image_url": "https://static.pushbullet.com/missing-image/55a7dc-45",
  "max_upload_size": 2.62144e+07,
  "modified": 1.441054560741007e+09,
  "name": "Elon Musk"
}
The API accepts requests over HTTPS at <a href="https://api.pushbullet.com" rel="nofollow">https://api.pushbullet.com</a>. All POST requests must use a JSON body with the Content-Type header set to application/json. Most programming languages have some way to encoded objects to JSON, and using the built-in library is recommended, since it will correctly handle newline characters and quotes.

Authentication

To authenticate for the API, use your access token in a header like Access-Token: <your_access_token_here>. Your access token can be found on the Account Settings page. Keep in mind that this key has full access to your account, so don't go posting it all over the internets.
If you are making an app that uses the Pushbullet API on behalf of another user (for instance, to send push notifications as that user), use OAuth to get an access token for that user. Using your own access token while developing though saves you from having to setup OAuth until later.
You can make a request from any app, though how you do that may depend on if you are writing a script or using a programming language. If you have a terminal and the curl utility you can perform requests from the command line.

Example: Get Current User

Request

curl --header 'Access-Token: <your_access_token_here>' \
     <a href="https://api.pushbullet.com/v2/users/me" rel="nofollow">https://api.pushbullet.com/v2/users/me</a>

Response

{
  "created": 1.381092887398433e+09,
  "email": "[email protected]",
  "email_normalized": "[email protected]",
  "iden": "ujpah72o0",
  "image_url": "https://static.pushbullet.com/missing-image/55a7dc-45",
  "max_upload_size": 2.62144e+07,
  "modified": 1.441054560741007e+09,
  "name": "Elon Musk"
}

Because we allow CORS requests, you can make a request from any browser (you can hit the run button or copy and paste this code into your javascript console):

Responses are always JSON. Keys are either present with a non-empty value, or entirely absent from the response. Empty values are: null, false, "", [], and {}. Deleted objects will only have the keys iden, active, created, and modified because all other properties have been removed and are now empty values.
Example: API Response
{
  "created": 1.35794175382879e+09,
  "email": "[email protected]",
  "email_normalized": "[email protected]",
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.39932599218423e+09
}

HTTP Status Codes

  • 200 OK - Everything worked as expected.
  • 400 Bad Request - Usually this results from missing a required parameter.
  • 401 Unauthorized - No valid access token provided.
  • 403 Forbidden - The access token is not valid for that request.
  • 404 Not Found - The requested item doesn't exist.
  • 429 Too Many Requests - You have been ratelimited for making too many requests to the server.
  • 5XX Server Error - Something went wrong on Pushbullet's side. If this error is from an intermediate server, it may not be valid JSON.

Errors

Error responses (any non-200 error code) contain information on the kind of error that happened. The response JSON will have an error property with the following fields:

  • type - A machine-readable code to refer to this type of error. Either invalid_request for client side errors or server for server side errors.
  • message - A (mostly) human-readable error message.
  • param - (OPTIONAL) Appears sometimes during an invalid_request error to say which parameter in the request caused the error.
  • cat - Some sort of ASCII cat to offset the pain of receiving an error message.
Example: Error Response
{
  "error": {
    "cat": "~(=^‥^)",
    "message": "The resource could not be found.",
    "type": "invalid_request"
  }
}

Errors from the Pushbullet server will have this JSON body. Errors from intermediate servers or the hosting infrastructure may not, so you should be able to handle a non-JSON response as a generic error.

Objects (such as pushes and devices) can be created, modified, listed and deleted.
All timestamps that appear on objects are floating point seconds since the epoch, also called Unix Time.

All calls to list objects (list-*) accept the active, limit, and cursor parameters.

Bootstrapping

By default, listing objects of any type will return deleted objects (this is useful for syncing). When you are getting the initial list of objects, you may want to only fetch the active ones. To get only active objects, set active to true on the request.

When listing objects, if you receive a cursor in the response, it means the results are on multiple pages. To request the next page of results, use this cursor as the parameter cursor in the next request. Any time you list a collection of objects, they may be multiple pages (objects are always returned with the most recent ones first). You can specify a limit parameter on any calls that return a list of objects to get a smaller number of objects on each page. The default (maximum) limit is 500, including deleted objects.

Syncing Changes

All calls to list objects accept a modified_after property (a timestamp). Any objects modified since that time will be returned, most recently modified first. The modified_after parameter should be the most recent modified value from an object returned by the server (don't trust the local machine's timestamp as it usually is not the same value as the server).

Deleted Objects

When you query with a modified_after timestamp to sync changed objects to a device, you need to know if an object was deleted so you can remove it locally. Deleted objects will have active=false and all properties except for iden, created, modified, and active will be missing from the returned object. Deleted objects show up by default when listing objects.

Resizing Images

Pushes have an image_url property that can be resized by setting query parameters. To use this, add =s<pixels> to the end of the url.
Example: Resize an Image

Resize the image so that the longest side is not longer than 100 pixels

Before After

The image_url should be hosted on domain ending with .googleusercontent.com. If the domain does not end with that, you should not attempt to resize the image with a query parameter. Objects besides pushes have an image_url property but they cannot necessarily be resized the same way.

Backwards Compatibility

We try to make only backwards compatible changes to existing public API calls. This means that we should not change the meaning of existing calls, and that we will only add, not remove, keys from objects returned from the API. Adding a key is considered to be a backwards-compatible change.

Ratelimiting

When you do a request to the API you will receive headers like the following on the response:

X-Ratelimit-Limit: 32768
X-Ratelimit-Remaining: 32765
X-Ratelimit-Reset: 1432447070
These tell you what the ratelimit is, how much you have remaining and when it resets (integer seconds in Unix Time). The units are a sort of generic 'cost' number. A request costs 1 and a database operation costs 4. So reading 500 pushes costs about 500 database operations + 1 request = 500*4 + 1 = 2001. You can see how much a request cost by the change in X-Ratelimit-Remaining between two requests.

Overview

OAuth lets you access a user's Pushbullet account or have them authenticate with their Pushbullet account using a browser.

OAuth is a standard authentication procedure used by most websites, here's how it works:
  1. You, the app developer, register your app (called an "OAuth client") with Pushbullet
  2. Using a url you generate in your app (you can see an example one on the Create Client page) you send the user to the Pushbullet site. One of the parameters of the url is a redirect url that the user will be sent to when they are done authorizing your app.
  3. The user authorizes your application by clicking the "Allow" button.
  4. The user is redirected to the redirect url you provided earlier, which is generally your site or your app.

Here's roughly how this looks with pictures:

Getting Started

To get started, create a client (register your application) on the Create Client page. For the examples on this page, the client looks like this:
EXAMPLE CLIENT
{
  "client_id": "YW7uItOzxPFx8vJ4",
  "client_secret": "MmA98EDg0pjr4fZw",
  "iden": "ujpah72o0sjAoRtnM0jc",
  "image_url": "http://www.catpusher.com/logo.png",
  "name": "Cat Pusher",
  "redirect_uri": "http://www.catpusher.com/auth_complete",
  "website_url": "http://www.catpusher.com"
}

Getting an Access Token

  • client_id - client_id from registering your client
  • redirect_uri - The url you want to redirect the user to after authorization is complete. The path portion must match what was provided for the client, the query string may be set dynamically.
  • response_type - Either "code" (if you've got a server) or "token" (if your app is entirely on the client)
EXAMPLE URL
<a href="https://www.pushbullet.com/authorize?client_id=YW7uItOzxPFx8vJ4&redirect_uri=http%3A%2F%2Fwww.catpusher.com%2Fauth_complete&response_type=code" rel="nofollow">https://www.pushbullet.com/authorize?client_id=YW7uItOzxPFx8vJ4&redirect_uri=http%3A%2F%2Fwww.catpusher.com%2Fauth_complete&response_type=code</a>
NOTE: There's an example url ("oauth test url") on the Create Client page for your app.

When the user is sent to this page, they are able to authorize or deny your application. If they choose deny, they get redirected to the redirect_uri with the parameter "error=access_denied".

If they chose authorize, there are two possible next steps, depending on the value of response_type:

For Client-Side Apps: response_type=token

The user is redirected to the redirect_uri with a url fragment of "access_token=<access_token>". If you have a client side app running an embedded web browser, you can configure your redirect_uri to be "https://www.pushbullet.com/login-success" and then use this redirect_uri in the authorize call.

EXAMPLE URL
<a href="https://www.pushbullet.com/authorize?client_id=YW7uItOzxPFx8vJ4&redirect_uri=https%3A%2F%2Fwww.pushbullet.com%2Flogin-success&response_type=token" rel="nofollow">https://www.pushbullet.com/authorize?client_id=YW7uItOzxPFx8vJ4&redirect_uri=https%3A%2F%2Fwww.pushbullet.com%2Flogin-success&response_type=token</a>
EXAMPLE REDIRECT
<a href="https://www.pushbullet.com/login-success#access_token=o.RUe7IZgC6384GrI1" rel="nofollow">https://www.pushbullet.com/login-success#access_token=o.RUe7IZgC6384GrI1</a>

For Apps with Servers: response_type=code

If you have a server you can use this response_type, it's potentially more secure than the client-side one, since the client never sees the actual access token. In this mode the user is redirected to the redirect_uri with a parameter "code=<code>".

EXAMPLE URL
<a href="https://www.pushbullet.com/authorize?client_id=YW7uItOzxPFx8vJ4&redirect_uri=http%3A%2F%2Fwww.catpusher.com%2Fauth_complete&response_type=code" rel="nofollow">https://www.pushbullet.com/authorize?client_id=YW7uItOzxPFx8vJ4&redirect_uri=http%3A%2F%2Fwww.catpusher.com%2Fauth_complete&response_type=code</a>
EXAMPLE REDIRECT
<a href="http://www.catpusher.com/auth_complete?code=RUe7IZgC6384GrI1" rel="nofollow">http://www.catpusher.com/auth_complete?code=RUe7IZgC6384GrI1</a>
  • grant_type - Set to "authorization_code"
  • client_id - client_id from registering your client
  • client_secret - client_secret from registering your client
  • code - code from the redirect

Example: Convert Code to Access Token

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"client_id":"YW7uItOzxPFx8vJ4","client_secret":"MmA98EDg0pjr4fZw","code":"RUe7IZgC6384GrI1","grant_type":"authorization_code"}' \
     --request POST \
     <a href="https://api.pushbullet.com/oauth2/token" rel="nofollow">https://api.pushbullet.com/oauth2/token</a>

Response

{
  "access_token": "a6FJVAA0LVJKrT8k",
  "token_type": "Bearer"
}

You can add extra query params to the end of redirect_uri if you need to store extra state for the request. For instance, if you have your client's redirect_uri set to <a href="http://www.catpusher.com/auth_complete" rel="nofollow">http://www.catpusher.com/auth_complete</a>, then when you build the url to send the user to Pushbullet, you could specify redirect_uri=http://www.catpusher.com/auth_complete?state=zhk2KJ3SAAS3q1. When the user finishes authorizing your app, they would end up at <a href="http://www.catpusher.com/auth_complete?state=zhk2KJ3SAAS3q1&code=RUe7IZgC6384GrI1" rel="nofollow">http://www.catpusher.com/auth_complete?state=zhk2KJ3SAAS3q1&code=RUe7IZgC6384GrI1</a>.

Using Your Access Token

Now that you have an access token, you can access Pushbullet as that user. Just include the access_token with your requests as the username in HTTP Basic Auth or set the Access-Token header to your access_token. Make sure to keep the access_token in a safe place, it allows access to your users accounts!

Example: Get Current User

Request

curl --header 'Access-Token: <your_access_token_here>' \
     <a href="https://api.pushbullet.com/v2/users/me" rel="nofollow">https://api.pushbullet.com/v2/users/me</a>

Response

{
  "created": 1.381092887398433e+09,
  "email": "[email protected]",
  "email_normalized": "[email protected]",
  "iden": "ujpah72o0",
  "image_url": "https://static.pushbullet.com/missing-image/55a7dc-45",
  "max_upload_size": 2.62144e+07,
  "modified": 1.441054560741007e+09,
  "name": "Elon Musk"
}

The access_token does not have a set expiration time, but may be expired at some point in the future. If you delete your client, all existing tokens are invalidated.

The encryption is used primarily for ephemerals. If you enable it in your Pushbullet client, you should be able to see the encrypted messages on the stream whenever you use any of the features that support end-to-end encryption.

Key Generation

The key is created from a user-supplied password and passed through PBKDF2:
  • Pseudorandom function: HMAC-SHA256
  • Password: password supplied by the user for encryption, must be the same on all Pushbullet devices owned by the user
  • Salt: the user iden for the current user, e.g. up0snaKOsn
  • Number of iterations: 30,000
  • Derived key length: 256-bit
Code Sample: Generate an Encryption/Decryption Key
var pseudorandom_function = forge.md.sha256.create();
var password = "hunter2";
var salt = "up0snaKOsn";
var iterations = 30000;
var derived_key_length_bytes = 32; // 256-bit
var key = forge.pkcs5.pbkdf2(
  password,
  salt,
  iterations,
  derived_key_length_bytes,
  pseudorandom_function
)
// encode to base64 so we can easily print the key
// (normally it's in binary and can't be printed)
var base64_key = btoa(key);
console.log("base64_key:", base64_key);

Encryption

To encrypt a message, use AES-256 with GCM Authentication. AES-256 uses the 256-bit key that is output by PBKDF2. To encrypt you need to generate a 96-bit initialization vector (this is used to start the encryption process, it is not a secret). The output of AES-256 with GCM will be the encrypted message (arbitrary length) and a 128-bit tag. The encoding for this encrypted message looks like this:
encoded_message = "1" + tag + initialization_vector + encrypted_message
The 1 prefix is a version number indicating the version of the encoding. When encoded_message is put into JSON, it must be base64-encoded since JSON cannot handle binary data.
Code Sample: Encrypt a Message
// convert key from base64 to binary
var key = atob("1sW28zp7CWv5TtGjlQpDHHG4Cbr9v36fG5o4f74LsKg=");
var initialization_vector = forge.random.getBytes(12); // 96-bit
var message = "meow!";

var cipher = forge.cipher.createCipher('AES-GCM', key);
cipher.start({"iv": initialization_vector});
cipher.update(forge.util.createBuffer(forge.util.encodeUtf8(message)));
cipher.finish();

var tag = cipher.mode.tag.getBytes();
var encrypted_message = cipher.output.getBytes();

var encoded_message = "1" + tag + initialization_vector + encrypted_message;
var base64_encoded_message = btoa(encoded_message);
console.log("base64_encoded_message:", base64_encoded_message);

Decryption

If you can encrypt a message, decrypting it is straightforward. You need to decode the encoded_message into the tag, initialization_vector, and encrypted_message.

Code Sample: Decrypt an Encrypted Message
var key = atob("1sW28zp7CWv5TtGjlQpDHHG4Cbr9v36fG5o4f74LsKg=");
var encoded_message = atob("MSfJxxY5YdjttlfUkCaKA57qU9SuCN8+ZhYg/xieI+lDnQ==");

var version = encoded_message.substr(0, 1);
var tag = encoded_message.substr(1, 16); // 128 bits
var initialization_vector = encoded_message.substr(17, 12); // 96 bits
var encrypted_message = encoded_message.substr(29);

if (version != "1") {
  throw "invalid version"
}

var decipher = forge.cipher.createDecipher('AES-GCM', key);
decipher.start({
    'iv': initialization_vector,
    'tag': tag
});
decipher.update(forge.util.createBuffer(encrypted_message));
decipher.finish();

var message = decipher.output.toString('utf8');
console.log("message:", message);
    

Make sure your encryption library is checking the validity of the tag parameter by using an incorrect tag and verifying that you get some sort of error. You must also discard any encoded_message without a prefix of 1 as those will be different, incompatible encodings in the future.

Encrypted Ephemeral Format

An ephemeral that looks like this:

{
  "push": {
    "data": {
      "key1": "value1",
      "key2": "value2"
    }
  },
  "type": "push"
}

Will look like this when encrypted:

{
  "push": {
    "ciphertext": "MXAdvN64uXWtLXCRaqYHEtGhiogR1VHyXX21Lpjp4jv3v+JWygMBA9Wp5npbQdfeZAgOZI+JT3y3pbmq+OrKXrK1rg==",
    "encrypted": true
  },
  "type": "push"
}

If you decode ciphertext then you will get the following javascript object:

{
  "key1": "value1",
  "key2": "value2"
}

Connect to the stream

You can connect to the websocket for an account by creating a secure websocket connection (wss://) to wss://stream.pushbullet.com/websocket/<your_access_token_here>

Once you are connected, you will see type="nop" messages periodically as well as other types if you send any ephemerals or pushes.

Stream Messages

All messages are JSON objects with a type key.

Types

  • type="nop" - Sent every 30 seconds confirming the connection is active.
  • type="tickle" - Tells you something has changed on the server. The subtype property tells you what has changed.
    • subtype="push" - A change to the /v2/pushes resources.
    • subtype="device" - A change to the /v2/devices resources.
  • type="push" - A new push. The push data is available in an object from the push key. NOTE: This is only used for Ephemerals (such as mirrored notifications) not normal pushes (such as those you see with list-pushes). Normal pushes only generate tickles, not these messages.
EXAMPLE MESSAGES
{
  "type": "nop"
}
{
  "subtype": "push",
  "type": "tickle"
}
{
  "push": {
    "cat": "meow"
  },
  "type": "push"
}

Push message types

A message with type="push" will contain a data object mapped to by the key push. This object is documented here based on its internal type.

  • type="mirror" - This push is a notification mirrored from an Android device.
  • type="dismissal" - This push is a dismissal message for a notification.
EXAMPLE NOTIFICATION MIRROR
{
  "push": {
    "application_name": "Pushbullet",
    "body": "If you see this on your computer, mirroring is working!\n",
    "created": 1.39935096416497e+09,
    "dismissable": true,
    "icon": "iVBORw0KGgoAAAANSUhEBgUzC42AAAADNElEQVRo\ng==\n",
    "iden": "1e443556ba3217c",
    "notification_id": "-8",
    "notification_tag": null,
    "package_name": "com.pushbullet.android",
    "receiver_email": "[email protected]",
    "receiver_email_normalized": "[email protected]",
    "receiver_iden": "ujpah72o0",
    "sender_email": "[email protected]",
    "sender_email_normalized": "[email protected]",
    "sender_iden": "ujpah72o0",
    "source_device_iden": "ujpah72o0sjAoRtnM0jc",
    "title": "Mirroring test",
    "type": "mirror"
  },
  "type": "push"
}
EXAMPLE NOTIFICATION DISMISSAL
{
  "push": {
    "created": 1.39935096622458e+09,
    "iden": "1e443556ba3217c",
    "notification_id": "-8",
    "notification_tag": null,
    "package_name": "com.pushbullet.android",
    "receiver_email": "[email protected]",
    "receiver_email_normalized": "[email protected]",
    "receiver_iden": "ujpah72o0",
    "sender_email": "[email protected]",
    "sender_email_normalized": "[email protected]",
    "sender_iden": "ujpah72o0",
    "source_device_iden": "ujpah72o0sjAoRtnM0jc",
    "type": "dismissal"
  },
  "type": "push"
}

Reacting to tickles

When you receive a tickle message, it means that a resource of the type subtype has changed. This is your cue to update that resource. Here's an example for the pushes type:

On receiving this message:

{
  "subtype": "push",
  "type": "tickle"
}

Request the pushes that have changed since the last time we received them:

GET <a href="https://api.pushbullet.com/v2/pushes?modified_after=1399008037.849" rel="nofollow">https://api.pushbullet.com/v2/pushes?modified_after=1399008037.849</a>

Then merge these updates into your local copy of the push history.

Note: It's best to use the most recently modified local push's modified timestamp when making requests for updates. This will keep the responses small and fast. Additionally, don't trust the local machine's current timestamp because it is inevitably different from the server's timestamp. Use the latest timestamp you have seen on a push object instead. Since pushes are returned with most recently modified first, this will be the first push you get from any call to list-pushes.

You can send arbitrary JSON messages, called "ephemerals", to all devices on your account. Ephemerals are stored for a short period of time (if at all) and are sent directly to devices. Because they are sent directly, there is no "tickle" message like when creating or updating pushes or other objects, the JSON message appears directly in the stream.

Ephemerals are used by the Pushbullet apps for notification mirroring and universal copy/paste.

Unlike some of the other HTTP endpoints, POST parameters are not supported for ephemerals due to their JSON structure.

Send an ephemeral

Parameters

  • type - Must be set to push which is the only type of ephemeral currently.
  • push - An arbitrary JSON object.

Example: Send Ephemeral

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"push":{"cat":"meow"},"type":"push"}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/ephemerals" rel="nofollow">https://api.pushbullet.com/v2/ephemerals</a>

Response

{}

Ephemerals respond with an empty JSON object unless there is an error.

You can send an SMS from your phone by sending an ephemeral message to your phone.

SMS Ephemeral

  • type - push for send SMS.
  • push - information about the SMS to send
    • type - messaging_extension_reply for send SMS.
    • package_name - com.pushbullet.android for send SMS
    • source_user_iden - The user iden of the user sending this message.
    • target_device_iden - The iden of the device corresponding to the phone that should send the SMS.
    • conversation_iden - Phone number to send the SMS to.
    • message - The SMS message to send.
EXAMPLE
{
  "push": {
    "conversation_iden": "+1 303 555 1212",
    "message": "Hello!",
    "package_name": "com.pushbullet.android",
    "source_user_iden": "ujpah72o0",
    "target_device_iden": "ujpah72o0sjAoRtnM0jc",
    "type": "messaging_extension_reply"
  },
  "type": "push"
}

Mirrored notifications are notifications sent from android devices (currently the only source of mirrored notifications) to other devices. To test these out you can go into the android app's settings screen and hit the button "Send a test notification" while listening to the stream.

Notification Ephemeral

  • type - push for mirrored notifications.
  • push - information about the notification
    • type - mirror for mirrored notifications.
    • icon - Base64-encoded JPEG image to use as the icon of the push.
    • title - The title of the notification.
    • body - The body of the notification.
    • source_user_iden - The user iden of the user sending this message.
    • source_device_iden - The iden of the device sending this message.
    • application_name - The name of the application that created the notification.
    • dismissable - True if the notification can be dismissed.
    • package_name - The package that made the notification, used when updating/dismissing an existing notification.
    • notification_id - The id of the notification, used when updating/dismissing an existing notification.
    • notification_tag - The tag of the notification, used when updating/dismissing an existing notification.
    • has_root - The phone is rooted.
    • client_version - The client version of the app sending this message.
EXAMPLE
{
  "push": {
    "application_name": "Pushbullet",
    "body": "If you see this on your computer, Android-to-PC notifications are working!\n",
    "client_version": 125,
    "dismissable": true,
    "has_root": false,
    "icon": "(base64_encoded_jpeg)",
    "notification_id": "-8",
    "notification_tag": null,
    "package_name": "com.pushbullet.android",
    "source_device_iden": "ujpah72o0sjAoRtnM0jc",
    "source_user_iden": "ujpah72o0",
    "title": "Mirroring test",
    "type": "mirror"
  },
  "type": "push"
}

Dismissal Ephemeral

  • type - "push" for notification dismissals.
  • push - information about the dismissal.
    • type - "dismissal" for notification dismissals.
    • package_name - Set to the package_name field from the mirrored notification.
    • notification_id - Set to the notification_id field from the mirrored notification.
    • notification_tag - Set to the notification_tag field from the mirrored notification.
    • source_user_iden - Set to the source_user_iden field from the mirrored notification.
EXAMPLE
{
  "push": {
    "notification_id": "-8",
    "notification_tag": null,
    "package_name": "com.pushbullet.android",
    "source_user_iden": "ujpah72o0",
    "type": "dismissal"
  },
  "type": "push"
}

Example: Dismiss Notification

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"push":{"notification_id":"-8","notification_tag":null,"package_name":"com.pushbullet.android","source_user_iden":"ujpah72o0","type":"dismissal"},"type":"push"}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/ephemerals" rel="nofollow">https://api.pushbullet.com/v2/ephemerals</a>

Response

{}

The Pushbullet apps can monitor the clipboard and send out a message each time the user copies a new text selection, sending it to all the user's devices which can copy it to the system clipboard or otherwise make it available to the user.

Copy a String to the Clipboard

Properties

  • type - push for clipboard messages.
  • push - information about the clipboard message.
    • type - clip for clipboard messages.
    • body - The text to copy to the clipboard.
    • source_user_iden - The iden of the user sending this message.
    • source_device_iden - The iden of the device sending this message.

Example

{
  "push": {
    "body": "http://www.google.com",
    "source_device_iden": "ujpah72o0sjAoRtnM0jc",
    "source_user_iden": "ujpah72o0",
    "type": "clip"
  },
  "type": "push"
}

Example: Send Clipboard Content

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"push":{"body":"http://www.google.com","source_device_iden":"ujpah72o0sjAoRtnM0jc","source_user_iden":"ujpah72o0","type":"clip"},"type":"push"}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/ephemerals" rel="nofollow">https://api.pushbullet.com/v2/ephemerals</a>

Response

{}

Pushbullet URL Handler

The iPhone app has a url handler, pushbullet:// that can be used to compose pushes like so:

  pushbullet://compose?type=note&body=Hello

compose is the only option right now, but a few push types can be constructed (make sure to urlencode any parameters):

  pushbullet://compose?type=link&url=https%3A%2F%2Fwww.pushbullet.com
  pushbullet://compose?type=address&address=850%20Bryant%20St
Only type="note" and type="link" are supported for now (and their parameters are the same as in create-push).

Open in Pushbullet

If you use a UIDocumentInteractionController to preview a file, when the user selects "Open In..." for most file types, Pushbullet should show up in the list of applications.

If the user selects the Pushbullet app, the app should open with a new compose window for a type="file" push with the provided file attached.

Feedback

Chats are created whenever you send a message to someone or a receive a message from them and there is no existing chat between you and the other user.

Field Type Description
iden string Unique identifier for this object

Example: "ujpah72o0sjAoRtnM0jc"

active bool false if the item has been deleted

Example: true

created float Creation time in floating point seconds (unix timestamp)

Example: 1.381092887398433e+09

modified float Last modified time in floating point seconds (unix timestamp)

Example: 1.441054560741007e+09

muted bool If true, notifications from this chat will not be shown

Example: false

with object The user or email that the chat is with
 ↳ email string Email address of the person
 ↳ email_normalized string Canonical email address of the person
 ↳ iden string If this is a user, the iden of that user

Example: "ujlMns72k"

 ↳ image_url string Image to display for the person

Example: "https://dl.pushbulletusercontent.com/foGfub1jtC6yYcOMACk1AbHwTrTKvrDc/john.jpg"

 ↳ type string "email" or "user"

Example: "user"

 ↳ name string Name of the person

Example: "John Carmack"

Example

{
  "active": true,
  "created": 1.412047948579029e+09,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.412047948579031e+09,
  "with": {
    "email": "[email protected]",
    "email_normalized": "[email protected]",
    "iden": "ujlMns72k",
    "image_url": "https://dl.pushbulletusercontent.com/foGfub1jtC6yYcOMACk1AbHwTrTKvrDc/john.jpg",
    "name": "John Carmack",
    "type": "user"
  }
}
Get a list of chats belonging to the current user. If you have a large number of chats, you will need to use Pagination.

Call

GET <a href="https://api.pushbullet.com/v2/chats" rel="nofollow">https://api.pushbullet.com/v2/chats</a>

Request

none

Response

Field Type Description
chats []Chat Array of Chat objects ordered with most recently modified first

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     <a href="https://api.pushbullet.com/v2/chats" rel="nofollow">https://api.pushbullet.com/v2/chats</a>

Response

{
  "chats": [
    {
      "active": true,
      "created": 1.412047948579029e+09,
      "iden": "ujpah72o0sjAoRtnM0jc",
      "modified": 1.412047948579031e+09,
      "with": {
        "email": "[email protected]",
        "email_normalized": "[email protected]",
        "iden": "ujlMns72k",
        "image_url": "https://dl.pushbulletusercontent.com/foGfub1jtC6yYcOMACk1AbHwTrTKvrDc/john.jpg",
        "name": "John Carmack",
        "type": "user"
      }
    }
  ]
}

Create a chat with another user or email address if one does not already exist.

Call

POST <a href="https://api.pushbullet.com/v2/chats" rel="nofollow">https://api.pushbullet.com/v2/chats</a>

Request

Field Type Description
email string Email of person to create chat with (does not have to be a Pushbullet user)

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"email":"[email protected]"}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/chats" rel="nofollow">https://api.pushbullet.com/v2/chats</a>

Response

{
  "active": true,
  "created": 1.412047948579029e+09,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.412047948579031e+09,
  "with": {
    "email": "[email protected]",
    "email_normalized": "[email protected]",
    "iden": "ujlMns72k",
    "image_url": "https://dl.pushbulletusercontent.com/foGfub1jtC6yYcOMACk1AbHwTrTKvrDc/john.jpg",
    "name": "John Carmack",
    "type": "user"
  }
}

Update existing chat object.

Call

POST <a href="https://api.pushbullet.com/v2/chats/%7Biden%7D" rel="nofollow">https://api.pushbullet.com/v2/chats/{iden}</a>

Request

Field Type Description
muted bool true to mute the grant, false to unmute it

Example: true

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"muted":true}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/chats/ujpah72o0sjAoRtnM0jc" rel="nofollow">https://api.pushbullet.com/v2/chats/ujpah72o0sjAoRtnM0jc</a>

Response

{
  "active": true,
  "created": 1.412047948579029e+09,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.412094382919271e+09,
  "muted": true,
  "with": {
    "email": "[email protected]",
    "email_normalized": "[email protected]",
    "iden": "ujlMns72k",
    "image_url": "https://dl.pushbulletusercontent.com/foGfub1jtC6yYcOMACk1AbHwTrTKvrDc/john.jpg",
    "name": "John Carmack",
    "type": "user"
  }
}

Delete a chat object.

Call

DELETE <a href="https://api.pushbullet.com/v2/chats/%7Biden%7D" rel="nofollow">https://api.pushbullet.com/v2/chats/{iden}</a>

Request

none

Response

none

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --request DELETE \
     <a href="https://api.pushbullet.com/v2/chats/ujpah72o0sjAoRtnM0jc" rel="nofollow">https://api.pushbullet.com/v2/chats/ujpah72o0sjAoRtnM0jc</a>

Response

{}
Field Type Description
iden string Unique identifier for this object

Example: "ujpah72o0sjAoRtnM0jc"

active bool false if the item has been deleted

Example: true

created float Creation time in floating point seconds (unix timestamp)

Example: 1.381092887398433e+09

modified float Last modified time in floating point seconds (unix timestamp)

Example: 1.441054560741007e+09

icon string Icon to use for this device, can be an arbitrary string. Commonly used values are: "desktop", "browser", "website", "laptop", "tablet", "phone", "watch", "system"

Example: "ios"

nickname string Name to use when displaying the device

Example: "Elon Musk's iPhone"

generated_nickname bool true if the nickname was automatically generated from the manufacturer and model fields (only used for some android phones)

Example: true

manufacturer string Manufacturer of the device

Example: "Apple"

model string Model of the device

Example: "iPhone 5s (GSM)"

app_version int Version of the Pushbullet application installed on the device

Example: 8623

fingerprint string String fingerprint for the device, used by apps to avoid duplicate devices. Value is platform-specific.

Example: "nLN19IRNzS5xidPF+X8mKGNRpQo2X6XBgyO30FL6OiQ="

key_fingerprint string Fingerprint for the device's end-to-end encryption key, used to determine which devices the current device (based on its own key fingerprint) will be able to talk to.

Example: "5ae6ec7e1fe681861b0cc85c53accc13bf94c11db7461a2808903f7469bfda56"

push_token string Platform-specific push token. Normally a prefix followed by an identifier. Prefixes are set per-app, if you want to receive push notifications in your app, contact [email protected] with your push backend credentials to get a prefix.

Example: "production:f73be0ee7877c8c7fa69b1468cde764f"

has_sms string true if the devices has SMS capability, currently only true for type="android" devices

Example: true

type string DEPRECATED, use icon field instead. Type of device, can be an arbitrary string. Commonly used values are: "android", "chrome", "firefox", "ios", "windows", "stream", "safari", "mac", "opera", "website"
kind string DEPRECATED, old name for type
pushable bool DEPRECATED, used to be for partially-initialized type="android" devices

Example

{
  "active": true,
  "app_version": 8623,
  "created": 1.412047948579029e+09,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "manufacturer": "Apple",
  "model": "iPhone 5s (GSM)",
  "modified": 1.412047948579031e+09,
  "nickname": "Elon Musk's iPhone",
  "push_token": "production:f73be0ee7877c8c7fa69b1468cde764f"
}
Get a list of devices belonging to the current user. If you have a large number of devices, you will need to use Pagination.

Call

GET <a href="https://api.pushbullet.com/v2/devices" rel="nofollow">https://api.pushbullet.com/v2/devices</a>

Request

none

Response

Field Type Description
devices []Device Array of Device objects ordered with most recently modified first

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     <a href="https://api.pushbullet.com/v2/devices" rel="nofollow">https://api.pushbullet.com/v2/devices</a>

Response

{
  "devices": [
    {
      "active": true,
      "app_version": 8623,
      "created": 1.412047948579029e+09,
      "iden": "ujpah72o0sjAoRtnM0jc",
      "manufacturer": "Apple",
      "model": "iPhone 5s (GSM)",
      "modified": 1.412047948579031e+09,
      "nickname": "Elon Musk's iPhone",
      "push_token": "production:f73be0ee7877c8c7fa69b1468cde764f"
    }
  ]
}

Create a new device.

Call

POST <a href="https://api.pushbullet.com/v2/devices" rel="nofollow">https://api.pushbullet.com/v2/devices</a>

Request

Field Type Description
nickname string Name to use when displaying the device

Example: "Elon Musk's iPhone"

model string Model of the device

Example: "iPhone 5s (GSM)"

manufacturer string Manufacturer of the device

Example: "Apple"

push_token string Platform-specific push token. Normally a prefix followed by an identifier. Prefixes are set per-app, if you want to receive push notifications in your app, contact [email protected] with your push backend credentials to get a prefix.

Example: "production:f73be0ee7877c8c7fa69b1468cde764f"

app_version int Version of the Pushbullet application installed on the device

Example: 8623

icon string Icon to use for this device, can be an arbitrary string. Commonly used values are: "desktop", "browser", "website", "laptop", "tablet", "phone", "watch", "system"

Example: "ios"

has_sms string true if the devices has SMS capability, currently only true for type="android" devices

Example: true

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"app_version":8623,"manufacturer":"Apple","model":"iPhone 5s (GSM)","nickname":"Elon Musk's iPhone","push_token":"production:f73be0ee7877c8c7fa69b1468cde764f"}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/devices" rel="nofollow">https://api.pushbullet.com/v2/devices</a>

Response

{
  "active": true,
  "app_version": 8623,
  "created": 1.412047948579029e+09,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "manufacturer": "Apple",
  "model": "iPhone 5s (GSM)",
  "modified": 1.412047948579031e+09,
  "nickname": "Elon Musk's iPhone",
  "push_token": "production:f73be0ee7877c8c7fa69b1468cde764f"
}

Update an existing device.

Call

POST <a href="https://api.pushbullet.com/v2/devices/%7Biden%7D" rel="nofollow">https://api.pushbullet.com/v2/devices/{iden}</a>

Request

Field Type Description
nickname string Name to use when displaying the device

Example: "Elon Musk's iPhone"

model string Model of the device

Example: "iPhone 5s (GSM)"

manufacturer string Manufacturer of the device

Example: "Apple"

push_token string Platform-specific push token. Normally a prefix followed by an identifier. Prefixes are set per-app, if you want to receive push notifications in your app, contact [email protected] with your push backend credentials to get a prefix.

Example: "production:f73be0ee7877c8c7fa69b1468cde764f"

app_version int Version of the Pushbullet application installed on the device

Example: 8623

icon string Icon to use for this device, can be an arbitrary string. Commonly used values are: "desktop", "browser", "website", "laptop", "tablet", "phone", "watch", "system"

Example: "ios"

has_sms string true if the devices has SMS capability, currently only true for type="android" devices

Example: true

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"nickname":"Work Phone"}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/devices/ujpah72o0sjAoRtnM0jc" rel="nofollow">https://api.pushbullet.com/v2/devices/ujpah72o0sjAoRtnM0jc</a>

Response

{
  "active": true,
  "app_version": 8623,
  "created": 1.412047948579029e+09,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "manufacturer": "Apple",
  "model": "iPhone 5s (GSM)",
  "modified": 1.412094382919271e+09,
  "nickname": "Work Phone",
  "push_token": "production:f73be0ee7877c8c7fa69b1468cde764f"
}

Delete a device.

Call

DELETE <a href="https://api.pushbullet.com/v2/devices" rel="nofollow">https://api.pushbullet.com/v2/devices</a>

Request

none

Response

none

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --request DELETE \
     <a href="https://api.pushbullet.com/v2/devices/ujpah72o0sjAoRtnM0jc" rel="nofollow">https://api.pushbullet.com/v2/devices/ujpah72o0sjAoRtnM0jc</a>

Response

{}

A Push.

Field Type Description
iden string Unique identifier for this object

Example: "ujpah72o0sjAoRtnM0jc"

active bool false if the item has been deleted

Example: true

created float Creation time in floating point seconds (unix timestamp)

Example: 1.381092887398433e+09

modified float Last modified time in floating point seconds (unix timestamp)

Example: 1.441054560741007e+09

type string Type of the push, one of "note", "file", "link".

Example: "note"

dismissed bool true if the push has been dismissed by any device or if any device was active when the push was received

Example: false

guid string Unique identifier set by the client, used to identify a push in case you receive it from /v2/everything before the call to /v2/pushes has completed. This should be a unique value. Pushes with guid set are mostly idempotent, meaning that sending another push with the same guid is unlikely to create another push (it will return the previously created push).

Example: "993aaa48567d91068e96c75a74644159"

direction string Direction the push was sent in, can be "self", "outgoing", or "incoming"

Example: "self"

sender_iden string User iden of the sender

Example: "ujpah72o0"

sender_email string Email address of the sender
sender_email_normalized string Canonical email address of the sender
sender_name string Name of the sender

Example: "Elon Musk"

receiver_iden string User iden of the receiver

Example: "ujpah72o0"

receiver_email string Email address of the receiver
receiver_email_normalized string Canonical email address of the receiver
target_device_iden string Device iden of the target device, if sending to a single device

Example: "ujpah72o0sjAoRtnM0jc"

source_device_iden string Device iden of the sending device. Optionally set by the sender when creating a push

Example: "ujpah72o0sjAoRtnM0jc"

client_iden string If the push was created by a client, set to the iden of that client.

Example: "ujpah72o0sjAoRtnM0jc"

channel_iden string If the push was created by a channel, set to the iden of that channel

Example: "ujpah72o0sjAoRtnM0jc"

awake_app_guids []string List of guids (client side identifiers, not the guid field on pushes) for awake apps at the time the push was sent. If the length of this list is > 0, dismissed will be set to true and the awake app(s) must decide what to do with the notification

Example: ["web-2d8cdf2a2b9b","web-cdb2313c74e"]

title string Title of the push, used for all types of pushes

Example: "Space Travel Ideas"

body string Body of the push, used for all types of pushes

Example: "Space Elevator, Mars Hyperloop, Space Model S (Model Space?)"

url string URL field, used for type="link" pushes

Example: "http://www.teslamotors.com/"

file_name string File name, used for type="file" pushes

Example: "john.jpg"

file_type string File mime type, used for type="file" pushes

Example: "image/jpeg"

file_url string File download url, used for type="file" pushes

Example: "https://dl.pushbulletusercontent.com/foGfub1jtC6yYcOMACk1AbHwTrTKvrDc/john.jpg"

image_url string URL to an image to use for this push, present on type="file" pushes if file_type matches image/*

Example: "https://lh3.googleusercontent.com/mrrz35lLbiYAz8ejkJcpdsYhN3tMEtrXxj93k_gQPin4GfdDjVy2Bj26pOGrpFQmAM7OFBHcDfdMjrScg3EUIJrgJeY"

image_width int Width of image in pixels, only present if image_url is set

Example: 322

image_height int Height of image in pixels, only present if image_url is set

Example: 484

Example

{
  "active": true,
  "body": "Space Elevator, Mars Hyperloop, Space Model S (Model Space?)",
  "created": 1.412047948579029e+09,
  "direction": "self",
  "dismissed": false,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.412047948579031e+09,
  "receiver_email": "[email protected]",
  "receiver_email_normalized": "[email protected]",
  "receiver_iden": "ujpah72o0",
  "sender_email": "[email protected]",
  "sender_email_normalized": "[email protected]",
  "sender_iden": "ujpah72o0",
  "sender_name": "Elon Musk",
  "title": "Space Travel Ideas",
  "type": "note"
}

Request push history.

Call

GET <a href="https://api.pushbullet.com/v2/pushes" rel="nofollow">https://api.pushbullet.com/v2/pushes</a>

Request

Field Type Description
modified_after string Request pushes modified after this timestamp

Example: 1.4e+09

active string Don't return deleted pushes

Example: true

cursor string Cursor for getting multiple pages of pushes, see Pagination

Example: "3eae6fa796b06b51b7bd6ad824b9b63b"

limit integer Limit on the number of results returned, see Pagination

Example: 10

Response

Field Type Description
pushes []Push Array of Push objects ordered with most recently modified first

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --data-urlencode active="true" \
     --data-urlencode modified_after="1.4e+09" \
     --get \
     <a href="https://api.pushbullet.com/v2/pushes" rel="nofollow">https://api.pushbullet.com/v2/pushes</a>

Response

{
  "pushes": [
    {
      "active": true,
      "body": "Space Elevator, Mars Hyperloop, Space Model S (Model Space?)",
      "created": 1.412047948579029e+09,
      "direction": "self",
      "dismissed": false,
      "iden": "ujpah72o0sjAoRtnM0jc",
      "modified": 1.412047948579031e+09,
      "receiver_email": "[email protected]",
      "receiver_email_normalized": "[email protected]",
      "receiver_iden": "ujpah72o0",
      "sender_email": "[email protected]",
      "sender_email_normalized": "[email protected]",
      "sender_iden": "ujpah72o0",
      "sender_name": "Elon Musk",
      "title": "Space Travel Ideas",
      "type": "note"
    }
  ]
}

Send a push to a device or another person.

Target Parameters

Each push has a target, if you don't specify a target, we will broadcast it to all of the user's devices. Only one target may be specified.

  • device_iden - Send the push to a specific device. Appears as target_device_iden on the push. You can find this using the /v2/devices call.
  • email - Send the push to this email address. If that email address is associated with a Pushbullet user, we will send it directly to that user, otherwise we will fallback to sending an email to the email address (this will also happen if a user exists but has no devices registered).
  • channel_tag - Send the push to all subscribers to your channel that has this tag.
  • client_iden - Send the push to all users who have granted access to your OAuth client that has this iden.

Parameters for different types of pushes

  • Note
    • type - Set to note
    • title - The note's title.
    • body - The note's message.
  • Link
    • type - Set to link
    • title - The link's title.
    • body - A message associated with the link.
    • url - The url to open.
  • File
    • type - Set to file
    • body - A message to go with the file.
    • file_name - The name of the file.
    • file_type - The MIME type of the file.
    • file_url - The url for the file. See pushing files for how to get a file_url

Push a file

Pushing files is a two-part process: first the file needs to be uploaded, then a push needs to be sent for that file.

Once the file has been uploaded, set the file_name, file_url, and file_type returned in the response to the upload request as the parameters for a new push with type="file".

Call

POST <a href="https://api.pushbullet.com/v2/pushes" rel="nofollow">https://api.pushbullet.com/v2/pushes</a>

Request

Field Type Description
type string Type of the push, one of "note", "file", "link".

Example: "note"

title string Title of the push, used for all types of pushes

Example: "Space Travel Ideas"

body string Body of the push, used for all types of pushes

Example: "Space Elevator, Mars Hyperloop, Space Model S (Model Space?)"

url string URL field, used for type="link" pushes

Example: "http://www.teslamotors.com/"

file_name string File name, used for type="file" pushes

Example: "john.jpg"

file_type string File mime type, used for type="file" pushes

Example: "image/jpeg"

file_url string File download url, used for type="file" pushes

Example: "https://dl.pushbulletusercontent.com/foGfub1jtC6yYcOMACk1AbHwTrTKvrDc/john.jpg"

source_device_iden string Device iden of the sending device. Optional.

Example: "ujpah72o0sjAoRtnM0jc"

device_iden string Device iden of the target device, if sending to a single device. Appears as target_device_iden on the push.

Example: "ujpah72o0sjAoRtnM0jc"

client_iden string Client iden of the target client, sends a push to all users who have granted access to this client. The current user must own this client.

Example: "ujpah72o0sjAoRtnM0jc"

channel_tag string Channel tag of the target channel, sends a push to all people who are subscribed to this channel. The current user must own this channel.
email string Email address to send the push to. If there is a pushbullet user with this address, they get a push, otherwise they get an email.
guid string Unique identifier set by the client, used to identify a push in case you receive it from /v2/everything before the call to /v2/pushes has completed. This should be a unique value. Pushes with guid set are mostly idempotent, meaning that sending another push with the same guid is unlikely to create another push (it will return the previously created push).

Example: "993aaa48567d91068e96c75a74644159"

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"body":"Space Elevator, Mars Hyperloop, Space Model S (Model Space?)","title":"Space Travel Ideas","type":"note"}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/pushes" rel="nofollow">https://api.pushbullet.com/v2/pushes</a>

Response

{
  "active": true,
  "body": "Space Elevator, Mars Hyperloop, Space Model S (Model Space?)",
  "created": 1.412047948579029e+09,
  "direction": "self",
  "dismissed": false,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.412047948579031e+09,
  "receiver_email": "[email protected]",
  "receiver_email_normalized": "[email protected]",
  "receiver_iden": "ujpah72o0",
  "sender_email": "[email protected]",
  "sender_email_normalized": "[email protected]",
  "sender_iden": "ujpah72o0",
  "sender_name": "Elon Musk",
  "title": "Space Travel Ideas",
  "type": "note"
}

Update a push.

Call

POST <a href="https://api.pushbullet.com/v2/pushes/%7Biden%7D" rel="nofollow">https://api.pushbullet.com/v2/pushes/{iden}</a>

Request

Field Type Description
dismissed bool Marks a push as having been dismissed by the user, will cause any notifications for the push to be hidden if possible.

Example: true

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"dismissed":true}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/pushes/ujpah72o0sjAoRtnM0jc" rel="nofollow">https://api.pushbullet.com/v2/pushes/ujpah72o0sjAoRtnM0jc</a>

Response

{
  "active": true,
  "body": "Space Elevator, Mars Hyperloop, Space Model S (Model Space?)",
  "created": 1.412047948579029e+09,
  "direction": "self",
  "dismissed": true,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.412094382919271e+09,
  "receiver_email": "[email protected]",
  "receiver_email_normalized": "[email protected]",
  "receiver_iden": "ujpah72o0",
  "sender_email": "[email protected]",
  "sender_email_normalized": "[email protected]",
  "sender_iden": "ujpah72o0",
  "sender_name": "Elon Musk",
  "title": "Space Travel Ideas",
  "type": "note"
}

Delete a push.

Call

DELETE <a href="https://api.pushbullet.com/v2/pushes/%7Biden%7D" rel="nofollow">https://api.pushbullet.com/v2/pushes/{iden}</a>

Request

none

Response

none

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --request DELETE \
     <a href="https://api.pushbullet.com/v2/pushes/ujpah72o0sjAoRtnM0jc" rel="nofollow">https://api.pushbullet.com/v2/pushes/ujpah72o0sjAoRtnM0jc</a>

Response

{}

Delete all pushes belonging to the current user. This call is asynchronous, the pushes will be deleted after the call returns.

Call

DELETE <a href="https://api.pushbullet.com/v2/pushes" rel="nofollow">https://api.pushbullet.com/v2/pushes</a>

Request

none

Response

none

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --request DELETE \
     <a href="https://api.pushbullet.com/v2/pushes" rel="nofollow">https://api.pushbullet.com/v2/pushes</a>

Response

{}

Subscribe to channels to receive any updates pushed to that channel.

Channels can be created on the website. Each channel has a unique tag to identify it. When you push to a channel, all people subscribed to that channel will receive a push.
To push to a channel, use the channel_tag parameter on create-push
Field Type Description
iden string Unique identifier for this object

Example: "ujpah72o0sjAoRtnM0jc"

active bool false if the item has been deleted

Example: true

created float Creation time in floating point seconds (unix timestamp)

Example: 1.381092887398433e+09

modified float Last modified time in floating point seconds (unix timestamp)

Example: 1.441054560741007e+09

muted bool If true, notifications from this subscription will not be shown

Example: false

channel object Information about the channel that is being subscribed to
 ↳ iden string Unique identifier for the channel

Example: "ujpah72o0sjAoRtnM0jc"

 ↳ tag string Unique tag for this channel

Example: "elonmusknews"

 ↳ name string Name of the channel

Example: "Elon Musk News"

 ↳ description string Description of the channel

Example: "News about Elon Musk."

 ↳ image_url string Image for the channel

Example: "https://dl.pushbulletusercontent.com/StzRmwdkIe8gluBH3XoJ9HjRqjlUYSf4/musk.jpg"

 ↳ website_url string Link to a website for the channel

Example: "https://twitter.com/elonmusk"

Example

{
  "active": true,
  "channel": {
    "description": "News about Elon Musk.",
    "iden": "ujxPklLhvyKsjAvkMyTVh6",
    "image_url": "https://dl.pushbulletusercontent.com/StzRmwdkIe8gluBH3XoJ9HjRqjlUYSf4/musk.jpg",
    "name": "Elon Musk News",
    "tag": "elonmusknews"
  },
  "created": 1.412047948579029e+09,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.412047948579031e+09,
  "muted": false
}
Get a list of subscriptions belonging to the current user. If you have a large number of subscriptions, you will need to use Pagination.

Call

GET <a href="https://api.pushbullet.com/v2/subscriptions" rel="nofollow">https://api.pushbullet.com/v2/subscriptions</a>

Request

none

Response

Field Type Description
subscriptions []Subscription Array of Subscription objects ordered with most recently modified first

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     <a href="https://api.pushbullet.com/v2/subscriptions" rel="nofollow">https://api.pushbullet.com/v2/subscriptions</a>

Response

{
  "subscriptions": [
    {
      "active": true,
      "channel": {
        "description": "News about Elon Musk.",
        "iden": "ujxPklLhvyKsjAvkMyTVh6",
        "image_url": "https://dl.pushbulletusercontent.com/StzRmwdkIe8gluBH3XoJ9HjRqjlUYSf4/musk.jpg",
        "name": "Elon Musk News",
        "tag": "elonmusknews"
      },
      "created": 1.412047948579029e+09,
      "iden": "ujpah72o0sjAoRtnM0jc",
      "modified": 1.412047948579031e+09
    }
  ]
}

Call

POST <a href="https://api.pushbullet.com/v2/subscriptions" rel="nofollow">https://api.pushbullet.com/v2/subscriptions</a>

Request

Field Type Description
channel_tag string Unique tag for the channel to subscribe to

Example: "elonmusknews"

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"channel_tag":"elonmusknews"}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/subscriptions" rel="nofollow">https://api.pushbullet.com/v2/subscriptions</a>

Response

{
  "active": true,
  "channel": {
    "description": "News about Elon Musk.",
    "iden": "ujxPklLhvyKsjAvkMyTVh6",
    "image_url": "https://dl.pushbulletusercontent.com/StzRmwdkIe8gluBH3XoJ9HjRqjlUYSf4/musk.jpg",
    "name": "Elon Musk News",
    "tag": "elonmusknews"
  },
  "created": 1.412047948579029e+09,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.412047948579031e+09
}

Call

POST <a href="https://api.pushbullet.com/v2/subscriptions/%7Biden%7D" rel="nofollow">https://api.pushbullet.com/v2/subscriptions/{iden}</a>

Request

Field Type Description
muted bool true to mute the subscription, false to unmute it

Example: true

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"muted":true}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/subscriptions/ujpah72o0sjAoRtnM0jc" rel="nofollow">https://api.pushbullet.com/v2/subscriptions/ujpah72o0sjAoRtnM0jc</a>

Response

{
  "active": true,
  "channel": {
    "description": "News about Elon Musk.",
    "iden": "ujxPklLhvyKsjAvkMyTVh6",
    "image_url": "https://dl.pushbulletusercontent.com/StzRmwdkIe8gluBH3XoJ9HjRqjlUYSf4/musk.jpg",
    "name": "Elon Musk News",
    "tag": "elonmusknews"
  },
  "created": 1.412047948579029e+09,
  "iden": "ujpah72o0sjAoRtnM0jc",
  "modified": 1.412094382919271e+09,
  "muted": true
}

Unsubscribe from a channel.

Call

DELETE <a href="https://api.pushbullet.com/v2/subscriptions/%7Biden%7D" rel="nofollow">https://api.pushbullet.com/v2/subscriptions/{iden}</a>

Request

none

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --request DELETE \
     <a href="https://api.pushbullet.com/v2/subscriptions/ujpah72o0sjAoRtnM0jc" rel="nofollow">https://api.pushbullet.com/v2/subscriptions/ujpah72o0sjAoRtnM0jc</a>

Response

{}

Get information about a channel.

Call

GET <a href="https://api.pushbullet.com/v2/channel-info" rel="nofollow">https://api.pushbullet.com/v2/channel-info</a>

Request

Field Type Description
tag string Tag of the channel to get information for

Example: "elonmusknews"

no_recent_pushes bool Don't show recent pushes, defaults to false

Example: true

Response

Field Type Description
iden string Unique identifier for the channel

Example: "ujpah72o0sjAoRtnM0jc"

name string Name of the channel

Example: "Elon Musk News"

description string Description of the channel

Example: "News about Elon Musk"

image_url string Image to display for the channel

Example: "https://dl.pushbulletusercontent.com/StzRmwdkIe8gluBH3XoJ9HjRqjlUYSf4/musk.jpg"

subscriber_count int Number of subscribers to the channel

Example: 9382239

tag string Globally unique identifier for the channel, chosen by the channel creator

Example: "elonmusknews"

recent_pushes []Push Array of recent Push objects sent on the channel

Example

Request

curl --data-urlencode no_recent_pushes="true" \
     --data-urlencode tag="elonmusknews" \
     --get \
     <a href="https://api.pushbullet.com/v2/channel-info" rel="nofollow">https://api.pushbullet.com/v2/channel-info</a>

Response

{
  "active": true,
  "created": 1.412047948579029e+09,
  "description": "News about Elon Musk.",
  "iden": "ujxPklLhvyKsjAvkMyTVh6",
  "image_url": "https://dl.pushbulletusercontent.com/StzRmwdkIe8gluBH3XoJ9HjRqjlUYSf4/musk.jpg",
  "modified": 1.412047948579031e+09,
  "name": "Elon Musk News",
  "subscriber_count": 9.382239e+06,
  "tag": "elonmusknews"
}
Field Type Description
iden string Unique identifier for the current user

Example: "ujpah72o0"

created float Creation time in floating point seconds (unix timestamp)

Example: 1.381092887398433e+09

modified float Last modified time in floating point seconds (unix timestamp)

Example: 1.441054560741007e+09

email string Email address
email_normalized string Canonical email address
name string Full name if available

Example: "Elon Musk"

image_url string URL for image of user or placeholder image

Example: "https://static.pushbullet.com/missing-image/55a7dc-45"

max_upload_size int Maximum upload size in bytes

Example: 26214400

referred_count int Number of users referred by this user

Example: 2

referrer_iden string User iden for the user that referred the current user, if set

Example: "ujlxm0aiz2"

Example

{
  "created": 1.381092887398433e+09,
  "email": "[email protected]",
  "email_normalized": "[email protected]",
  "iden": "ujpah72o0",
  "image_url": "https://static.pushbullet.com/missing-image/55a7dc-45",
  "max_upload_size": 2.62144e+07,
  "modified": 1.441054560741007e+09,
  "name": "Elon Musk"
}

Gets the currently logged in user.

Call

GET <a href="https://api.pushbullet.com/v2/users/me" rel="nofollow">https://api.pushbullet.com/v2/users/me</a>

Request

none

Response

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     <a href="https://api.pushbullet.com/v2/users/me" rel="nofollow">https://api.pushbullet.com/v2/users/me</a>

Response

{
  "created": 1.381092887398433e+09,
  "email": "[email protected]",
  "email_normalized": "[email protected]",
  "iden": "ujpah72o0",
  "image_url": "https://static.pushbullet.com/missing-image/55a7dc-45",
  "max_upload_size": 2.62144e+07,
  "modified": 1.441054560741007e+09,
  "name": "Elon Musk"
}
To upload a file you need to call upload-request with the file name and type. After you get an upload_url from the response, you can upload the file contents using multipart/form-data encoding.
EXAMPLE REQUEST
curl -i -X POST <a href="https://upload.pushbullet.com/upload-legacy/a5e1776d2566a6b16032958697288df4" rel="nofollow">https://upload.pushbullet.com/upload-legacy/a5e1776d2566a6b16032958697288df4</a> \
  -F [email protected]
EXAMPLE RESPONSE
HTTP/1.1 204 No Content
After the request completes, the file will be available at the file_url from the upload-request response.

Request authorization to upload a file.

Call

POST <a href="https://api.pushbullet.com/v2/upload-request" rel="nofollow">https://api.pushbullet.com/v2/upload-request</a>

Request

Field Type Description
file_name string The name of the file you want to upload

Example: "cat.jpg"

file_type string The MIME type of the file

Example: "image/jpeg"

Response

Field Type Description
file_name string The file name that will be used for the file (may be truncated from the original file_name.
file_type string The file type that will be used for the file (may be different from the one provided to upload-request.
file_url string The URL where the file will be available after it is uploaded.
upload_url string The URL to POST the file to. The file must be posted using multipart/form-data encoding.
data object DEPRECATED

Example

Request

curl --header 'Access-Token: <your_access_token_here>' \
     --header 'Content-Type: application/json' \
     --data-binary '{"file_name":"cat.jpg","file_type":"image/jpeg"}' \
     --request POST \
     <a href="https://api.pushbullet.com/v2/upload-request" rel="nofollow">https://api.pushbullet.com/v2/upload-request</a>

Response

{
  "file_name": "cat.jpg",
  "file_type": "image/jpeg",
  "file_url": "https://dl.pushbulletusercontent.com/034f197bc6c37cac3cc03542659d458b/cat.jpg",
  "upload_url": "https://upload.pushbullet.com/upload-legacy/a5e1776d2566a6b16032958697288df4"
}

• Removed address and list pushes which have been deprecated for forever.

• Fixed curl link for windows.

• Removed Android Extension section, as this has been replaced with Android Wear integration, the Android Extension is no longer needed.

• New style for docs.

• Removed Contacts calls as the official apps no longer user Contacts. These have been replaced with the Chat objects.

• Added a run button to execute javascript snippets.

• Added new auth header Access-Token to Requests, removed mention of older auth headers.
• Updated Resizing Images to mention new resizing method and remove old ones.




March 12, 2016 at 02:54PM
Read the whole story
Share this story
Delete

特朗普越来越少儿不宜美国父母很难堪

1 Share

ELECTION 2016

The Parent-Child Discussion That So Many Dread: Donald Trump

By SARAH LYALL March 11, 2016

美国大选

特朗普越来越“少儿不宜”,美国父母很难堪

SARAH LYALL 2016年3月11日

It was mortifying enough when the Republican debate last week introduced the question of whether it was appropriate for one presidential candidate to accuse another of wetting his pants. But the final straw for Gary Goyette and Andrea Todd, who were watching at home in Sacramento with their 10-year-old son, was Donald J. Trump’s jarring, out-of-left-field boast about his sexual endowment.

上周的共和党辩论上提出了一个问题:一个总统候选人指责另一个候选人尿裤子是否合适。这已经够丢脸的了,但是对于在萨克拉门托家中和10岁的儿子一起看电视辩论的加里·格伊特(Gary Goyette)和安德莉亚·托德(Andrea Todd)来说,最后突破他们底限的是,唐纳德·特朗普(Donald J. Trump)令人厌恶而又出人意料地吹嘘起自己的性能力来。

“We were just incredulous,” Ms. Todd said, when Mr. Trump leeringly declared that there was “no problem” with that part of his anatomy. She and her husband looked at each other, she recalled, and then looked at their son. “Gary said, ‘Tommy, you’ve got to leave — you’ve got to get out of here.’ And Tommy actually got up and ran out of the room.”

“这简直难以置信,”托德说。当时特朗普正狎亵地宣称,他身体的那一部分“没问题”。她回忆说,当时她和丈夫对视了一眼,然后看着他们的儿子。“加里说,‘汤米,你得离开——你得离开这里。’然后汤米就起身跑出了房间。”

Many unforeseeable things have happened so far in the raucous Republican presidential race. But the 2016 election — with its rudeness, crudeness, bluster and bullying — has also presented adults with an unexpected, unpleasant dilemma: How on earth do they explain Donald Trump to children?

迄今为止,在喧闹的共和党总统竞选过程中已经出现过许多无法预料的事。但是,充斥着粗鲁、低俗、咆哮和欺凌的2016年选举,还是意外地给成人提出了让他们如坐针毡的难题:究竟该如何向孩子们解释唐纳德·特朗普?

米肖夫妇和两个儿子住在新泽西州梅普尔伍德。托马斯(左)8岁,马库斯13岁。米肖说托马斯告诉他,他担心如果唐纳德·特朗普当选总统,就会“把种族主义带回来”。

Bryan Anselm for The New York Times

米肖夫妇和两个儿子住在新泽西州梅普尔伍德。托马斯(左)8岁,马库斯13岁。米肖说托马斯告诉他,他担心如果唐纳德·特朗普当选总统,就会“把种族主义带回来”。

“Quite frankly, it’s been quite embarrassing when I have an 11-year-old who is better behaved and more polite than some people who are the potential next leaders of our country,” said Maury Peterson, who runs Parenting Journey, a nonprofit group in Somerville, Mass., that provides support for families. “This name-calling and making fun of people is basically the opposite of what he’s been taught at home and at school.”

“坦率地说,情况相当尴尬,我家11岁小孩的举止,比有望成为我国下一任领导者的人更得体,更有礼貌。这种辱骂和取笑,和孩子在家里、在学校学到的东西基本上正好相反。”马萨诸塞萨默维尔的莫里·彼得森(Maury Peterson)说。她管理着一个名为“育儿之旅”的非营利性组织,为家庭提供帮助。

For some children, Mr. Trump’s message has filtered down in extremely upsetting, possibly dangerous, ways. Social media has buzzed with parents relaying their children’s fears that they or their friends would be deported, walled in or walled out if Mr. Trump becomes president.

有些孩子所听到的特朗普的言论,可能经过了令人极端不安、甚至可能有危险的层层过滤。孩子们担心,如果特朗普成为总统,自己或朋友就会被驱逐出境,被隔在墙内或是墙外;父母们纷纷在社交媒体上转达这种担心。

Jon Michaud of Maplewood, N.J., who is white and whose wife is Dominican, wrote on Facebook about a conversation he had with one of his two sons: “So if Donald Trump becomes president, he’s going to bring racism back,” he said his 8-year-old had told him. “That means Marcus, Mommy and I will be separated from you because we have darker skin than you do, right?”

乔恩·米肖(Jon Michaud)是一个白人,妻子来自多米尼加,他们与两个儿子住在新泽西州梅普尔伍德。米肖在Facebook上记录了自己与其中一个儿子的对话:“那如果唐纳德·特朗普当了总统,他就会把种族主义带回来,”他说8岁的儿子告诉他:“这意味着马库斯、妈妈和我就会和你分开,因为我们的肤色比你的深,对不对?”

Speaking on MSNBC’s “Morning Joe” on Wednesday, Cokie Roberts put the question to the candidate himself. “There’ve been incidents of white children pointing to their darker-skinned classmates and saying, ‘You’ll be deported when Donald Trump is president,’” she said. “There’ve been incidents of white kids at basketball games holding up signs to teams which have Hispanic kids on them, saying, ‘We’re going to build a wall to keep you out.’”

在MSNBC电视台《早安,乔》(Morning Joe)本周三的节目中,柯奇·罗伯茨(Cokie Roberts)向特朗普本人提出了这个问题:“已经有一些白人孩子指着深肤色同学说,‘唐纳德·特朗普当了总统,你就会被驱逐出境,’在篮球赛中,已经有白人孩子举起了针对有西裔队员球队的标语,‘我们要建起一堵墙,把你挡在外面。’”

“Are you proud of that?” Ms. Roberts asked. “Is that something you’ve done in American political and social discourse that you’re proud of?”

“你为之骄傲吗?”罗伯茨问道。“你为你对美国政治及社会话语产生的影响感到骄傲吗?”

Mr. Trump replied that he had no knowledge of such reports. “I think your question is a very nasty question,” he said, “and I’m not proud of it because I didn’t even hear of it, O.K.?”

特朗普回答称,他不知道此类报道。“我觉得这是个很恶心的问题,”他说。“我没有为此感到骄傲,因为我甚至没听说过,好吗?”

As much as they might want to, parents and educators cannot keep their children insulated from news about Mr. Trump.

家长及教育工作者无法使孩子远离有关特朗普的新闻,尽管他们可能非常希望这么做。

“He’s omnipresent. It’s going to come up, so you better be prepared,” said Carolyn Lee, a substitute kindergarten teacher in the Hawaii public school system.

“他无处不在,这种情况将会出现,所以最好做好准备,”夏威夷公立学校系统幼儿园代课老师卡洛琳·利(Carolyn Lee)说。

With very young children, she advised that parents remain calm and refrain from retaliatory anti-Trump name-calling. 

她建议家里有幼小儿童的家长保持冷静,不要有报复性的反特朗普咒骂。

In Los Angeles, Andy Behrman, a single parent of two girls, 8 and 10, said that his daughters continually accused Mr. Trump of violating “the double v’s,” a reference to their school’s “virtues and values” program.

 在洛杉矶,带着8岁和10岁的女儿生活的单身父亲安迪·贝尔曼(Andy Behrman)表示,女儿们不断指责特朗普违背了“两个V”,她们指的是学校的“美德及价值观”项目。

“They’re not picking up on the innuendoes of his hands, they’re not catching on to the genital issue,” Mr. Behrman said. “But they’re catching on to the fact that Trump, Rubio and Cruz are all talking at the same time, which they’ve learned doesn’t make sense. It’s not polite and it doesn’t allow anyone to voice their own opinion.”

“她们不理解有关他的手的讨论影射了什么,也不明白生殖器的问题,”贝尔曼说。“但她们知道特朗普、卢比奥及克鲁兹在同时讲话,她们之前了解到这种行为不可取。这不礼貌,不允许任何人发表自己的意见。”

Parents who support Mr. Trump disagree, of course. They say that his authenticity and his refusal to pander to his critics are more important than the words he uses. And they ask why America’s children are so sensitive that they cannot be exposed to robust views, forcefully expressed.

当然支持特朗普的家长不同意这一说法。他们表示,特朗普非常真实,拒绝迎合针对他的批评者,这比他使用什么词更重要。他们问道,为何美国儿童如此脆弱,以至于不能听到那些强力表达的有力观点。

“This is not about him being rude to people randomly,” said Jeremy Diamond, a marketing executive who lives in Manhattan and has a son, 12, and a daughter, 15. “He shows passion and aggression, and that he’s going to fight for his point of view.”

“这不是他随便粗鲁待人的问题,”曼哈顿的销售主管杰里米·戴蒙德(Jeremy Diamond)说。“他展示出了激情和攻击性,他会为了自己的观点而斗争。”戴蒙德有一个12岁的儿子和15岁的女儿。

He said he was “confident in the integrity and behavior and values” of his children, both of whom have been impressed by Mr. Trump’s take-no-prisoners approach, which Mr. Diamond called “strategic aggression.”

他表示,他对孩子们“的正直、行为及价值观有信心”,他们对特朗普毫无顾忌的风格印象深刻,戴蒙德称之为“战略侵犯”。

“My son said, ‘Daddy, he just wants to show that he is stronger than the other candidates and that he’s not going to get pushed around,’” he said.

他表示,“我儿子说,‘爸爸,他只是想表现出他比其他候选人强大,他不会被人摆布。’”

Ruth Ben-Ghiat, a professor of history and Italian studies at New York University, who has a 15-year-old daughter and has written about Mr. Trump for <a href="http://CNN.com" rel="nofollow">CNN.com</a>, said that for older children, it helps to place Mr. Trump in the context of a society driven by celebrity and social media.

纽约大学(New York University)历史学及意大利研究教授露丝·本-吉亚(Ruth Ben-Ghiat)表示,对于年纪稍大点的孩子来说,将特朗普置于一个由名人及社交媒体驱动的社会环境会有所帮助。本-吉亚为CNN.com撰写了有关特朗普的文章,她有一个15岁的女儿。

“My daughter asks, ‘Why are you so obsessed with Trump? So what if he did a retweet?’” Ms. Ben-Ghiat said. “But we can tell our children that he’s a product of our branding culture and our selfie culture and our attraction to reality-show television, where the behavior is so brutal.”

“我女儿问我,‘你为何如此迷恋特朗普?他转了一条推又能怎么样呢?’”本-吉亚说。“但我们可以告诉孩子们,他是我们的品牌文化、自拍文化及电视真人秀热潮的产物,真人秀中的行为都很粗鲁。”

The ubiquity of Mr. Trump, she said, provides a useful opportunity for children to examine their own preoccupations.

她表示,特朗普无处不在的现象为孩子们提供了一个审视自身偏见的机会。

“They can learn to look beyond flash and glamour, to be skeptical of the power of messaging and branding, but also to learn that it’s important that each one of us speak out and use our right to vote,” Ms. Ben-Ghiat said. “And to listen to the other side even if you don’t agree with them.”

“他们可以学着思考那些光鲜外表之下的东西,怀疑信息传递及品牌化的力量,还能学到每个人直抒己见、行使投票权是非常重要的,”本-吉亚说。“学着倾听另一方的意见,即便你不同意他们的观点。”

本文内容版权归纽约时报公司所有,任何单位及个人未经许可,不得擅自转载或翻译。

翻译:土土、许欣

本文内容版权归纽约时报公司所有,任何单位及个人未经许可,不得擅自转载或翻译。





March 12, 2016 at 02:48PM
Read the whole story
Share this story
Delete
Next Page of Stories