2011年11月16日 星期三

[Java] Object Initialization - (2)

Initialization and inheritance
  • When an object is initialized, all the instance variables defined in the object's class must be set to proper initial values.
  • When an object is created, the Java virtual machine allocates enough space for all the object's instance variables, which include all fields defined in the object's class and in all its superclasses.
    • The data that must be allocated on the heap
    • The actual manner of representing objects on the heap is an implementation detail of each particular Java virtual machine.
  • Object will have no fields in any given Java platform implementation.
    • Because Object is the superclass of all other objects, any fields declared in Object must be allocated for every object used by every Java program.

A note on the word "inherit"
  • A class's members are the fields and methods that
    • Actually declared in the class
    • Inherits from superclasses.
      • Only inherits accessible members of its superclasses. (the subclass doesn't override or hide those accessible members.)

Initializing fields in superclasses
  • Unlike methods, constructors are never inherited.
  • If you don't explicitly declare a constructor in a class
    • Will not inherit a constructor from its direct superclass.
    • The compiler will generate a default constructor
      • This is because a superclass constructor can't initialize fields in the subclass. A subclass must have its own constructor to initialize its own instance variables.
    • => Every class has at least one method responsible for initializing the class variables explicitly declared in that class.
  • To fully initialize an object, the Java virtual machine must invoke (at least) one instance initialization method from each class along the object's inheritance path.

Order of initialization
  • The fields of an object are initialized
    • Starting with the fields declared in the base class.
    • Ending with the fields declared in the object's class.
  • The order of initialization of fields would be:
    • Object's fields (this will be quick, because there are none)
    • ParentClass's fields
    • ChildClass's fields
  • This base-class-first order
    • Aims to prevent fields from being used before they are initialized to their proper (not default) values.
    • In a child constructor or initializer
      • You can safely use a superclass's field directly
      • Call a method that uses a superclass's field.
    • By the time the code in your child constructor or initializer is executed
      • You can be certain that the fields declared in any superclasses have already been properly initialized.

The structure of <init>

  • How does Java ensure the correct ordering of initialization?
    • The Java compiler generates the instance initialization method.
    • Into each <init> method, the compiler can place three kinds of code:
      • An invocation of another constructor
      • Instance variable initializers
      • The constructor body
    • The order in which the compiler places these components into the method determines the order of initialization of an object's fields.



(Almost) every constructor's first act and Automatic invocation of super() (For every class except Object)
  • The first thing each <init> method will do is invoke another constructor.
  • The first statement in a constructor
    • If is this()
      • The corresponding <init> method will start by calling another <init> method of the same class.
    • If not the this()
      • The method for that constructor will begin with an invocation of a superclass constructor.
    • super()
      • You can explicitly invoke a superclass constructor using the super() statement.
      • If you don't, the compiler will automatically generate an invocation of the superclass's no-arg constructor.
        • This is true for default constructors as well.
        • With the exception of class Object, the method for any default constructor will do only one thing: invoke the method for the superclass's no-arg constructor.

Invoking super() with arguments

  • If you want to invoke a superclass constructor that takes parameters,
    • You must provide an explicit super() invocation.
  • If parent class explicitly declares a constructor,
    • The Java compiler won't generate a default constructor. 
  • If a subclass's direct superclass does not offer a no-arg constructor,
    • Eevery constructor in that subclass must begin with either an explicit super() or this()invocation.


Only one constructor invocation allowed

  • You can't have both this() and super() in the same constructor.
    • Can only have one or the other (or neither, if the direct superclass includes a no-arg constructor). 
    • If a constructor includes a this() or super() invocation, it must be the first statement in the constructor.


Catching exceptions not allowed

  • One other rule enforced on constructors is that you can't catch any exceptions thrown by the constructor invoked with this() or super().
  • To do so, you would have to begin your constructor with a try statement.
  • If any instance initialization method completes abruptly by throwing an exception, initialization of the object fails.
    • This in turn means that object creation fails, because in Java programs, objects must be properly initialized before they are used.


When you instantiate a new Child object with the new operator, the JVM will

  1. Allocate (at least) enough space on the heap to hold all the instance variables declared in Child object and its superclasses.
  2. Initialize all the instance variables to their default initial values.
  3. Invoke the method in the Child class.

this() won't change the order of initialization
  • The code for constructor invocations and constructor bodies, the Java compiler also places code for any initializers in the <init> method. 
  • If a class includes initializers, the code for them will be placed after the superclass method invocation but before the code for the constructor body, in every <init> method that begins with an explicit or implicit super() invocation.
  • Code for initializers are not included as part of <init> methods that begin with a this() invocation
  • The initializers for a class are guaranteed to be run only once for each new class creation.


Steps for new operator
  1. 分配空間並且設為 default value。
  2. Child 會先呼叫其 Parent。
  3. Parent 會呼叫 Object。
  4. Object 不會做啥事便回傳。
  5. Parent 初始欄位為你所設定的初始值、constructor,回傳。
    • Note:
      • If <init> in a superclass invokes a method that has been overridden in a subclass, the subclass's implementation of that method will run.
      • If the subclass's method implementation uses instance variables explicitly declared in the subclass, those variables will still have their default initial values.
      • 如果在步驟中呼叫了定義在 child 中的 fields,則會取到它的 default value,因為 Child 並還未經過 <init>
  6. Child 初始欄位為你所設定的初始值、constructor。
  7. JVM 回傳 Child object reference。


Summary
  • 在 java 中有個 implicit 初始動作: initializers,其 method name is <init>,負責執行你所給的預設值 (="initial value")。
  • 初始化的動作是往上優先的(會一直跑到 class Object),然後再依 top-down 的順序,這樣可以確保當 child object 使用到 parent object 時,fields 已經被初始化完成。
    • 因此有繼承關係時,一定會呼叫 super(),不論你是否有寫,super() 也必寫在第一行。
    • class Object 中沒有任何 fields,因為 Object 是每個 object 的 superclass。
  • <init> 的執行時間會在 superclass constructor 後,以及 child class constructor body 前。
  • If B extends A
    • allocate spaces and set default values for A and B -> call super() in B -> execute A's <init> -> execute A's constructor -> execute B's <init> -> execute B's constructor -> return B's reference to new operator.
    • 對 A 而言,B 裡 fields 都是不可視的,即使是 B 覆寫了 A's member。



* Reference
- Object Initialization in Java ***

[Java] Object Initialization - (1)

An object is a chunk of memory bundled with the code that manipulates memory.

* The Java language has three mechanisms dedicated to ensuring proper initialization of objects:
(Instance initializers and instance variable initializers collectively are called "initializers.")
  • Instance initializers (also called instance initialization blocks)
  • Instance variable initializers
  • Constructors.
class CoffeeCup {
    private int innerCoffee = 100;
    //...
}

Note
If you explicitly initialize innerCoffee, say to a value of 100, then when each CoffeeCup object is created, innerCoffee will, in effect, be initialized twice.
  1. innerCoffee will be given its default initial value of zero.
  2. The zero will be overwritten with the proper initial value of 100.
All of this takes place while the Java virtual machine is creating the new object -- before it returns the reference to the new object.


* The difference between methods and constructors:
  • The name of a class is a valid name for its methods.
  • Constructors aren't methods by showing that a constructor does not conflict with a method that has the same signature.


* Default constructors
  • If you declare a class with no constructors, the compiler will automatically create a default constructor for the class.
  • Takes no parameters (it's a no-arg constructor) and has an empty body.
  • All classes are guaranteed to have at least one constructor.
  • The compiler gives default constructors the same access level as their class.


* Instance initialization methods
  • When you compile a class, the Java compiler creates an instance initialization method for each constructor you declare in the source code of the class.
  • Although the constructor is not a method, the instance initialization method is
    • It has a name, <init>
    • A return type, void,
    • A set of parameters that match the parameters of the constructor from which it was generated.
    • Not a valid Java method name, so you could not define a method in your source file that accidentally conflicted with an instance initialization method. 
    • Is not a method in the Java language sense of the term, because it has an illegal name. In the compiled, binary Java class file, however, it is a legal method.
If you don't explicitly declare a constructor in a class, the Java compiler will create a default constructor on the fly, then translate that default constructor into a corresponding instance initialization method. Thus, every class will have at least one instance initialization method.


* Initializers

  • Besides providing constructors, Java offers one other way for you to assign an initial value to instance variables: initializers (instance variable initializers and instance initializers).
  • In an instance variable initializer, you have only an equals sign and one expression.
    • private int innerCoffee = 355; // "= 355" is an initializer
    • The right-hand side of the equals sign in an initializer can be any expression that evaluates to the type of the instance variable.


* Instance initializers
Java 1.1 introduced the instance initializer, which is also called the instance initialization block.

// The following block is an instance initializer
    {
        innerCoffee = 355;
    }

Instance initializers are a useful alternative to instance variable initializers whenever:
(1) initializer code must catch exceptions, or
(2) perform fancy calculations that can't be expressed with an instance variable initializer.

Advantages
  • Can just write the code once.
    • You could, of course, always write such code in constructors. But in a class that had multiple constructors, you would have to repeat the code in each constructor.
  • Will be executed no matter what constructor is used to create the object.
  • Useful in anonymous inner classes, which can't declare any constructors at all.


* Initializers can't make forward references

參考物件的順序是無法顛倒,得依照宣告的先後,因此使用了還未宣告到的變數是不可行的,會被報錯,如下:

class VirtualCafe {
    private int chairsCount = 4 * tablesCount;
    private int tablesCount = 20;
    //...
}
但有些寫法,仍能通過,如下:
class VirtualCafe {

    private int chairsCount = initChairsCount();
    private int tablesCount = 20;

    private int initChairsCount() {
        return tablesCount * 4;
    }
    //...
}
  • Here chairsCount's initializer sneakily invokes a method that uses tablesCount before its initializer has been executed.
  • When initChairsCount() calculates tablesCount * 4, tablesCount is still at its default initial value of zero.
  • As a result, initChairsCount() returns zero, and chairsCount is initialized to zero.



* Reference
- Object Initialization in Java ***

[Android] Bluetooth - (3) APIs

Minim Android API Level Suggestion: Android 2.0 (Level 5)


Provided from API 5: Basic Functions



Provided from API 11: Working with Profiles

  • BluetoothProfile
    • A Bluetooth profile is a wireless interface specification for Bluetooth-based communication between devices.
  • BluetoothProfile.ServiceListener
    • The internal service that runs a particular profile
  • BluetoothA2dp
    • A2dp: Advanced Audio Distribution Profile
    • Defines how high quality audio can be streamed from one device to another over a Bluetooth connection.
    • To control the Bluetooth A2DP profile.
    • Only supports one connected Bluetooth A2dp device at a time.
  • BluetoothAssignedNumbers
    • Only include Company ID values.
    • Company Identifiers
  • BluetoothHeadset
    • Provides support for Bluetooth headsets to be used with mobile phones.
    • Controlling the Bluetooth Headset(Handsfree v1.5) Service.
    • Only supports one connected Bluetooth Headset at a time.


Provided from API 14: Bluetooth Health Devices

  • 提供使用藍芽進行健康照護,透過藍芽與監視裝置連線
  • BluetoothHealth
    • A proxy object for controlling the Bluetooth Service via IPC.BluetoothHealthCallback
    • 接收所監視的資訊與藍芽狀態。
  • BluetoothHealthAppConfiguration
    • 會從 BluetoothHealthCallback 得到此物件,其中關於連線設備的設定資訊。
    • ex: 可由 configuration 資訊來 initiate and terminate connections。



* Reference
- Bluetooth | Android Developers
- Bluetooth Glossary

2011年11月14日 星期一

[Android] Bluetooth - (2) Connection

Connecting as a server
  • Server is holding an open BluetoothServerSocket.
  • The purpose of the server socket is to listen for incoming connection requests and when one is accepted, provide a connected BluetoothSocket.
  • When the BluetoothSocket is acquired from the BluetoothServerSocket, the BluetoothServerSocket can (and should) be discarded, unless you want to accept more connections.


Here's the basic procedure to set up a server socket and accept a connection:

1. Get a BluetoothServerSocket by calling thelistenUsingRfcommWithServiceRecord(String, UUID).
  • The string is an identifiable name of your service.
  • The system will automatically write to a new Service Discovery Protocol (SDP) database entry on the device (the name is arbitrary and can simply be your application name).
  • The UUID is also included in the SDP entry and will be the basis for the connection agreement with the client device.
    • When the client attempts to connect with this device, it will carry a UUID that uniquely identifies the service with which it wants to connect
    • These UUIDs must match in order for the connection to be accepted (in the next step).

2. Start listening for connection requests by calling accept().
  • This is a blocking call. 
    • The accept() call should not be executed in the main Activity UI thread because it is a blocking call and will prevent any other interaction with the application.
    • To abort a blocked call such as accept(), call close() on the BluetoothServerSocket (or BluetoothSocket) from another thread and the blocked call will immediately return. 
  • It will return when either a connection has been accepted or an exception has occurred. 
  • A connection is accepted only when a remote device has sent a connection request with a UUID matching the one registered with this listening server socket.
  • When successful, accept() will return a connected BluetoothSocket.

3. Unless you want to accept additional connections, call close().
  • This releases the server socket and all its resources, but does not close the connected BluetoothSocket that's been returned by accept()
  • Unlike TCP/IP, RFCOMM only allows one connected client per channel at a time, so in most cases it makes sense to call close() on the BluetoothServerSocket immediately after accepting a connected socket.
Note:
  • All methods on a BluetoothServerSocket or BluetoothSocket are thread-safe.
    • It usually makes sense to do all work with a BluetoothServerSocket or BluetoothSocket in a new thread managed by your application.
  • When accept() returns the BluetoothSocket, the socket is already connected, so you should not call connect() (as you do from the client-side).



Connecting as a client
  • In order to initiate a connection with a remote device, you must first obtain a BluetoothDevice object that represents the remote device.
  • You must then use the BluetoothDevice to acquire a BluetoothSocket and initiate the connection.

Here's the basic procedure:

1. Using the BluetoothDevice, get a BluetoothSocket by calling createRfcommSocketToServiceRecord(UUID).
  • This initializes a BluetoothSocket that will connect to the BluetoothDevice
  • The UUID passed here must match the UUID used by the server device when it opened its BluetoothServerSocket (with listenUsingRfcommWithServiceRecord(String, UUID)).
  • Using the same UUID is simply a matter of hard-coding the UUID string into your application and then referencing it from both the server and client code.


2. Initiate the connection by calling connect().
  • This method is a blocking call. 
    • If, for any reason, the connection fails or the connect() method times out (after about 12 seconds), then it will throw an exception.
    • This connection procedure should always be performed in a thread separate from the main Activity thread.
  • Upon this call, the system will perform an SDP lookup on the remote device in order to match the UUID
    • If the lookup is successful and the remote device accepts the connection, it will share the RFCOMM channel to use during the connection and connect() will return. 
Note: 
  • Ensure that the device is not performing device discovery when you call connect().
    • If discovery is in progress, then the connection attempt will be significantly slowed and is more likely to fail.
  • cancelDiscovery() is called before the connection is made.
    • You should always do this before connecting and it is safe to call without actually checking whether it is running or not (but if you do want to check, call isDiscovering()).


Managing a Connection

Using the BluetoothSocket, the general procedure to transfer arbitrary data is simple:
  1. Get the InputStream and OutputStream that handle transmissions through the socket, via getInputStream() and getOutputStream(), respectively.
  2. Read and write data to the streams with read(byte[]) and write(byte[]).
Note
  • Should use a dedicated thread for all stream reading and writing.
    • This is important because both read(byte[]) and write(byte[]) methods are blocking calls.



Working with Profiles
Starting in Android 3.0, the Bluetooth API includes support for working with Bluetooth profiles.

A Bluetooth profile
  • Is a wireless interface specification for Bluetooth-based communication between devices. 
  • An example is the Hands-Free profile. For a mobile phone to connect to a wireless headset, both devices must support the Hands-Free profile.

Support Profiles
  • Headset
    • The Headset profile provides support for Bluetooth headsets to be used with mobile phones.
    • BluetoothHeadset class
      • A proxy for controlling the Bluetooth Headset Service via interprocess communication (IPC). 
      • Includes both Bluetooth Headset and Hands-Free (v1.5) profiles.
      • Support for AT commands. For more discussion of this topic, see Vendor-specific AT commands
  • A2DP
    • The Advanced Audio Distribution Profile (A2DP).
    • Defines how high quality audio can be streamed from one device to another over a Bluetooth connection.
    • BluetoothA2dp class
      • A proxy for controlling the Bluetooth A2DP Service via IPC.


Here are the basic steps for working with a profile:
  1. Get the default adapter, as described in Setting Up Bluetooth.
  2. Use getProfileProxy() to establish a connection to the profile proxy object associated with the profile. In the example below, the profile proxy object is an instance of BluetoothHeadset.
  3. Set up a BluetoothProfile.ServiceListener. This listener notifies BluetoothProfile IPC clients when they have been connected to or disconnected from the service.
  4. In onServiceConnected(), get a handle to the profile proxy object.
  5. Once you have the profile proxy object, you can use it to monitor the state of the connection and perform other operations that are relevant to that profile.



By the way

UUID
  • Universally Unique Identifier (UUID) 
  • A standardized 128-bit format for a string ID used to uniquely identify information. 
  • Big enough that you can select any random and it won't clash.
  • Used to uniquely identify your application's Bluetooth service.
  • To get a UUID to use with your application, you can use one of the many random UUID generators on the web, then initialize a UUID with fromString(String).



* Reference
Bluetooth | Android Developers **
package android.bluetooth
Android應用程式學習筆記 - Bluetooth
藍牙規範 - 维基百科,自由的百科全书
Bluetooth profile - Wikipedia, the free encyclopedia
Android 上的 Bluetooth | 憑虛御風
Bluetooth Health Devices

[Android] Bluetooth - (1)

Using the Bluetooth APIs, an Android application can perform the following:
  • Scan for other Bluetooth devices
  • Query the local Bluetooth adapter for paired Bluetooth devices
  • Establish RFCOMM channels
  • Connect to other devices through service discovery
  • Transfer data to and from other devices
  • Manage multiple connections

Four steps to communicate using Bluetooth
  1. Setting up Bluetooth
  2. Finding devices that are either paired or available in the local area
  3. Connecting devices
  4. Transferring data between devices.

Permissions
  • BLUETOOTH
    • To perform any Bluetooth communication
    • 讓程式有權限連接裝置、傳輸資料。
      • ex: requesting a connection, accepting a connection, and transferring data.
  • BLUETOOTH_ADMIN
    • Initiate device discovery or manipulate Bluetooth settings.
    • 讓程式有權限搜尋裝置及設定藍芽。
  • Note
    • If you use BLUETOOTH_ADMIN permission, then must also have the BLUETOOTH permission.


Check Bluetooth Function

在使用 Bluetooth 前必須先確認裝置有支援並且已開啟。判斷的方式如下:

1. Get the BluetoothAdapter
  • This returns a BluetoothAdapter that represents the device's own Bluetooth adapter (the Bluetooth radio).
    • There's one Bluetooth adapter for the entire system, and your application can interact with it using this object.
  • If getDefaultAdapter() returns null, then the device does not support Bluetooth.
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
    // Device does not support Bluetooth
}


2. Enable Bluetooth
  • Call isEnabled() to check whether Bluetooth is currently enable.
    • If this method returns false, then Bluetooth is disabled.
  • To request that Bluetooth be enabled, call startActivityForResult() with the ACTION_REQUEST_ENABLE action Intent.
    • This will issue a request to enable Bluetooth through the system settings (without stopping your application).
    • enabling Bluetooth succeeds ? return RESULT_OK : RESULT_CANCELED.

if (!mBluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}


3.  Listen for the ACTION_STATE_CHANGED broadcast Intent

此步驟可略,但接收此 intent,有助於在程式執行中了解 Bluetooth 的狀態。
  • The system will broadcast whenever the Bluetooth state has changed
  • Contains the extra fields 
    • EXTRA_STATE: new Bluetooth status
    • EXTRA_PREVIOUS_STATE: old Bluetooth status
    • Possible values for these extra fields are STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, and STATE_OFF.


Querying paired devices

在 scan devices 前,可以使用 getBondedDevices() 先找尋已經配對過的資訊。
Set pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
    // Loop through paired devices
    for (BluetoothDevice device : pairedDevices) {
        // Add the name and address to an array adapter to show in a ListView
        mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
    }
}

