2012年6月2日

Google 將搶先WWDC 於6 月6 日發布新一代的Google Maps 三維地圖服務

Google給各大媒體發去了邀請函,邀請他們參加於6月6日上午9:30開始的Google Maps發布會,屆時Google Maps和Google Earth副總裁Brian McClendon將發布新版Google Maps,並分享其背後的故事。

邀請函上暗示說要展示Google Maps的新維度,也就應該是全新的三維地圖服務吧。

之前有傳言說6月11日開幕的WWDC 2012上將展示iOS 6系統,其中就包含棄用Google Maps的全新三維地圖應用,看起來Google也知道這個事兒了,於是決定先發製人預覽他們的新地圖服務,以便不會讓大家覺得Google Maps又在山寨iOS 6裡的新地圖應用了?

看起來Google這次發布會完全就是針對WWDC的,匆忙上陣,而且只是預覽而已,消費者不會馬上就可以用到。真的有必要這麼對著幹嗎?

Via 9to5google

Google 發布World Wonders 項目,探索世界遺產

Google今天發布了World Wonders Project,幫助你探索全球的遺產,這裡整合了Google街景、Google Maps地圖和Google Earth裡的3D建築,總共收錄有123個世界歷史遺產。

除了 ​​著名的巨石陣龐貝古城,你還可以探索到很多不知名但同樣讓人驚異的歷史遺產,比如歷史悠久的村落白川鄉和五個山

繼續觀看官方介紹視頻:


Via GEB

2012年6月1日

Facebook 不再推薦使用Chrome 瀏覽器,Opera 取而代之

上周有傳言說Facebook欲收購Opera提升自己在移動領域的控制力,現在這個傳言越來越像是真的了,Facebook現在居然不再推薦使用Chrome瀏覽器而是用Opera取而代之,要知道Chrome已經是全球第一流行的瀏覽器了啊。

Apple的Safari其實也完全支持Facebook,但他們也不推薦給用戶,看來Facebook跟Apple和Google結的梁子都不淺啊?

Via BGR

Google 向ICANN 申請增加.Google、.Docs、.YouTube 和.LOL 域名

今天ICANN結束了對頂級域名的申請窗口,他們將在未來兩周里陸續公佈申請新增的域名列表,但Google今天自己就先行透露了自己申請的域名,包括:
  • 他們自己的域名,比如.Google
  • 跟他們核心業務有關的域名,比如.Docs
  • 可改進用戶體驗的域名,比如.YouTube,可方便用戶直接登錄某個YouTube頻道或是某類視頻
  • 有趣而有潛在創造力的域名,比如.LOL

現在ICANN希望每年能征集到300到1000個新的頂級域名,每申請一個域名需要支付185,000美元的費用。

如果.LOL這種搞笑域名都被批准的話,我認為還應該增加.233域名。

Via TC

Google+ Events 洩露,與Google Calendar 整合的活動功能

儘管Google+ Event還沒有發布,但已經有用戶在Google Calendar裡看到了它的介紹鏈接,很顯然這個Event功能是與Google Calendar整合的,也就是將日程表也社交化了。Google+ Event可以做到:
  • 為你圈子裡的好友創建事件,他們都可以了解到你的事件和日程
  • 為事件添加照片和視頻
  • 提前設置好Hangouts的時間,好​​讓大家知道什麼時候等著看你耍寶
  • 可在事件到來之前進行討論

其實就等於將Google Calendar的分享功能延伸到了Google+裡,讓你的好友也可以看到,並可針對某個未到來的事件進行討論和留言。

Via TNW

Chrome 實驗標籤頁堆疊功能

你在Chrome裡打開的標籤頁越多,每個標籤頁的寬度就越小,最後乾脆看不到每個標籤頁的標題了。於是這個Chrome里新增的標籤頁堆疊功能可以讓你將暫時不需要的標籤頁堆疊到一起,省出更多的空間。

下載最新版的Chromium或是Chrome Canary都可體驗到堆疊功能,不過它目前還作為實驗項目出現,必須進入chrome:flags,打開其中的Tab Stacking功能並重啟瀏覽器才可以。之後再多打開幾個標籤頁即可看到左側的標籤頁堆疊到一起了。

Via Chrome Story

2012年5月31日

你現在可以截取部分視頻片段來組成自己的YouTube 播放列表了