All that's needed from the BluetoothDevice object in order to initiate a connection is the MAC address.



Finding Devices (concept)

找尋裝置 -> 配對 -> 連線

  • Using the BluetoothAdapter
    • Can find remote Bluetooth devices either through device discovery or by querying the list of paired (bonded) devices.
  • Device discovery
    • A scanning procedure that searches the local area for Bluetooth enabled devices and then requesting some information about each one.
    • This is sometimes referred to as "discovering," "inquiring" or "scanning".
  • A Bluetooth device within the local area will respond to a discovery request only if it is currently enabled to be discoverable. 手機必須是已設定為 discoverable 才有可能被找到
    • If a device is discoverable, it will respond to the discovery request by sharing some information.
      • ex: the device name, class, and its unique MAC address
    • Using this information, the device performing discovery can then choose to initiate a connection to the discovered device.
  • Once a connection is made with a remote device for the first time
    • A pairing request is automatically presented to the user.
  • When a device is paired
    • The basic information about that device is saved and can be read using the Bluetooth APIs. 
    • Using the known MAC address for a remote device, a connection can be initiated with it at any time without performing discovery (assuming the device is within range).
Note: Being paired and being connected is the different.
  • To be paired
    • Two devices are aware of each other's existence
    • Have a shared link-key that can be used for authentication
    • Be capable of establishing an encrypted connection with each other.
  • To be connected
    • The devices currently share an RFCOMM channel.
    • Be able to transmit data with each other.
  • The current Android Bluetooth API's require devices to be paired before an RFCOMM connection can be established. (Pairing is automatically performed when you initiate an encrypted connection with the Bluetooth APIs.)