將同一類視頻做成播放列表可以讓別人全面的了解某個事情或是專題,但也許每個視頻裡有好多重複的內容,那樣連續看播放列表的時候就太浪費時間了。於是今天YouTube開始允許你截取每個視頻的片段,把他們拼成一個播放列表,就好像自己做剪輯師似的。

只需要在YouTube Editor裡選擇視頻的開始點和結束點即可,非常方面而直觀,不過每段視頻裡似乎只能截取一個片段,而不能是多個片段。

這個新功能將在未來1、2天裡上線。

Via TNW

Google+ 新增Local 本地商戶專頁,全面整合Zagat 用戶評價信息

今天Google+左側又多出了一個專頁:Local,也就是本地商戶。進入之後可看到你周邊的商戶信息,不過現在有一個問題是,不翻越萬里長城的話上不去Google+,而翻越了萬里長城之後,Google+顯示的位置都是錯了,它又不讓你自定義位置……

所有商戶信息都來自於Google之前收購的Zagat用戶評論數據庫,其實Zagat的數據也開始整合進了Google Places的商戶頁面:


不過Zagat一直就沒有景德鎮的用戶評價信息,所以這個改變對我們查找景德鎮的商戶沒什麼意義。

繼續觀看兩段官方介紹視頻:

Google+ Local介紹:


Google+ Local裡的Zagat用戶評價信息介紹:


Via TNW

Sergey Brin 繼續上電視台秀Google 眼鏡,透露其觸摸和手勢操作方式

自己得瑟還不夠,這次Sergey Brin不僅戴上了自己的Google眼鏡,還帶上了自己的老婆Anne Wojcicki,一同出席California Lieutenant Governor Gavin Newsom的Current TV節目,不過這次得擠出了點硬貨,那就是Google眼鏡的操作方式:觸摸眼鏡腿兒。Sergey Brin甚至大方的叫主持人Newsom試戴了一下:


在視頻裡,Brin談到這個眼鏡的右側腿兒上有一個觸摸區域,只要用手在這個區域來回滑動即可在拍攝的照片中來回切換(顯然通過左右晃悠腦袋來切換圖片的顯示太2了)。Sergey Brin自己先是摸了一下鼻子,眼鏡就在同時拍照了(看來眼鏡內置的攝像頭不光具有偷拍能力,也在時刻捕捉使用者的動作以進行互動)。然後他將眼鏡給主持人Newsom帶上,並親自示範用手觸摸右側眼鏡腿兒來切換到之前拍攝的照片,Newsom當時就被震驚了。

繼續觀看採訪視頻:

2012年5月30日

劍走偏鋒的Native Client

不知不覺,Google已經正式推出其Native Client (NaCl)過去約7個月之久。而目前國內似乎還沒有多少關於NaCl的資料,所以在這裡面向Web開發者做一下簡單的介紹,希望能夠起到一個拋磚引玉的效果。

本文的所有代碼均來自於https://developers.google.com/native-client/devguide/tutorial,如果您對其中的任何技術細節存在疑問,請以原文為準。

何謂NaCl

NaCl是一項能讓C/C++代碼運行在瀏覽器當中的技術。這是一個最通俗的說法,但不夠精確。嚴格來說,NaCl技術在理論上能夠實現任何編譯型語言都在其之上運行。

但是目前由於技術上的原因,NaCl還做不到任何語言任何平台的編譯型語言支持。

因為NaCl所憧憬的實際是LLVM技術,LLVM技術的要點即在於能將編譯型語言轉化為一個統一的中間語言,NaCl通過對這個中間語言的執行,即可達成任何編譯型語言的運行。換句話說,NaCl實際上希望搭建一個虛擬機。

不過LLVM現在還不夠成熟,NaCl不得不先使用GNU的編譯套件,使用LLVM技術的版本被稱為了PNaCl,目前還沒有正式推出。同時也因為這個原因,ARM架構沒能正式支持。

為什麼NaCl

在開發層面上,NaCl希望解決一個問題:JavaScript的低效率。當然,從經營策略上來說,Google可能還希望籍此將桌面領域的成熟軟件快速移植到其Chrome OS當中,不過這不是我們討論的重點。

JavaScript畢竟是一門解釋型語言,只有當瀏覽器執行到代碼的時刻才能夠看到代碼,因此在執行優化上力度非常小。