Discovering devices
  • Using startDiscovery() to start discovering devices.
    • The process is asynchronous and the method will immediately return with a boolean indicating whether discovery has successfully started.
  • The discovery process usually involves an inquiry scan of about 12 seconds, followed by a page scan of each found device to retrieve its Bluetooth name.
  • Your application must register a BroadcastReceiver for the ACTION_FOUND Intent in order to receive information about each device discovered.
    • This Intent carries the extra fields
      • EXTRA_DEVICE: BluetoothDevice
      • EXTRA_CLASS: BluetoothClass
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        // When discovery finds a device
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            // Get the BluetoothDevice object from the Intent
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            // Add the name and address to an array adapter to show in a ListView
            mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
        }
    }
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy

NotePerforming device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources.
  • Once you have found a device to connect, be certain that you always stop discovery with cancelDiscovery() before attempting a connection.
  • Also, if you already hold a connection with a device, then performing discovery can significantly reduce the bandwidth available for the connection, so you should not perform discovery while connected.


Enabling discoverability

必須要將裝置設為 discoverable 才能被搜尋到。
  • To make the local device discoverable to other devices
    • startActivityForResult(Intent, int) with the ACTION_REQUEST_DISCOVERABLE action Intent.
    • This will issue a request to enable discoverable mode through the system settings (without stopping your application).
  • By default, the device will become discoverable for 120 seconds
    • You can define a different duration by adding the EXTRA_DISCOVERABLE_DURATION Intent extra.
      • The maximum duration an app can set is 3600 seconds
      • A value of 0 means the device is always discoverable.
      • Any value below 0 or above 3600 is automatically set to 120 secs
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);

ACTION_SCAN_MODE_CHANGED Intent
  • Notified when the discoverable mode has changed.
  • This will contain the extra fields
    • EXTRA_SCAN_MODE: new scan mode
    • EXTRA_PREVIOUS_SCAN_MODE: old scan mode
    • Possible values for each are
      • SCAN_MODE_CONNECTABLE_DISCOVERABLE: discoverable mode
      • SCAN_MODE_CONNECTABLE: not in discoverable mode but still able to receive connections
      • SCAN_MODE_NONE: not in discoverable mode and unable to receive connections
Note
  • You do not need to enable device discoverability if you will be initiating the connection to a remote device.
  • Enabling discoverability is only necessary when you want your application to host a server socket that will accept incoming connections, because the remote devices must be able to discover the device before it can initiate the connection.


By the way
  • Bluetooth Profile (藍牙規範)
    • 目的是要確保 Bluetooth 設備間的互通性(interoperability)。
      • The way a device uses Bluetooth technology depends on its profile capabilities. 
      • The profiles provide standards which manufacturers follow to allow devices to use Bluetooth in the intended manner.
    • 由藍牙技術聯盟所定義。
    • 但 Bluetooth 產品無須實現所有的 Bluetooth 規範 Profile。
    • Bluetooth 規格 1.1 定義 13 個 Profiles。
    • At a maximum, each profile specification contains information on the following topics:
      • Dependencies on other formats
      • Suggested user interface formats
      • Specific parts of the Bluetooth protocol stack used by the profile.
        • To perform its task, each profile uses particular options and parameters at each layer of the stack. This may include an outline of the required service record, if appropriate.
  • Advance Audio Distribution Profile (A2DP, 藍牙立體聲音訊傳輸規範)
    • 規定了使用藍牙非同步傳輸信道方式,傳輸高質量音樂檔案數據的協議堆棧軟體和使用方法,基於該協議就能通過以藍牙方式傳輸高品質的立體聲音樂。
    • 分為 1.1 版和 1.2 版,只要連線雙方支援 A2DP 協議都能以 16 bits,44.1 kHz的質量傳輸聲音訊號。
    • 假如有一方沒有支援 A2DP 的話,只能以 8 bits,8 kHz的質量的 Handsfree Profile 傳輸模式,聲音質量會大打折扣