但是Web應用發展至今,效率已經必須拿到桌面上考慮,如果你還想在瀏覽器裡面看到更多優質的遊戲的話。

有關限制
  • 缺乏能夠切合的IDE
  • 不支持硬件異常
  • 不支持創建子進程
  • 不支持原生TCP/UDP操作(但已提供了websocket支持)
  • 不支持同步I/O
  • 不支持內存剩餘查詢
  • 內聯彙編代碼必須通過NaCl驗證
  • NaCl的Pepper API必須通過主線程使用

如何使用

上面那些對於行動主義來說其實都是P,真正需要聚焦的還是如何使用。

NaCl的典型項目由三個部分組成:
網頁(*.html)。這裡所指的網頁是一個泛指,它包括JS代碼、CSS樣式表已經HTML代碼。
NaCl模塊(*.c;*.cc)。這是C/C++代碼的文件。
清單(*.nmf)。這份清單類似於Chrome Extension的清單,主要用於指明在不同架構的機器上調用什麼模塊。

在真正開始之前,我們還需要安裝一個NaCl的SDK。這個SDK當中主要包含了NaCl的模塊編譯工具鏈。大家可以從這裡下載:https://developers.google.com/native-client/sdk/download

安裝之前,確保一下機器上有一個可用的Python 2.7,並加入到環境變量當中。

而SDK的安裝則相當簡單,只需要使用naclsdk update命令即可。

下面,創建一個名為hello_tutorial的目錄,我們來搭建一個簡單的demo。

網頁
 <script type="text/javascript">
    hello_tutorialModule = null;  // Global application object.
    statusText = 'NO-STATUS';

    // Indicate load success.
    function moduleDidLoad() {
      hello_tutorialModule = document.getElementById('hello_tutorial');
      updateStatus('SUCCESS');
    }

    // The 'message' event handler.  This handler is fired when the NaCl module
    // posts a message to the browser by calling PPB_Messaging.PostMessage()
    // (in C) or pp::Instance.PostMessage() (in C++).  This implementation
    // simply displays the content of the message in an alert panel.
    function handleMessage(message_event) {
      alert(message_event.data);
    }

    // If the page loads before the Native Client module loads, then set the
    // status message indicating that the module is still loading.  Otherwise,
    // do not change the status message.
    function pageDidLoad() {
      if (hello_tutorialModule == null) {
        updateStatus('LOADING...');
      } else {
        // It's possible that the Native Client module onload event fired
        // before the page's onload event.  In this case, the status message
        // will reflect 'SUCCESS', but won't be displayed.  This call will
        // display the current message.
        updateStatus();
      }
    }

    // Set the global status message.  If the element with id 'statusField'
    // exists, then set its HTML to the status message as well.
    // opt_message The message test.  If this is null or undefined, then
    // attempt to set the element with id 'statusField' to the value of
    // |statusText|.
    function updateStatus(opt_message) {
      if (opt_message)
        statusText = opt_message;
      var statusField = document.getElementById('status_field');
      if (statusField) {
        statusField.innerHTML = statusText;
      }
    }
  </script>
</head>
<body onload="pageDidLoad()">
<h1>Native Client Module hello_tutorial</h1>
<p>
  <!-- Load the published .nexe.  This includes the 'nacl' attribute which
  shows how to load multi-architecture modules.  Each entry in the "nexes"
  object in the .nmf manifest file is a key-value pair: the key is the
  instruction set architecture ('x86-32', 'x86-64', etc.); the value is a URL
  for the desired NaCl module.
  To load the debug versions of your .nexes, set the 'nacl' attribute to the
  _dbg.nmf version of the manifest file.

  Note: Since this NaCl module does not use any real-estate in the browser,
  it's width and height are set to 0.

  Note: The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
  and a 'message' event listener attached.  This wrapping method is used
  instead of attaching the event listeners directly to the <EMBED> element to
  ensure that the listeners are active before the NaCl module 'load' event
  fires.  This also allows you to use PPB_Messaging.PostMessage() (in C) or
  pp::Instance.PostMessage() (in C++) from within the initialization code in
  your NaCl module.
  -->
  <div id="listener">
    <script type="text/javascript">
      var listener = document.getElementById('listener');
      listener.addEventListener('load', moduleDidLoad, true);
      listener.addEventListener('message', handleMessage, true);
    </script>

    <embed name="nacl_module"
       id="hello_tutorial"
       width=0 height=0
       src="hello_tutorial.nmf"
       type="application/x-nacl" />
  </div>