* Reference
- Bluetooth | Android Developers **
- package android.bluetooth
- Android應用程式學習筆記 - Bluetooth
- 藍牙規範 - 维基百科,自由的百科全书
- Bluetooth profile - Wikipedia, the free encyclopedia
- Android 上的 Bluetooth | 憑虛御風

2011年11月13日 星期日

[Facebook] Authentication

  • Uses the OAuth 2.0 protocol for authentication and authorization.
  • Support for Website, mobile and desktop apps.


Supports two different OAuth 2.0 flows for user login
  • Server-side
    • The authentication code flow in the specification.
    • Used whenever you need to call the Graph API from your web server.
  • Client-side
    • The implicit flow.
    • Used when you need to make calls to the Graph API from a client.
    • ex: JavaScript running in a Web browser or from a native mobile or desktop app.


Implementation of the OAuth 2.0 involves three different steps
  • User authentication
    • Ensures that the user is who they say they are
  • App authorization
    • Ensures that the user knows exactly what data and capabilities they are providing to your app.
  • App authentication
    • Ensures that the user is giving their information to your app and not someone else.


Server-side Flow



Client-side Flow



Alternate Redirect URIs
  • Specifying additional App Domains for your app is useful for redirecting users to other servers for geographic distribution of load.
  • When redirect_uris are specified in the authentication flows, the user is normally redirected to a path under the Site URL that you specify in the Basic Info section on the Summary tab in the Developer App
  • However, you can override this behavior and redirect to one or more other related or sub-domains by specifying each domain name in the App Domain field in the Basic Info section of the Summary Tab in the Developer App


You can log a user out of their Facebook session by directing them to the following URL:
https://www.facebook.com/logout.php?next=YOUR_URL&access_token=ACCESS_TOKEN


Also support
  • App Login
  • Page Login


Cross Site Request Forgery (CSRF)
  • Cross site request forgery is an attack in which a trusted (authenticated and authorized) user unknowingly performs an action on website.
  • To prevent this attack, you should
    • Pass an identifier in the state parameter
    • Validate the state parameter matches on the response. 
  • We strongly recommend that any app implementing Facebook user login implement CSRF protection using this mechanism.



Related
[Security] OAuth and OpenId


* Reference
- Authentication

[Facebook] Graph API - Real-time Update

The Graph API 提供 subscriptions API 訂閱資訊功能,讓 Application 能即時收到這些資訊的更新。

Here are the steps to set up a subscription:
  • Set up an endpoint URL that receives both HTTP GET (for subscription verification) and POST (for actual change data) requests from Facebook.
  • Make a POST to the graph API url https://graph.facebook.com/APPLICATION_ID/subscriptions to subscribe, and be ready to handle the verification request.
  • When data changes, and there is a valid subscription, Facebook servers will make an HTTP POST request to the callback_url you specified. 
  • The request will have content type of application/json; the body will be a JSON-encoded string containing one or more changes.
    • Note that this does not include the actual data values;
  •  Facebook aggregates changes and sends batched updates every 5 seconds or when number of unsent changes exceeds 1000, so your server(s) should be set up to handle this level of load.


You can currently subscribe to updates for these types of objects:
  • user
    • Get notifications about particular fields and connections corresponding to user nodes in the Graph API.
  • permissions (FQL)
    • Get notifications when your users change the permissions they afford your applications.
    • The fields are like those in the corresponding FQL table.
  • page
    • Get notifications when pages that have installed your application change their public properties. 
    • Note
      • Page topic is only used for subscribing to changes to public attributes of the page (like name, category, picture etc).
    • You can subscribe to the page's feed in the same way you subscribe to a user's feed - the subscription topic should be 'user' and the subscription field should be 'feed'


User connections to which you can/can't subscribe

  • Can
    • feed, friends, activities, interests, music, books, movies, television, likes, checkins
  • Can't
    • home, tagged, posts, photos, albums, videos, groups, notes, events, inbox, outbox, updates, accounts
  • Note
    • please check back on this page at later time for updates.



Questions
  • 即使 Facebook 會將更新資訊 post 到我們設定的 callback url,但怎麼將這資訊送到(push)手機上的 Application?
    • This service only for server-to-server communication.
    • 所以應再考慮若 app server 收到更新訊息,如何 push 到 app,can try C2DM.




* Reference
- Real-time Updates
- Subscription
- Facebook API 开发记录

- real-time Sample code
- [TLK]Q/A about real-time updates
- How to Implement Push Notifications for Android
- Does Android support near real time push notification

2011年11月12日 星期六

[Facebook] Graph API - Objects

* Some Connection is a kind of Objects.

Format
  • Object
    • Explanation
    • Permissions maybe needed (not list all)
    • URL to get this Object
    • Connections of this Object (URL to get other objects by their connection)

[Main Objects]
  • Application
    • An application registered on Facebook Platform
    • /APPLICATION_ID/accounts, albums, banned, feed, insights, links, payments, picture, posts, reviews, staticresources, statuses, subscriptions, tagged, translations, scores, achievements
  • Page
    • A Facebook Page
    • /PAGE_ID/feed, picture, settings, tagged, links, photos, groups, albums, statuses, videos, notes, events, checkins, admins, blocked, tabs
  • User
    • A user profile.
    • https://graph.facebook.com/me (the current user)
    • /USER_ID/accounts, achievements, activities, albums, apprequests, books, checkins, events, family, feed, friendlists, friendrequests, friends, games, groups, home, inbox, interests, likes, links, movies, music, mutualfriends, notes, notifications, outbox, payments, permissions, photos, picture, pokes, posts, scores, statuses, tagged, television, updates, videos