</p>
<h2>Status</h2>
<div id="status_field">NO-STATUS</div>
</body>
</html>

NaCl模塊
/// @file hello_tutorial.cc
/// This example demonstrates loading, running and scripting a very simple NaCl
/// module.  To load the NaCl module, the browser first looks for the
/// CreateModule() factory method (at the end of this file).  It calls
/// CreateModule() once to load the module code from your .nexe.  After the
/// .nexe code is loaded, CreateModule() is not called again.
///
/// Once the .nexe code is loaded, the browser than calls the CreateInstance()
/// method on the object returned by CreateModule().  It calls CreateInstance()
/// each time it encounters an <embed> tag that references your NaCl module.
///
/// The browser can talk to your NaCl module via the postMessage() Javascript
/// function.  When you call postMessage() on your NaCl module from the browser,
/// this becomes a call to the HandleMessage() method of your pp::Instance
/// subclass.  You can send messages back to the browser by calling the
/// PostMessage() method on your pp::Instance.  Note that these two methods
/// (postMessage() in Javascript and PostMessage() in C++) are asynchronous.
/// This means they return immediately - there is no waiting for the message
/// to be handled.  This has implications in your program design, particularly
/// when mutating property values that are exposed to both the browser and the
/// NaCl module.
#include <cstdio>
#include <string>
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
/// The Instance class.  One of these exists for each instance of your NaCl
/// module on the web page.  The browser will ask the Module object to create
/// a new Instance for each occurence of the <embed> tag that has these
/// attributes:
///     type="application/x-nacl"
///     src="hello_tutorial.nmf"
/// To communicate with the browser, you must override HandleMessage() for
/// receiving messages from the borwser, and use PostMessage() to send messages
/// back to the browser.  Note that this interface is entirely asynchronous.
class hello_tutorialInstance : public pp::Instance {
 public:
  /// The constructor creates the plugin-side instance.
  /// @param[in] instance the handle to the browser-side plugin instance.
  explicit hello_tutorialInstance(PP_Instance instance) : pp::Instance(instance)
  {}
  virtual ~hello_tutorialInstance() {}

  /// Handler for messages coming in from the browser via postMessage().  The
  /// @a var_message can contain anything: a JSON string; a string that encodes
  /// method names and arguments; etc.  For example, you could use
  /// JSON.stringify in the browser to create a message that contains a method
  /// name and some parameters, something like this:
  ///   var json_message = JSON.stringify({ "myMethod" : "3.14159" });
  ///   nacl_module.postMessage(json_message);
  /// On receipt of this message in @a var_message, you could parse the JSON to
  /// retrieve the method name, match it to a function call, and then call it
  /// with the parameter.
  /// @param[in] var_message The message posted by the browser.
  virtual void HandleMessage(const pp::Var& var_message) {
    // TODO(sdk_user): 1. Make this function handle the incoming message.
  }
};
/// The Module class.  The browser calls the CreateInstance() method to create
/// an instance of your NaCl module on the web page.  The browser creates a new
/// instance for each <embed> tag with type="application/x-nacl".
class hello_tutorialModule : public pp::Module {
 public:
  hello_tutorialModule() : pp::Module() {}
  virtual ~hello_tutorialModule() {}

  /// Create and return a hello_tutorialInstance object.
  /// @param[in] instance The browser-side instance.
  /// @return the plugin-side instance.
  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new hello_tutorialInstance(instance);
  }
};
namespace pp {
/// Factory function called by the browser when the module is first loaded.
/// The browser keeps a singleton of this module.  It calls the
/// CreateInstance() method on the object you return to make instances.  There
/// is one instance per <embed> tag on the page.  This is the main binding
/// point for your NaCl module with the browser.
Module* CreateModule() {
  return new hello_tutorialModule();
}
}  // namespace pp

Makefile

Makefile是C\C++編譯指令的存放文件,這份文件將指引編譯器、鏈接器如何工作。因為我們現在所處情況特殊,所以Makefile需要自己編寫。 
# Copyright (c) 2012 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# GNU Make based build file.  For details on GNU Make see:
# http://www.gnu.org/software/make/manual/make.html
#
#
# Project information
#
# These variables store project specific settings for the project name
# build flags, files to copy or install. In the examples it is typically
# only the list of sources and project name that will actually change and
# the rest of the makefile is boilerplate for defining build rules.
#
PROJECT:=hello_tutorial
LDFLAGS:=-lppapi_cpp -lppapi
CXX_SOURCES:=$(PROJECT).cc

#
# Get pepper directory for toolchain and includes.
#
# If NACL_SDK_ROOT is not set, then assume it can be found a two directories up,
# from the default example directory location.
#
THIS_MAKEFILE:=$(abspath $(lastword $(MAKEFILE_LIST)))
NACL_SDK_ROOT?=$(abspath $(dir $(THIS_MAKEFILE))../..)
# Project Build flags
WARNINGS:=-Wno-long-long -Wall -Wswitch-enum -pedantic -Werror
CXXFLAGS:=-pthread -std=gnu++98 $(WARNINGS)
#
# Compute tool paths
#
#
OSNAME:=$(shell python $(NACL_SDK_ROOT)/tools/getos.py)
TC_PATH:=$(abspath $(NACL_SDK_ROOT)/toolchain/$(OSNAME)_x86_newlib)
CXX:=$(TC_PATH)/bin/i686-nacl-g++
#
# Disable DOS PATH warning when using Cygwin based tools Windows
#
CYGWIN ?= nodosfilewarningexport CYGWIN

# Declare the ALL target first, to make the 'all' target the default build
all: $(PROJECT)_x86_32.nexe $(PROJECT)_x86_64.nexe
# Define 32 bit compile and link rules for main application
x86_32_OBJS:=$(patsubst %.cc,%_32.o,$(CXX_SOURCES))
$(x86_32_OBJS) : %_32.o : %.cc $(THIS_MAKE)
        $(CXX) -o $@ -c $< -m32 -O0 -g $(CXXFLAGS)

$(PROJECT)_x86_32.nexe : $(x86_32_OBJS)
        $(CXX) -o $@ $^ -m32 -O0 -g $(CXXFLAGS) $(LDFLAGS)
# Define 64 bit compile and link rules for C++ sources
x86_64_OBJS:=$(patsubst %.cc,%_64.o,$(CXX_SOURCES))
$(x86_64_OBJS) : %_64.o : %.cc $(THIS_MAKE)
        $(CXX) -o $@ -c $< -m64 -O0 -g $(CXXFLAGS)

$(PROJECT)_x86_64.nexe : $(x86_64_OBJS)
        $(CXX) -o $@ $^ -m64 -O0 -g $(CXXFLAGS) $(LDFLAGS)
# Define a phony rule so it always runs, to build nexe and start up server.
.PHONY: RUN 
RUN: all
  python ../httpd.py

清單文件

清單中指出了不同架構所使用的模塊。
{
  "program": {
    "x86-64": {"url": "hello_tutorial_x86_64.nexe"},
    "x86-32": {"url": "hello_tutorial_x86_32.nexe"}
  }
}

所有這些文件齊全之後,只需要make即可完成自動編譯。

如何運行

在編譯之後,雙擊html頁面打開其實並不會載入模塊運行,這是由於瀏覽器的訪問域規則不允許直接在用戶的本地讀取文件。因此,我們需要讓本機成為一個服務器,以遠程服務器的身份來讀取模塊最終傳送給瀏覽器。

這很容易,SDK當中已經包含了提供http服務的python腳本:
cd pepper_18/examples/hello_tutorial
make

這樣,http://localhost:5103就成為了我們的服務器地址。注意,http服務的根目錄的位置位於examples目錄。

現在,我們在瀏覽器的chrome://flags和chrome://plugins頁面中打開NaCl的幾個相關選項,就可以成功運行了。

Via NewHTML

Google 發布第一段Google 眼鏡的使用說明視頻

Google今天發布了一段叫做Glass How-to: Getting Started的視頻,入門性的介紹了Google眼鏡的使用方式,這應該是眾多視頻中的一個,接下來估計還會有更深入的視頻吧? 這段視頻介紹了你如何觀看到棱鏡屏幕,使用右側眼鏡腿兒觸摸區域操作眼鏡的基本...