[Connections]
  • Album
    • A photo album
    • user_photos: 你的相片; friends_photos: 和你分享的相片
    • /User, Application, Page/albums
    • /ALBUMS_ID/photos, likes, comments, picture
  • Photo
    • An individual photo within an album; 所有照片(包含被tag的...)
    • ADD: publish_stream: 替你張貼內容到 Facebook
    • /User, Page, Application, ALBUMS_ID/photos
    • /PHOTO_ID/comments, likes, picture, tags
  • Checkin
    • A checkin made through Facebook Places or the Graph API.
    • user_checkins: 你的打卡動態; 和你分享的打卡動態
    • /User, Page/checkins
    • /CHECKIN_ID/comments, likes
    • Test Result
      • Can't get checkin info that tagged by friend?
  • Comment
    • A Comment on a Graph API object
    • /COMEMENT_ID/likes
  • Event
    • A Facebook event
    • user_events: 你的活動; rsvp_event: Manage your events; friends_events: 和你分享的活動
    • /User, Application, Page/events
    • /EVENT_ID/feed, noreply, invited, attending, maybe, declined, picture
      • feed can CREATE/DELETE links, posts, statuses
    • Test Result
      • 僅取得 User 發起的、不確定的與確定參加的?
  • FriendList
    • A Facebook friend list; 取得朋友群組清單
    • read_friendlists: Access my custom friend lists
    • /User/friendlists
    • /FRIENDLIST_ID/members
      • manage_friendlists : Manage your custom friend lists
  • Group
    • A Facebook group
    • user_groups
    • /User, Page/groups
    • /GROUP_ID/feed, members, picture, docs
    • Message
      • A message in a thread
      • read_mailbox: Access messages in your inbox
      • /User/inbox
    • Note
      • A Facebook Note
      • user_notes, friends_notes
      • /User/notes
      • /NOTE_ID/comments, likes
    • Question
      • A question asked by a user, as represented in the Graph API.
      • user_questions, friends_questions
      • /Use/questions
      • /QUESTION_ID/options
    • QuestionOption
      • An option allowed as an answer to a question.
      • /Question/options
      • /QUESTIONOPTION_ID/votes
    • Review
      • A review for an application
      • /Application/reviews
    • Subscription
      • A subscription to an application to get real-time updates for an Graph object type.
      • /Application/subscriptions
    • Thread
      • A message thread
      • /User/threads
      • Test Error
        • (#298) You must be a developer of the application
    • Video
      • An individual video
      • /Use, Application, Page/videos
      • /VIDEO_ID/likes, comments, picture

    - Wall-related
    • Link
      • A shared link
      • read_stream: Access posts in your News Feed
      • /User, Application, Page/links
      • /LINK_ID/comments, likes
    • Post
      • An individual entry in a profile's feed
      • /User, Application, Page, Group/posts
      • /POST_ID/comments, likes
    • Status message
      • A status message on a user's wall (UPDATE)
      • User 在 wall 發表的純文字敘述。
      • /User/statuses
      • /STATUS_ID/comments, likes

    - Game-related
    • Achievement(Instance)
      • Instance for an achievement for a user.

    [Others]
    • Domain
      • A website domain within the Graph API
    • Insights
      • Statistics about applications, pages, or domain.
      • /User, Application, Domain/insights

    Note
    like and feed are not an Object


    By the way
    HTTP 302: 暫時轉移(Temporarily Moved)
    物件已移動,並告知移動過去的網址。針對表單架構驗證,這通常表示為「物件已移動」。 要求的資源暫時存於不同的 URI 底下。由於重新導向可能偶而改變,用戶端應繼續使用要求 URI 來執行未來的要求。 除非以 Cache-Control 或 Expires 標頭欄位表示,此回應才能夠快取。


    * Reference
    - Graph API
    - Graph API Explorer

    [Facebook] Graph APIs - Introduction

    [The Graph API]
    • Presents a simple, consistent view of the Facebook social graph.
    • Uniformly representing objects in the graph and the connections between them.
      • Objects: ex: people, photos, events, and pages
      • Relationships connections: ex: friend relationships, shared content, and photo tags

    [How to access Object]
    • Every object has a unique ID.
    • Access the properties of an object by requesting https://graph.facebook.com/ID
    • Alternatively, people and pages with usernames can be accessed using their username as an ID by https://graph.facebook.com/USERNAME
    • All responses are JSON objects.
    • Support RESTful using HTTP GET(get), POST(create), DELETE(delete).
      • ex: DELETE https://graph.facebook.com/ID?access_token=... HTTP/1.1
      • To support clients that do not support all HTTP methods (like JavaScript clients), you can alternatively issue a POST request to an object URL with the additional argument method=delete to override the HTTP method. ex:

    [Access connections of Object]
    • All of the objects in the Facebook social graph are connected to each other via relationships.
      • ex: Bret Taylor is a fan of the Coca-Cola page; Bret Taylor and Arjun Banker are friends...
    • Access the connections between objects using the URL structure https://graph.facebook.com/ID/CONNECTION_TYPE.


    [Query skills]
    * About Objects

    * About Connections
    Several useful parameters that enable you to filter and page through connection data:

    * Data format
    • All date fields are returned as ISO-8601 formatted strings.
    • You can optionally override the date format by specifying a "date_format" query parameter.


    [Permission]
    • To get additional information about a user, you must first get their permission.
    • Different information may need different permissions, you have obtain the right permissions of access token for the user or you can not get the relative information.

    [Introspection]
    • Enables you to see all of the connections an object has without knowing its type ahead of time. 
    • This feature is a useful and extensible way to find all the things your users are connected to.
    • To get this information, add metadata=1 to the object URL, and the resulting JSON will include a metadata property that lists all the supported connections for the given object. 
    • ex: See all the connections for the Developer Garage event above by fetching https://graph.facebook.com/331218348435?metadata=1.


    [Search]
    https://graph.facebook.com/search?q=QUERY&type=OBJECT_TYPE
    ex:


    * Reference
    - Graph API
    - Graph API Explorer

    2011年11月10日 星期四

    [AndroidDev] WebView

    [WebView]
    • The basis upon which you can do followings within your Activity:
      • Roll your own web browser.
      • Simply display some online content.
      • Uses the same rendering and JavaScript engine(WebKit) as the browser, but it runs under the control of your application.
    • By default:
      • A WebView provides no browser-like widgets.
      • No zoom in and out.
      • Does not enable JavaScript.
      • No navigation controls.
        • Need to handle the BACK button on the device
        • Overrides URL loading, it automatically accumulates a history of visited web pages.
      • Web page errors are ignored.
      • Perform text searches. (?)
      • No address bar.
      • As you click a link, by default WebView will ask Activity Manager to choose the proper handler for the url.
        • Instead of adding an intent filter to view web pages, you can override the WebViewClient class and enable this Activity to handle its own URL requests.

    Load content
    • Can download content from the web.
    • Can come from local files stored in your assets directory.
    • Can even be dynamically generated by your application code.
    • ex:
    webview.loadUrl("http://www.google.com.tw/");  
    
    // or
    
    String summary = "You scored 192 points.";
    webview.loadData(summary, "text/html", null);
    
    

    Note:

    A WebView has several customization points where you can add your own behavior. These are:
    • Creating and setting a WebChromeClient subclass. 
      • This class is called when something that might impact a browser UI happens, ex:
        • Progress update.
        • JavaScript alerts are sent here.
    • Creating and setting a WebViewClient subclass.
      • It will be called when things happen that impact the rendering of the content, ex:
        • Errors or form submissions.
      • Will load any URL selected from this WebView into the same WebView.
      • Can intercept URL loading here (via shouldOverrideUrlLoading()).
        • 預設點擊頁面上的 link 會由系統處理,開啟相對應的 app。
          • ex: 若是 URL 則開啟系統 Browser。
        • 但若 override shouldOverrideUrlLoading()
          • 則能依照自己意思判斷 URL 決定要在 WebView 開啟或是在 Browser 中開啟。ex:
          • return true
            • The method has handled the URL and the event should not propagate.
              • ex: an Intent would be created that's handled by the Browser application
            • 表示會自己處理 url。
            • 因此若沒有任何處理動作,點擊後不會有反應。
          • return false
            • The current WebView handles the url
            • 仍由系統處理,但會開啟在當前的 WebView。
            • 因此若有設定自己的執行動作又 return false,則兩種執行動作都會被觸發。
        • 所以如果想要畫面都在 WebView 中開啟,則表示一定要 override shouldOverrideUrlLoading()。
    • Related JavaScript
      • Enabling JavaScript with setJavaScriptEnabled() (Modifying the WebSettings)
      • addJavascriptInterface(Object, String)
        • Adding JavaScript-to-Java interfaces.
        • Has security issue.
        • Bind Java objects into the WebView so they can be controlled from the web pages JavaScript.
          • ex: Your JavaScript code can call a method in your Android code to display a Dialog, instead of using JavaScript's alert() function.
    Data
    • For obvious security reasons, your application has its own cache, cookie store etc.—it does not share the Browser application's data
    • Cookies are managed on a separate thread, so operations like index building don't block the UI thread. 
    • CookieSyncManager
      • Is used to synchronize the browser cookie store between RAM and permanent storage.
        • To get the best performance, browser cookies are saved in RAM. A separate thread saves the cookies between, driven by a timer.
      • Note that even sync() happens asynchronously, so don't do it just as your activity is shutting down.

    Note
    • Must claim this permission in AndroidManifest.xml or you won't open page and do not get any exception.
      • <uses-permission android:name="android.permission.INTERNET">


    Related
    [AndroidLayout] WebView Performance


    * Reference
    - WebView | Android Developers
    WebViewClient | Android Developers
    - WebChromeClient
    WebSettings | Android Developers
    CookieSyncManager | Android Developers
    Android Developers Blog: Using WebViews
    Building Web Apps in WebView | Android Developers
    - WebView 1 - 4 ***
    - SOP - Same Origin Policy (Browser Security Policy)

    [Android] Other app types

    android 除了主要的四元件(activity, broadcastReceiver, service, content provider)

    從這四元件所延伸的應用,有些可被歸類的項目

    2011年11月8日 星期二

    [Android] requestFeature() must be called before adding content

    Error Message

    Caused by: android.util.AndroidRuntimeException: requestFeature() must be called before adding content

    Occurred when using requestWindowFeature


    Solution

    必須在 setContentView 前呼叫 requestWindowFeature



    [Android] Action Bar - (1)

    [Android 3.0]
    • A replacement for the traditional title bar at the top of the activity window. Includes:
      • The application logo in the left corner.
      • Provides a new interface for items in the Options Menu.
    • Can provide:
      • Action items
        • Equal to option menu items.
        • Using android:showAsAction menu item xml attribute with a value of "ifRoom"
        • When there's enough room
          • The menu item appears directly in the Action Bar.
        • Otherwise
          • The item is placed in the overflow menu, revealed by the menu icon on the right side of the Action Bar.
        • By default all items from the Options Menu are placed in the overflow menu.
          • The user can open by touching the menu icon on the right side of the Action Bar.
          • However, you can place select menu items directly in the Action Bar as "action items," for instant access
      • Action view
        • Replace an action item with a widget, ex: search box.
        • Using android:actionViewLayout(android:actionLayout?) attribute with a layout resource or the android:actionViewClass attribute with the class name of a widget.
        • You must also declare the android:showAsAction attribute so that the item appears in the Action Bar.
        • If there's not enough room in the Action Bar does not show the widget.
      • Add an action to the application logo and replace it with a custom logo
        • The application logo is automatically assigned the android.R.id.home ID, which the system delivers to your activity's onOptionsItemSelected() callback when touched.
        • Simply respond to this ID in your callback method to perform an action such as go to your application's "home" activity.
        • To replace the icon with a logo.
          • Specify your application logo in the manifest file with the android:logo attribute, then call setDisplayUseLogoEnabled(true) in your activity.
      • Add breadcrumbs to navigate backward through the back stack of fragments.
      • Add tabs or a drop-down list to navigate through fragments.
      • Customize the Action Bar with themes and backgrounds.


    Summary
    • action items = options menu = overflow action items (ifRoom)
    • context menu: showing after long press
      • Displayed when the user performs a "right-click" on a PC.
      • 需覆寫 onCreateContextMenu()onContextItemSelected()
    • action view: widget(search box)


    By the way