12 |
13 | ##Source Code
14 | Either download the source as a .zip or use your favourite git client:-
15 |
16 | https://github.com/PhilipsHue/PhilipsHueSDKAndroid
17 |
18 | Here you have 2 Sample Apps (Android projects) and 1 Java Desktop Application. Pick either to use as a starting point.
19 |
20 |
QuickStart App. Contains a skeleton app with minimal functionality for connecting to a bridge and setting lights.
21 |
Example App. A more complete app containing schedules, groups, scenes.
22 |
Desktop App. A Java Desktop Application written in Swing showing how to connect to your Hue Lights.
23 |
24 | Import either into your favourite IDE.
25 |
26 | ##Connecting to/finding a Bridge
27 | On your mobile device in your Wi-Fi settings connect to the router that corresponds to the label on your developer kit (e.g. For "hue dev 009" Wi-Fi name would be "hue dev 009 2.4GHz").
28 |
29 | Password is: philipshue
30 |
31 | ### Using an Emulator.
32 | If there are no developer kits available an Emulator can be used instead.
33 | The following emulator is currently in development but it should be usable:
34 |
35 | http://steveyo.github.io/Hue-Emulator/
36 |
37 | ##Classpath
38 | The huelocalsdk.jar and the sdkresources.jar should be placed in your project buildpath (these are located under the /libs folder in either of the sample apps).
39 |
40 | ##Coding Tips
41 |
42 | To obtain an instance of the SDK:
43 |
44 | phHueSDK = PHHueSDK.getInstance();
45 |
46 |
47 | To get bridge information (e.g. Lights, Config, Scenes, Groups) use the Bridge Resource Cache. For example:
48 |
49 | PHBridge bridge = phHueSDK.getSelectedBridge();
50 | PHBridgeResourcesCache cache = bridge.getResourceCache();
51 | ArrayList allLights = cache.getAllLights();
52 |
53 |
54 | For updates (e.g. change light state) use the Bridge directly. For example:
55 |
56 | PHBridge bridge = phHueSDK.getSelectedBridge();
57 | bridge.updateLightState(light, lightState, listener);
58 |
59 | To set lights to specific RGB Colours:
60 |
61 | float xy[] = PHUtilities.calculateXYFromRGB(255, 0, 255, light.getModelNumber());
62 | PHLightState lightState = new PHLightState();
63 | lightState.setX(xy[0]);
64 | lightState.setY(xy[1]);
65 |
66 | To set all lights to the same state, easiest way is to use the default group.
67 |
68 | bridge.setLightStateForDefaultGroup(lightState);
69 |
70 | To validate your lightstate object is valid (before sending to the bridge), you can use:
71 |
72 | String validState = lightState.validateState(); // null means valid, otherwise the returned String contains the error message.
73 |
74 |
75 | For more information see:
76 |
77 | https://github.com/PhilipsHue/PhilipsHueSDKAndroid/blob/master/README.md
78 |
79 |
80 | Have fun & happy coding!
81 |
82 |
--------------------------------------------------------------------------------
/QuickStartApp/src/com/philips/lighting/quickstart/MyApplicationActivity.java:
--------------------------------------------------------------------------------
1 | package com.philips.lighting.quickstart;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 | import java.util.Random;
6 |
7 | import android.app.Activity;
8 | import android.os.Bundle;
9 | import android.util.Log;
10 | import android.view.View;
11 | import android.view.View.OnClickListener;
12 | import android.widget.Button;
13 |
14 | import com.philips.lighting.hue.listener.PHLightListener;
15 | import com.philips.lighting.hue.sdk.PHHueSDK;
16 | import com.philips.lighting.model.PHBridge;
17 | import com.philips.lighting.model.PHBridgeResource;
18 | import com.philips.lighting.model.PHHueError;
19 | import com.philips.lighting.model.PHLight;
20 | import com.philips.lighting.model.PHLightState;
21 |
22 | /**
23 | * MyApplicationActivity - The starting point for creating your own Hue App.
24 | * Currently contains a simple view with a button to change your lights to random colours. Remove this and add your own app implementation here! Have fun!
25 | *
26 | * @author SteveyO
27 | *
28 | */
29 | public class MyApplicationActivity extends Activity {
30 | private PHHueSDK phHueSDK;
31 | private static final int MAX_HUE=65535;
32 | public static final String TAG = "QuickStart";
33 |
34 | @Override
35 | public void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | setTitle(R.string.app_name);
38 | setContentView(R.layout.activity_main);
39 | phHueSDK = PHHueSDK.create();
40 | Button randomButton;
41 | randomButton = (Button) findViewById(R.id.buttonRand);
42 | randomButton.setOnClickListener(new OnClickListener() {
43 |
44 | @Override
45 | public void onClick(View v) {
46 | randomLights();
47 | }
48 |
49 | });
50 |
51 | }
52 |
53 | public void randomLights() {
54 | PHBridge bridge = phHueSDK.getSelectedBridge();
55 |
56 | List allLights = bridge.getResourceCache().getAllLights();
57 | Random rand = new Random();
58 |
59 | for (PHLight light : allLights) {
60 | PHLightState lightState = new PHLightState();
61 | lightState.setHue(rand.nextInt(MAX_HUE));
62 | // To validate your lightstate is valid (before sending to the bridge) you can use:
63 | // String validState = lightState.validateState();
64 | bridge.updateLightState(light, lightState, listener);
65 | // bridge.updateLightState(light, lightState); // If no bridge response is required then use this simpler form.
66 | }
67 | }
68 | // If you want to handle the response from the bridge, create a PHLightListener object.
69 | PHLightListener listener = new PHLightListener() {
70 |
71 | @Override
72 | public void onSuccess() {
73 | }
74 |
75 | @Override
76 | public void onStateUpdate(Map arg0, List arg1) {
77 | Log.w(TAG, "Light has updated");
78 | }
79 |
80 | @Override
81 | public void onError(int arg0, String arg1) {}
82 |
83 | @Override
84 | public void onReceivingLightDetails(PHLight arg0) {}
85 |
86 | @Override
87 | public void onReceivingLights(List arg0) {}
88 |
89 | @Override
90 | public void onSearchComplete() {}
91 | };
92 |
93 | @Override
94 | protected void onDestroy() {
95 | PHBridge bridge = phHueSDK.getSelectedBridge();
96 | if (bridge != null) {
97 |
98 | if (phHueSDK.isHeartbeatEnabled(bridge)) {
99 | phHueSDK.disableHeartbeat(bridge);
100 | }
101 |
102 | phHueSDK.disconnect(bridge);
103 | super.onDestroy();
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/QuickStartApp/src/com/philips/lighting/data/AccessPointListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.philips.lighting.data;
2 |
3 | import java.util.List;
4 |
5 | import android.content.Context;
6 | import android.graphics.Color;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.BaseAdapter;
11 | import android.widget.TextView;
12 |
13 | import com.philips.lighting.hue.sdk.PHAccessPoint;
14 | import com.philips.lighting.quickstart.R;
15 |
16 | /**
17 | * This class provides adapter view for a list of Found Bridges.
18 | *
19 | * @author SteveyO.
20 | */
21 | public class AccessPointListAdapter extends BaseAdapter {
22 | private LayoutInflater mInflater;
23 | private List accessPoints;
24 |
25 | /**
26 | * View holder class for access point list.
27 | *
28 | * @author SteveyO.
29 | */
30 | class BridgeListItem {
31 | private TextView bridgeIp;
32 | private TextView bridgeMac;
33 | }
34 |
35 | /**
36 | * creates instance of {@link AccessPointListAdapter} class.
37 | *
38 | * @param context the Context object.
39 | * @param accessPoints an array list of {@link PHAccessPoint} object to display.
40 | */
41 | public AccessPointListAdapter(Context context, List accessPoints) {
42 | // Cache the LayoutInflate to avoid asking for a new one each time.
43 | mInflater = LayoutInflater.from(context);
44 | this.accessPoints = accessPoints;
45 | }
46 |
47 | /**
48 | * Get a View that displays the data at the specified position in the data set.
49 | *
50 | * @param position The row index.
51 | * @param convertView The row view.
52 | * @param parent The view group.
53 | * @return A View corresponding to the data at the specified position.
54 | */
55 | public View getView(final int position, View convertView, ViewGroup parent) {
56 |
57 | BridgeListItem item;
58 |
59 | if (convertView == null) {
60 | convertView = mInflater.inflate(R.layout.selectbridge_item, null);
61 |
62 | item = new BridgeListItem();
63 | item.bridgeMac = (TextView) convertView.findViewById(R.id.bridge_mac);
64 | item.bridgeIp = (TextView) convertView.findViewById(R.id.bridge_ip);
65 |
66 | convertView.setTag(item);
67 | } else {
68 | item = (BridgeListItem) convertView.getTag();
69 | }
70 | PHAccessPoint accessPoint = accessPoints.get(position);
71 | item.bridgeIp.setTextColor(Color.BLACK);
72 | item.bridgeIp.setText(accessPoint.getIpAddress());
73 | item.bridgeMac.setTextColor(Color.DKGRAY);
74 | item.bridgeMac.setText(accessPoint.getMacAddress());
75 |
76 | return convertView;
77 | }
78 |
79 | /**
80 | * Get the row id associated with the specified position in the list.
81 | *
82 | * @param position The row index.
83 | * @return The id of the item at the specified position.
84 | */
85 | @Override
86 | public long getItemId(int position) {
87 | return 0;
88 | }
89 |
90 | /**
91 | * How many items are in the data set represented by this Adapter.
92 | *
93 | * @return Count of items.
94 | */
95 | @Override
96 | public int getCount() {
97 | return accessPoints.size();
98 | }
99 |
100 | /**
101 | * Get the data item associated with the specified position in the data set.
102 | *
103 | * @param position Position of the item whose data we want within the adapter's data set.
104 | * @return The data at the specified position.
105 | */
106 | @Override
107 | public Object getItem(int position) {
108 | return accessPoints.get(position);
109 | }
110 |
111 | /**
112 | * Update date of the list view and refresh listview.
113 | *
114 | * @param accessPoints An array list of {@link PHAccessPoint} objects.
115 | */
116 | public void updateData(List accessPoints) {
117 | this.accessPoints = accessPoints;
118 | notifyDataSetChanged();
119 | }
120 |
121 | }
--------------------------------------------------------------------------------
/QuickStartApp/src/com/philips/lighting/quickstart/PHPushlinkActivity.java:
--------------------------------------------------------------------------------
1 | package com.philips.lighting.quickstart;
2 |
3 | import java.util.List;
4 |
5 | import android.app.Activity;
6 | import android.app.AlertDialog;
7 | import android.content.DialogInterface;
8 | import android.os.Bundle;
9 | import android.widget.ProgressBar;
10 |
11 | import com.philips.lighting.hue.sdk.PHAccessPoint;
12 | import com.philips.lighting.hue.sdk.PHHueSDK;
13 | import com.philips.lighting.hue.sdk.PHMessageType;
14 | import com.philips.lighting.hue.sdk.PHSDKListener;
15 | import com.philips.lighting.model.PHBridge;
16 | import com.philips.lighting.model.PHHueParsingError;
17 |
18 | /**
19 | * Activity which gives hint for manual pushlink. needs to add in manifest file
21 | *
22 | *
23 | */
24 |
25 | public class PHPushlinkActivity extends Activity {
26 | private ProgressBar pbar;
27 | private static final int MAX_TIME=30;
28 | private PHHueSDK phHueSDK;
29 | private boolean isDialogShowing;
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | setContentView(R.layout.pushlink);
35 | setTitle(R.string.txt_pushlink);
36 | isDialogShowing=false;
37 | phHueSDK = PHHueSDK.getInstance();
38 |
39 | pbar = (ProgressBar) findViewById(R.id.countdownPB);
40 | pbar.setMax(MAX_TIME);
41 |
42 | phHueSDK.getNotificationManager().registerSDKListener(listener);
43 | }
44 |
45 | @Override
46 | protected void onStop(){
47 | super.onStop();
48 | phHueSDK.getNotificationManager().unregisterSDKListener(listener);
49 | }
50 |
51 | public void incrementProgress() {
52 | pbar.incrementProgressBy(1);
53 | }
54 |
55 | private PHSDKListener listener = new PHSDKListener() {
56 |
57 | @Override
58 | public void onAccessPointsFound(List arg0) {}
59 |
60 | @Override
61 | public void onAuthenticationRequired(PHAccessPoint arg0) {}
62 |
63 | @Override
64 | public void onBridgeConnected(PHBridge bridge, String username) {}
65 |
66 | @Override
67 | public void onCacheUpdated(List arg0, PHBridge bridge) {}
68 |
69 | @Override
70 | public void onConnectionLost(PHAccessPoint arg0) {}
71 |
72 | @Override
73 | public void onConnectionResumed(PHBridge arg0) {}
74 |
75 | @Override
76 | public void onError(int code, final String message) {
77 | if (code == PHMessageType.PUSHLINK_BUTTON_NOT_PRESSED) {
78 | incrementProgress();
79 | }
80 | else if (code == PHMessageType.PUSHLINK_AUTHENTICATION_FAILED) {
81 | incrementProgress();
82 |
83 | if (!isDialogShowing) {
84 | isDialogShowing=true;
85 | PHPushlinkActivity.this.runOnUiThread(new Runnable() {
86 |
87 | @Override
88 | public void run() {
89 | AlertDialog.Builder builder = new AlertDialog.Builder(PHPushlinkActivity.this);
90 | builder.setMessage(message).setNeutralButton(R.string.btn_ok,
91 | new DialogInterface.OnClickListener() {
92 | public void onClick(DialogInterface dialog, int id) {
93 | finish();
94 | }
95 | });
96 |
97 | builder.create();
98 | builder.show();
99 | }
100 | });
101 | }
102 |
103 | }
104 |
105 | } // End of On Error
106 |
107 | @Override
108 | public void onParsingErrors(List parsingErrorsList) {}
109 | };
110 |
111 | @Override
112 | public void onDestroy() {
113 | super.onDestroy();
114 | if (listener !=null) {
115 | phHueSDK.getNotificationManager().unregisterSDKListener(listener);
116 | }
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/JavaDesktopApp/src/com/philips/lighting/gui/LightColoursFrame.java:
--------------------------------------------------------------------------------
1 | package com.philips.lighting.gui;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.Color;
5 | import java.awt.Container;
6 | import java.awt.Dimension;
7 | import java.awt.event.ActionEvent;
8 | import java.awt.event.ActionListener;
9 | import java.util.List;
10 |
11 | import javax.swing.BorderFactory;
12 | import javax.swing.DefaultListModel;
13 | import javax.swing.JButton;
14 | import javax.swing.JColorChooser;
15 | import javax.swing.JFrame;
16 | import javax.swing.JList;
17 | import javax.swing.JPanel;
18 | import javax.swing.JScrollPane;
19 | import javax.swing.border.Border;
20 |
21 | import com.philips.lighting.hue.sdk.PHHueSDK;
22 | import com.philips.lighting.hue.sdk.utilities.PHUtilities;
23 | import com.philips.lighting.model.PHBridge;
24 | import com.philips.lighting.model.PHLight;
25 | import com.philips.lighting.model.PHLightState;
26 | /**
27 | * LightColoursFrame.java
28 | * An example showing how to change Bulb Colours using a JColorChooser.
29 | *
30 | */
31 | public class LightColoursFrame extends JFrame {
32 |
33 | private static final long serialVersionUID = -3830092035262367974L;
34 | private PHHueSDK phHueSDK;
35 |
36 | private JList lightIdentifiersList;
37 | private List allLights;
38 |
39 | public LightColoursFrame() {
40 | super("Bulb Colour Changer");
41 |
42 | // The the HueSDK singleton.
43 | phHueSDK = PHHueSDK.getInstance();
44 |
45 | Container content = getContentPane();
46 |
47 | // Get the selected bridge.
48 | PHBridge bridge = phHueSDK.getSelectedBridge();
49 |
50 | // To get lights use the Resource Cache.
51 | allLights = bridge.getResourceCache().getAllLights();
52 |
53 | DefaultListModel sampleModel = new DefaultListModel();
54 |
55 | for (PHLight light : allLights) {
56 | sampleModel.addElement(light.getIdentifier() + " " + light.getName() );
57 | }
58 |
59 | lightIdentifiersList = new JList(sampleModel);
60 | lightIdentifiersList.setVisibleRowCount(4);
61 | lightIdentifiersList.setSelectedIndex(0);
62 |
63 | JScrollPane listPane = new JScrollPane(lightIdentifiersList);
64 | listPane.setPreferredSize(new Dimension(300,100));
65 |
66 | JPanel listPanel = new JPanel();
67 | listPanel.setBackground(Color.white);
68 |
69 | Border listPanelBorder = BorderFactory.createTitledBorder("My Lights");
70 | listPanel.setBorder(listPanelBorder);
71 | listPanel.add(listPane);
72 | content.add(listPanel, BorderLayout.CENTER);
73 |
74 | JButton changeColourButton = new JButton("Change Bulb Colour");
75 | changeColourButton.addActionListener(new ColourChanger());
76 |
77 | Border buttonPanelBorder = BorderFactory.createTitledBorder("Change Selected");
78 | JPanel buttonPanel = new JPanel();
79 | buttonPanel.setBackground(Color.white);
80 | buttonPanel.setBorder(buttonPanelBorder);
81 | buttonPanel.add(changeColourButton);
82 |
83 | content.add(buttonPanel, BorderLayout.SOUTH);
84 | setPreferredSize(new Dimension(400,250));
85 | pack();
86 | setVisible(true);
87 | }
88 |
89 | private class ColourChanger implements ActionListener {
90 | public void actionPerformed(ActionEvent event) {
91 |
92 | Color lightColour = JColorChooser.showDialog(getContentPane(), "Choose Bulb Color", getBackground());
93 |
94 | if (lightColour !=null) {
95 | int selectedBulb = lightIdentifiersList.getSelectedIndex();
96 | if (selectedBulb !=-1) {
97 | int selectedIndex= lightIdentifiersList.getSelectedIndex();
98 | String lightIdentifer = allLights.get(selectedIndex).getIdentifier();
99 |
100 | PHLightState lightState = new PHLightState();
101 | float xy[] = PHUtilities.calculateXYFromRGB(lightColour.getRed(), lightColour.getGreen(), lightColour.getBlue(), "LCT001");
102 | lightState.setX(xy[0]);
103 | lightState.setY(xy[1]);
104 |
105 | phHueSDK.getSelectedBridge().updateLightState(lightIdentifer, lightState, null); // null is passed here as we are not interested in the response from the Bridge.
106 |
107 | }
108 | }
109 | }
110 | }
111 |
112 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # This repository is deprecated.
2 |
3 | **Deprecation – Philips Hue SDK**
4 |
5 | We have decided to **deprecate the hue SDK** effective **as of July 1st 2019**. This means there will be no new SDK releases except for critical updates (e.g. security) which will be maintained for one additional year. Existing Hue SDK client applications will continue to work normally but we can no longer guarantee long term compatibility with future Hue software. We strongly recommend Hue SDK users to migrate to Hue API which remains up-to-date and supported.
6 |
7 | **FAQ**
8 |
9 | **Why is this changing?** Philips Hue has decided to focus its resources into improving the Hue API and building new features. The usage of the SDK has been declining as has our own dependence on it so we feel it is more beneficial to focus on building directly on the Hue API.
10 |
11 | **Who’s Impacted?** Anyone who is leveraging the Philips Hue SDK.
12 |
13 | **Who’s Not Impacted?** Anyone who is not utilizing the Philips Hue SDK.
14 |
15 | **What should you use instead?** Philips Hue API
16 |
17 | **Next steps?** Migration code samples and best practice blogs by Hue Developer Program.
18 |
19 | **Question?** Contact us! https://developers.meethue.com/support/
20 |
21 | **See also:** https://developers.meethue.com/deprecation-philips-hue-sdk/
22 |
23 | -----
24 |
25 | The Hue SDK by Philips
26 | ===============
27 | (c) Copyright Philips 2012-2014
28 | Java SDK Guide
29 | ----------------
30 | Full documentation and code examples for using the hue Java SDK can be found on our developer portal:
31 |
32 | http://developers.meethue.com/documentation/java-multi-platform-and-android-sdk
33 |
34 | and:
35 |
36 | http://www.developers.meethue.com/documentation/java-sdk-getting-started
37 |
38 |
39 | Our new developer portal also contains interviews with 3rd party developers, lists of Android 3rd party hue apps as well as instructions on how to promote your app.
40 | Your 3rd party Android apps are now promoted in the official Philips hue app meaning even greater exposure!
41 |
42 | http://developers.meethue.com/
43 |
44 |
45 | Acknowledgements
46 | ----------------
47 | Please adhere to any third party licenses that are applicable on this SDK when building applications with our SDK or using the QuickStart applications as your base (see ACKNOWLEDGEMENTS file in this repository, for applicable licenses).
48 |
49 |
50 | Philips releases this SDK with friendly house rules. These friendly house rules are part of a legal framework; this to protect both the developers and hue. The friendly house rules cover e.g. the naming of Philips and of hue which can only be used as a reference (a true and honest statement) and not as a an brand or identity. Also covered is that the hue SDK and API can only be used for hue and for no other application or product. Very common sense friendly rules that are common practice amongst leading brands that have released their SDK’s.
51 |
52 |
53 | Copyright (c) 2012- 2013, Philips Electronics N.V. All rights reserved.
54 |
55 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
56 |
57 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
58 |
59 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
60 |
61 | * Neither the name of Philips Electronics N.V. , nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
62 |
63 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOTLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FORA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER ORCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, ORPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDINGNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THISSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Android/Java SDK Changelog
2 |
3 | ## 1.22.0 (2017-10-21)
4 | Changes
5 | - Fixed serialization issue in PHGroup
6 |
7 | ## 1.20.2 (2017-08-19)
8 | Changes
9 | - Changed Java compliance level to 1.6
10 |
11 | ## 1.20.1 (2017-08-18)
12 | Changes
13 | - Critical bug fix regarding missing methods and classes
14 |
15 | ## 1.20 (2017-08-04)
16 | Changes
17 | - Critical bug fix regarding 1.20 bridge firmware and commissioning sensors and switches.
18 |
19 | ## 1.11.2 (2015-12-22)
20 | Changes
21 | - Minor bug fix when getting the brightness increment from a schedule.
22 |
23 | ## 1.11.1 (2015-12-21)
24 | Changes
25 | - Minor bug fix when creating a scene on 1.11 bridge.
26 |
27 | ## 1.11 (2015-12-18)
28 | Changes
29 | - Implemented API 1.11 changes. In particular minor modifications to PHGroups (for type Room) and many modifications to the Scenes API. See the Using Scenes page for more info.
30 | - Added ability to make HTTP calls directly in the SDK in order to use the Hue Rest API. See Using Http Requests page for more info.
31 |
32 | ## 1.10.1 (2015-12-07)
33 | Changes
34 | - Can now create a PHGroup with an empty constructor (more logical as when you create a group the group identifier is not known).
35 | - Minor bug fix, when renaming lights removed /name from the URL (works on the bridge anyway, but not correct).
36 |
37 | ## 1.10 (2015-11-09)
38 | Changes
39 | - Implemented Bridge API 1.9 and 1.10 features. Bridge Backup (Factorynew + replacesbridgeid), Uniqueid, Luminaireuniqueid and touchlink.
40 |
41 | ## 1.8.3beta (2015-09-25)
42 | Changes
43 | - Minor fix to huelocalsdk.jar so the IP Scan only finds Hue Bridges.
44 |
45 | ## 1.8.2beta (2015-09-03)
46 | Changes
47 | - Fix to huelocalsdk.jar so DestroySDK method works if Pushlinking has been called (i.e. All Pushlinking Threads are now correctly killed).
48 |
49 | ## 1.8.1beta (2015-07-23)
50 | Changes
51 | - Removed ability to create your own whitelist username (as will be removed in the bridge in the future).
52 | Important!! If you are using the QuickStart app as your base code and updating the Java SDK, please check out the small
53 | but important changes (to setting the username) in PHHomeActivity.java , HueSharedPreferences.java and PHPushlinkActivity.java
54 |
55 | ## 1.8beta (2015-06-30)
56 | Changes
57 | - Delete devices added (sensors and lights)
58 | - New Clip Increment Feature (new increment* attributes in PHLightState)
59 | - New bridge fields added (e.g .ModelId, Type in PHGroup, Manufacturername, UniqueId in PHLight, Bridge Id)
60 | - New light Models added for Color Conversions (e.g .HueGo).
61 | - UPNP search now returns BridgeId
62 | - All bug fixes since previous release.
63 |
64 | ## 1.3.1beta (2015-03-20)
65 | Changes
66 | - Fix to kill heartbeat manager when exiting the SDK (after calling destroySDKMethod).
67 | This prevents a NPE when an Android App is destroyed but the GC has not fully released all SDK resources.
68 |
69 | ## 1.3.1beta (2015-02-19)
70 | Changes
71 | - Fix to kill hanging timer thread when exiting the SDK (after calling destroySDKMethod).
72 |
73 | ## 1.3beta (2014-09-12)
74 | Features:
75 |
76 | - Java SDK now supports 1.3 bridges.
77 | - Added support for sensors
78 | - Added support for rules
79 | - Added multi resources heartbeat (ie. can run full heartbeat or select your resource, e.g. lights).
80 | - Added Feature Based parsing (meaning the SDK checks which bridge version is running and sends commands appropriately).
81 |
82 | Changes:
83 |
84 | - API improvements
85 | - Bug fixes
86 | - Removed sample app as no longer supported. Code examples are now on our developer portal.
87 |
88 | Notes:
89 | - The SDK is fully backwards compatible but updating your app to use the new SDK will result in a few compilation errors. However, this are all minor and can be easily fixed. For example PHSDKListener now implements
90 | onParsingErrors, onCacheUpdated signature has changed (from an int to a List)
91 |
92 | ## 1.1.2beta (2014-01-02)
93 | Changes:
94 |
95 | - Simplified the code/app. PHAccessPointListActivity/Adapter class merged into PHHomeActivity, PHHomeActiviy now displays available bridges so now only 1 main PHSDKListener object.
96 | - Added IPScan fallback code in case bridge search (upnp) fails.
97 | - Removed unused layouts.
98 |
99 | ## 1.1.1beta (2013-12-05)
100 |
101 | Features:
102 |
103 | - The SDK is now PLATFORM INDEPENDENT! The 2.jars (huelocalsdk.jar and sdkresources.jar) can now be used in any Java Desktop project as well as in Android projects.
104 |
105 | Changes:
106 |
107 | - QuickStart and SampleApp now persist data in Shared Preferences.
108 | - QuickStart and SampleApp now automatically connect to the last connected bridge (last connected IP Address is persisted).
109 | - Whitelist username is now a 16 character random string. This is persisted in the Shared Preferences.
110 | - Refactored PHHomeActivity, PHPushlinkActivity and PHAccessPointListActivity due to Platform Independence changes.
111 | - Removed all Android specific code from the SDK. As a result backwards compatibility with 1.1 has been lost, however it is easy to fix.
112 | - Added IPScan functionality which can be used as a fallback if the UPnP/portal search fails to find any bridges.
113 |
114 | ## 1.1 (2013-09-22)
115 |
116 | The Android SDK 1.1 is publicly released.
117 |
118 | Features:
119 |
120 | - Android SDK released. Includes all functionality to control your hue lights aswell as automatic bridge detection.
121 | - QuickStart App released, containing minimal functionality to connect to a bridge and for getting started. Ideal for devs to start programming their Hue Apps.
122 | - Sample App released, showing all the bridge functionality. e.g. Groups, Schedules, Configuration, Lights, Scenes.
--------------------------------------------------------------------------------
/JavaDesktopApp/src/com/philips/lighting/gui/DesktopView.java:
--------------------------------------------------------------------------------
1 | package com.philips.lighting.gui;
2 |
3 | import java.awt.BorderLayout;
4 | import java.awt.Dimension;
5 | import java.awt.GridLayout;
6 | import java.awt.event.ActionEvent;
7 | import java.awt.event.ActionListener;
8 |
9 | import javax.swing.JButton;
10 | import javax.swing.JFrame;
11 | import javax.swing.JLabel;
12 | import javax.swing.JOptionPane;
13 | import javax.swing.JPanel;
14 | import javax.swing.JProgressBar;
15 | import javax.swing.JTextField;
16 |
17 | import layout.TableLayout;
18 |
19 | import com.philips.lighting.Controller;
20 | import com.philips.lighting.data.HueProperties;
21 |
22 | /**
23 | * DesktopView.java
24 | *
25 | * The main GUI showing last connected IP/Username and buttons for Finding Bridges and Changing the Hue Lights, once connected to a bridge.
26 | *
27 | */
28 | public class DesktopView extends JFrame {
29 |
30 | private static final long serialVersionUID = -7469471678945429320L;
31 | private Controller controller;
32 | private JButton setLightsButton;
33 | private JButton randomLightsButton;
34 | private JButton findBridgesButton;
35 | private JButton connectToLastBridgeButton;
36 | private JProgressBar findingBridgeProgressBar;
37 |
38 | private JTextField lastConnectedIP;
39 | private JTextField lastUserName;
40 |
41 | public DesktopView(){
42 | setTitle("Hue Desktop");
43 | JPanel mainPanel = new JPanel();
44 |
45 | // TODO - Move to another class
46 | JPanel controls = new JPanel();
47 | controls.setLayout(new GridLayout(2,3));
48 |
49 | findingBridgeProgressBar = new JProgressBar();
50 | findingBridgeProgressBar.setBorderPainted(false);
51 | findingBridgeProgressBar.setIndeterminate(true);
52 | findingBridgeProgressBar.setVisible(false);
53 |
54 | //Set up components preferred size
55 | String lastUsername = HueProperties.getUsername();
56 | String lastConnectedIPStr = HueProperties.getLastConnectedIP();
57 |
58 | JLabel labelLastConIP = new JLabel("Last Connected IP:");
59 | lastConnectedIP = new JTextField(lastConnectedIPStr);
60 |
61 | lastConnectedIP.setEditable(false);
62 | JLabel labelLastUsername = new JLabel("Last UserName:");
63 | lastUserName = new JTextField(lastUsername);
64 | lastUserName.setEditable(false);
65 | findBridgesButton = new JButton("Find New Bridges");
66 | findBridgesButton.addActionListener(new ActionListener() {
67 |
68 | @Override
69 | public void actionPerformed(ActionEvent arg0) {
70 | findBridgesButton.setEnabled(false);
71 | connectToLastBridgeButton.setEnabled(false);
72 | controller.findBridges();
73 | findingBridgeProgressBar.setBorderPainted(true);
74 | findingBridgeProgressBar.setVisible(true);
75 | }
76 | });
77 |
78 | connectToLastBridgeButton = new JButton("Auto Connect");
79 | connectToLastBridgeButton.addActionListener(new ActionListener() {
80 |
81 | @Override
82 | public void actionPerformed(ActionEvent ae) {
83 | if (controller.connectToLastKnownAccessPoint()) {
84 | connectToLastBridgeButton.setEnabled(false);
85 | findBridgesButton.setEnabled(false);
86 | findingBridgeProgressBar.setBorderPainted(true);
87 | findingBridgeProgressBar.setVisible(true);
88 | }
89 | }
90 | });
91 |
92 |
93 | setLightsButton = new JButton("Change Light Colours");
94 | setLightsButton.setEnabled(false);
95 | setLightsButton.addActionListener(new ActionListener() {
96 |
97 | @Override
98 | public void actionPerformed(ActionEvent arg0) {
99 | controller.showControlLightsWindow();
100 | }
101 | });
102 |
103 | randomLightsButton = new JButton("Randomize Lights");
104 | randomLightsButton.setEnabled(false);
105 | randomLightsButton.addActionListener(new ActionListener() {
106 |
107 | @Override
108 | public void actionPerformed(ActionEvent arg0) {
109 | controller.randomLights();
110 | }
111 | });
112 |
113 | double border = 10;
114 | double size[][] =
115 | {{border, 160, 20, 300, 20, 160}, // Columns
116 | {border, 26, 10, 26, 26, 26,6,26}}; // Rows
117 |
118 | mainPanel.setLayout (new TableLayout(size));
119 |
120 |
121 | mainPanel.add(labelLastConIP, " 1, 1");
122 | mainPanel.add(lastConnectedIP, " 3, 1");
123 |
124 | mainPanel.add(labelLastUsername, " 1, 3");
125 | mainPanel.add(lastUserName, " 3, 3");
126 |
127 | mainPanel.add(findingBridgeProgressBar, " 3, 5");
128 |
129 | mainPanel.add(connectToLastBridgeButton, " 5, 1");
130 | mainPanel.add(findBridgesButton, " 5, 3");
131 |
132 | mainPanel.add(randomLightsButton, " 5, 5");
133 | mainPanel.add(setLightsButton, " 5, 7");
134 |
135 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
136 | setPreferredSize(new Dimension(700,270));
137 |
138 | getContentPane().add(new JLabel(" An example Java/Swing Desktop Application to control your Hue Lights."), BorderLayout.NORTH);
139 | getContentPane().add(mainPanel, BorderLayout.CENTER);
140 |
141 |
142 | //4. Size the frame.
143 | pack();
144 | setLocationRelativeTo(null); // Centre the window.
145 | setVisible(true);
146 |
147 | }
148 |
149 | public void setController(Controller controller) {
150 | this.controller = controller;
151 | }
152 |
153 | public JButton getSetLightsButton() {
154 | return setLightsButton;
155 | }
156 |
157 | public JButton getRandomLightsButton() {
158 | return randomLightsButton;
159 | }
160 |
161 | public JButton getFindBridgesButton() {
162 | return findBridgesButton;
163 | }
164 |
165 | public JButton getConnectToLastBridgeButton() {
166 | return connectToLastBridgeButton;
167 | }
168 |
169 | public void showDialog(String message) {
170 | JOptionPane.showMessageDialog(this, message);
171 | }
172 |
173 | public JProgressBar getFindingBridgeProgressBar() {
174 | return findingBridgeProgressBar;
175 | }
176 |
177 | public JTextField getLastConnectedIP() {
178 | return lastConnectedIP;
179 | }
180 |
181 | public JTextField getLastUserName() {
182 | return lastUserName;
183 | }
184 | }
--------------------------------------------------------------------------------
/JavaDesktopApp/src/com/philips/lighting/Controller.java:
--------------------------------------------------------------------------------
1 | package com.philips.lighting;
2 |
3 | import java.util.List;
4 | import java.util.Random;
5 |
6 | import javax.swing.JDialog;
7 |
8 | import com.philips.lighting.data.HueProperties;
9 | import com.philips.lighting.gui.AccessPointList;
10 | import com.philips.lighting.gui.DesktopView;
11 | import com.philips.lighting.gui.LightColoursFrame;
12 | import com.philips.lighting.gui.PushLinkFrame;
13 | import com.philips.lighting.hue.sdk.PHAccessPoint;
14 | import com.philips.lighting.hue.sdk.PHBridgeSearchManager;
15 | import com.philips.lighting.hue.sdk.PHHueSDK;
16 | import com.philips.lighting.hue.sdk.PHMessageType;
17 | import com.philips.lighting.hue.sdk.PHSDKListener;
18 | import com.philips.lighting.model.PHBridge;
19 | import com.philips.lighting.model.PHBridgeResourcesCache;
20 | import com.philips.lighting.model.PHHueError;
21 | import com.philips.lighting.model.PHHueParsingError;
22 | import com.philips.lighting.model.PHLight;
23 | import com.philips.lighting.model.PHLightState;
24 |
25 | public class Controller {
26 |
27 | private PHHueSDK phHueSDK;
28 | private DesktopView desktopView;
29 |
30 | private PushLinkFrame pushLinkDialog;
31 | private LightColoursFrame lightColoursFrame;
32 |
33 | private static final int MAX_HUE=65535;
34 | private Controller instance;
35 |
36 | public Controller(DesktopView view) {
37 | this.desktopView = view;
38 | this.phHueSDK = PHHueSDK.getInstance();
39 | this.instance = this;
40 | }
41 |
42 | public void findBridges() {
43 | phHueSDK = PHHueSDK.getInstance();
44 | PHBridgeSearchManager sm = (PHBridgeSearchManager) phHueSDK.getSDKService(PHHueSDK.SEARCH_BRIDGE);
45 | sm.search(true, true);
46 | }
47 |
48 | private PHSDKListener listener = new PHSDKListener() {
49 |
50 | @Override
51 | public void onAccessPointsFound(List accessPointsList) {
52 | desktopView.getFindingBridgeProgressBar().setVisible(false);
53 | AccessPointList accessPointList = new AccessPointList(accessPointsList, instance);
54 | accessPointList.setVisible(true);
55 | accessPointList.setLocationRelativeTo(null); // Centre the AccessPointList Frame
56 | }
57 |
58 | @Override
59 | public void onAuthenticationRequired(PHAccessPoint accessPoint) {
60 | // Start the Pushlink Authentication.
61 | desktopView.getFindingBridgeProgressBar().setVisible(false);
62 | phHueSDK.startPushlinkAuthentication(accessPoint);
63 |
64 | pushLinkDialog = new PushLinkFrame(instance);
65 | pushLinkDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
66 | pushLinkDialog.setModal(true);
67 | pushLinkDialog.setLocationRelativeTo(null); // Center the dialog.
68 | pushLinkDialog.setVisible(true);
69 |
70 | }
71 |
72 | @Override
73 | public void onBridgeConnected(PHBridge bridge, String username) {
74 | phHueSDK.setSelectedBridge(bridge);
75 | phHueSDK.enableHeartbeat(bridge, PHHueSDK.HB_INTERVAL);
76 | desktopView.getFindingBridgeProgressBar().setVisible(false);
77 | String lastIpAddress = bridge.getResourceCache().getBridgeConfiguration().getIpAddress();
78 | HueProperties.storeUsername(username);
79 | HueProperties.storeLastIPAddress(lastIpAddress);
80 | HueProperties.saveProperties();
81 | // Update the GUI.
82 | desktopView.getLastConnectedIP().setText(lastIpAddress);
83 | desktopView.getLastUserName().setText(username);
84 | // Close the PushLink dialog (if it is showing).
85 | if (pushLinkDialog!=null && pushLinkDialog.isShowing()) {
86 | pushLinkDialog.setVisible(false);
87 | }
88 | // Enable the Buttons/Controls to change the hue bulbs.s
89 | desktopView.getRandomLightsButton().setEnabled(true);
90 | desktopView.getSetLightsButton().setEnabled(true);
91 |
92 | }
93 |
94 | @Override
95 | public void onCacheUpdated(List arg0, PHBridge arg1) {
96 | }
97 |
98 | @Override
99 | public void onConnectionLost(PHAccessPoint arg0) {
100 | }
101 |
102 | @Override
103 | public void onConnectionResumed(PHBridge arg0) {
104 | }
105 |
106 | @Override
107 | public void onError(int code, final String message) {
108 |
109 | if (code == PHHueError.BRIDGE_NOT_RESPONDING) {
110 | desktopView.getFindingBridgeProgressBar().setVisible(false);
111 | desktopView.getFindBridgesButton().setEnabled(true);
112 | desktopView.getConnectToLastBridgeButton().setEnabled(true);
113 | desktopView.showDialog(message);
114 | }
115 | else if (code == PHMessageType.PUSHLINK_BUTTON_NOT_PRESSED) {
116 | pushLinkDialog.incrementProgress();
117 | }
118 | else if (code == PHMessageType.PUSHLINK_AUTHENTICATION_FAILED) {
119 | if (pushLinkDialog.isShowing()) {
120 | pushLinkDialog.setVisible(false);
121 | desktopView.showDialog(message);
122 | }
123 | else {
124 | desktopView.showDialog(message);
125 | }
126 | desktopView.getFindBridgesButton().setEnabled(true);
127 | }
128 | else if (code == PHMessageType.BRIDGE_NOT_FOUND) {
129 | desktopView.getFindingBridgeProgressBar().setVisible(false);
130 | desktopView.getFindBridgesButton().setEnabled(true);
131 | desktopView.showDialog(message);
132 | }
133 | }
134 |
135 | @Override
136 | public void onParsingErrors(List parsingErrorsList) {
137 | for (PHHueParsingError parsingError: parsingErrorsList) {
138 | System.out.println("ParsingError : " + parsingError.getMessage());
139 | }
140 | }
141 | };
142 |
143 | public PHSDKListener getListener() {
144 | return listener;
145 | }
146 |
147 | public void setListener(PHSDKListener listener) {
148 | this.listener = listener;
149 | }
150 |
151 | public void randomLights() {
152 | PHBridge bridge = phHueSDK.getSelectedBridge();
153 | PHBridgeResourcesCache cache = bridge.getResourceCache();
154 |
155 | List allLights = cache.getAllLights();
156 | Random rand = new Random();
157 |
158 | for (PHLight light : allLights) {
159 | PHLightState lightState = new PHLightState();
160 | lightState.setHue(rand.nextInt(MAX_HUE));
161 | bridge.updateLightState(light, lightState); // If no bridge response is required then use this simpler form.
162 | }
163 | }
164 |
165 | public void showControlLightsWindow() {
166 | if (lightColoursFrame == null) {
167 | lightColoursFrame = new LightColoursFrame();
168 | }
169 | lightColoursFrame.setLocationRelativeTo(null); // Centre window
170 | lightColoursFrame.setVisible(true);
171 | }
172 |
173 | /**
174 | * Connect to the last known access point.
175 | * This method is triggered by the Connect to Bridge button but it can equally be used to automatically connect to a bridge.
176 | *
177 | */
178 | public boolean connectToLastKnownAccessPoint() {
179 | String username = HueProperties.getUsername();
180 | String lastIpAddress = HueProperties.getLastConnectedIP();
181 |
182 | if (username==null || lastIpAddress == null) {
183 | desktopView.showDialog("Missing Last Username or Last IP. Last known connection not found.");
184 | return false;
185 | }
186 | PHAccessPoint accessPoint = new PHAccessPoint();
187 | accessPoint.setIpAddress(lastIpAddress);
188 | accessPoint.setUsername(username);
189 | phHueSDK.connect(accessPoint);
190 | return true;
191 | }
192 |
193 | public void enableFindBridgesButton() {
194 | desktopView.getFindBridgesButton().setEnabled(true);
195 | }
196 |
197 | public void showProgressBar() {
198 | desktopView.getFindingBridgeProgressBar().setVisible(true);
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/QuickStartApp/src/com/philips/lighting/quickstart/PHHomeActivity.java:
--------------------------------------------------------------------------------
1 | package com.philips.lighting.quickstart;
2 |
3 | import java.util.List;
4 |
5 | import android.app.Activity;
6 | import android.content.Intent;
7 | import android.os.Build;
8 | import android.os.Bundle;
9 | import android.util.Log;
10 | import android.view.Menu;
11 | import android.view.MenuItem;
12 | import android.view.View;
13 | import android.widget.AdapterView;
14 | import android.widget.AdapterView.OnItemClickListener;
15 | import android.widget.ListView;
16 |
17 | import com.philips.lighting.data.AccessPointListAdapter;
18 | import com.philips.lighting.data.HueSharedPreferences;
19 | import com.philips.lighting.hue.sdk.PHAccessPoint;
20 | import com.philips.lighting.hue.sdk.PHBridgeSearchManager;
21 | import com.philips.lighting.hue.sdk.PHHueSDK;
22 | import com.philips.lighting.hue.sdk.PHMessageType;
23 | import com.philips.lighting.hue.sdk.PHSDKListener;
24 | import com.philips.lighting.model.PHBridge;
25 | import com.philips.lighting.model.PHHueError;
26 | import com.philips.lighting.model.PHHueParsingError;
27 |
28 | /**
29 | * PHHomeActivity - The starting point in your own Hue App.
30 | *
31 | * For first time use, a Bridge search (UPNP) is performed and a list of all available bridges is displayed (and clicking one of them shows the PushLink dialog allowing authentication).
32 | * The last connected Bridge IP Address and Username are stored in SharedPreferences.
33 | *
34 | * For subsequent usage the app automatically connects to the last connected bridge.
35 | * When connected the MyApplicationActivity Activity is started. This is where you should start implementing your Hue App! Have fun!
36 | *
37 | * For explanation on key concepts visit: https://github.com/PhilipsHue/PhilipsHueSDK-Java-MultiPlatform-Android
38 | *
39 | *
40 | */
41 | public class PHHomeActivity extends Activity implements OnItemClickListener {
42 |
43 | private PHHueSDK phHueSDK;
44 | public static final String TAG = "QuickStart";
45 | private HueSharedPreferences prefs;
46 | private AccessPointListAdapter adapter;
47 |
48 | private boolean lastSearchWasIPScan = false;
49 |
50 | @Override
51 | protected void onCreate(Bundle savedInstanceState) {
52 | super.onCreate(savedInstanceState);
53 | setContentView(R.layout.bridgelistlinear);
54 |
55 | // Gets an instance of the Hue SDK.
56 | phHueSDK = PHHueSDK.create();
57 |
58 | // Set the Device Name (name of your app). This will be stored in your bridge whitelist entry.
59 | phHueSDK.setAppName("QuickStartApp");
60 | phHueSDK.setDeviceName(android.os.Build.MODEL);
61 |
62 | // Register the PHSDKListener to receive callbacks from the bridge.
63 | phHueSDK.getNotificationManager().registerSDKListener(listener);
64 |
65 | adapter = new AccessPointListAdapter(getApplicationContext(), phHueSDK.getAccessPointsFound());
66 |
67 | ListView accessPointList = (ListView) findViewById(R.id.bridge_list);
68 | accessPointList.setOnItemClickListener(this);
69 | accessPointList.setAdapter(adapter);
70 |
71 | // Try to automatically connect to the last known bridge. For first time use this will be empty so a bridge search is automatically started.
72 | prefs = HueSharedPreferences.getInstance(getApplicationContext());
73 | String lastIpAddress = prefs.getLastConnectedIPAddress();
74 | String lastUsername = prefs.getUsername();
75 |
76 | // Automatically try to connect to the last connected IP Address. For multiple bridge support a different implementation is required.
77 | if (lastIpAddress !=null && !lastIpAddress.equals("")) {
78 | PHAccessPoint lastAccessPoint = new PHAccessPoint();
79 | lastAccessPoint.setIpAddress(lastIpAddress);
80 | lastAccessPoint.setUsername(lastUsername);
81 |
82 | if (!phHueSDK.isAccessPointConnected(lastAccessPoint)) {
83 | PHWizardAlertDialog.getInstance().showProgressDialog(R.string.connecting, PHHomeActivity.this);
84 | phHueSDK.connect(lastAccessPoint);
85 | }
86 | }
87 | else { // First time use, so perform a bridge search.
88 | doBridgeSearch();
89 | }
90 | }
91 |
92 | @Override
93 | public boolean onCreateOptionsMenu(Menu menu) {
94 | Log.w(TAG, "Inflating home menu");
95 | // Inflate the menu; this adds items to the action bar if it is present.
96 | getMenuInflater().inflate(R.menu.home, menu);
97 | return true;
98 | }
99 |
100 |
101 | // Local SDK Listener
102 | private PHSDKListener listener = new PHSDKListener() {
103 |
104 | @Override
105 | public void onAccessPointsFound(List accessPoint) {
106 | Log.w(TAG, "Access Points Found. " + accessPoint.size());
107 |
108 | PHWizardAlertDialog.getInstance().closeProgressDialog();
109 | if (accessPoint != null && accessPoint.size() > 0) {
110 | phHueSDK.getAccessPointsFound().clear();
111 | phHueSDK.getAccessPointsFound().addAll(accessPoint);
112 |
113 | runOnUiThread(new Runnable() {
114 | @Override
115 | public void run() {
116 | adapter.updateData(phHueSDK.getAccessPointsFound());
117 | }
118 | });
119 |
120 | }
121 |
122 | }
123 |
124 | @Override
125 | public void onCacheUpdated(List arg0, PHBridge bridge) {
126 | Log.w(TAG, "On CacheUpdated");
127 |
128 | }
129 |
130 | @Override
131 | public void onBridgeConnected(PHBridge b, String username) {
132 | phHueSDK.setSelectedBridge(b);
133 | phHueSDK.enableHeartbeat(b, PHHueSDK.HB_INTERVAL);
134 | phHueSDK.getLastHeartbeat().put(b.getResourceCache().getBridgeConfiguration() .getIpAddress(), System.currentTimeMillis());
135 | prefs.setLastConnectedIPAddress(b.getResourceCache().getBridgeConfiguration().getIpAddress());
136 | prefs.setUsername(username);
137 | PHWizardAlertDialog.getInstance().closeProgressDialog();
138 | startMainActivity();
139 | }
140 |
141 | @Override
142 | public void onAuthenticationRequired(PHAccessPoint accessPoint) {
143 | Log.w(TAG, "Authentication Required.");
144 | phHueSDK.startPushlinkAuthentication(accessPoint);
145 | startActivity(new Intent(PHHomeActivity.this, PHPushlinkActivity.class));
146 |
147 | }
148 |
149 | @Override
150 | public void onConnectionResumed(PHBridge bridge) {
151 | if (PHHomeActivity.this.isFinishing())
152 | return;
153 |
154 | Log.v(TAG, "onConnectionResumed" + bridge.getResourceCache().getBridgeConfiguration().getIpAddress());
155 | phHueSDK.getLastHeartbeat().put(bridge.getResourceCache().getBridgeConfiguration().getIpAddress(), System.currentTimeMillis());
156 | for (int i = 0; i < phHueSDK.getDisconnectedAccessPoint().size(); i++) {
157 |
158 | if (phHueSDK.getDisconnectedAccessPoint().get(i).getIpAddress().equals(bridge.getResourceCache().getBridgeConfiguration().getIpAddress())) {
159 | phHueSDK.getDisconnectedAccessPoint().remove(i);
160 | }
161 | }
162 |
163 | }
164 |
165 | @Override
166 | public void onConnectionLost(PHAccessPoint accessPoint) {
167 | Log.v(TAG, "onConnectionLost : " + accessPoint.getIpAddress());
168 | if (!phHueSDK.getDisconnectedAccessPoint().contains(accessPoint)) {
169 | phHueSDK.getDisconnectedAccessPoint().add(accessPoint);
170 | }
171 | }
172 |
173 | @Override
174 | public void onError(int code, final String message) {
175 | Log.e(TAG, "on Error Called : " + code + ":" + message);
176 |
177 | if (code == PHHueError.NO_CONNECTION) {
178 | Log.w(TAG, "On No Connection");
179 | }
180 | else if (code == PHHueError.AUTHENTICATION_FAILED || code==PHMessageType.PUSHLINK_AUTHENTICATION_FAILED) {
181 | PHWizardAlertDialog.getInstance().closeProgressDialog();
182 | }
183 | else if (code == PHHueError.BRIDGE_NOT_RESPONDING) {
184 | Log.w(TAG, "Bridge Not Responding . . . ");
185 | PHWizardAlertDialog.getInstance().closeProgressDialog();
186 | PHHomeActivity.this.runOnUiThread(new Runnable() {
187 | @Override
188 | public void run() {
189 | PHWizardAlertDialog.showErrorDialog(PHHomeActivity.this, message, R.string.btn_ok);
190 | }
191 | });
192 |
193 | }
194 | else if (code == PHMessageType.BRIDGE_NOT_FOUND) {
195 |
196 | if (!lastSearchWasIPScan) { // Perform an IP Scan (backup mechanism) if UPNP and Portal Search fails.
197 | phHueSDK = PHHueSDK.getInstance();
198 | PHBridgeSearchManager sm = (PHBridgeSearchManager) phHueSDK.getSDKService(PHHueSDK.SEARCH_BRIDGE);
199 | sm.search(false, false, true);
200 | lastSearchWasIPScan=true;
201 | }
202 | else {
203 | PHWizardAlertDialog.getInstance().closeProgressDialog();
204 | PHHomeActivity.this.runOnUiThread(new Runnable() {
205 | @Override
206 | public void run() {
207 | PHWizardAlertDialog.showErrorDialog(PHHomeActivity.this, message, R.string.btn_ok);
208 | }
209 | });
210 | }
211 |
212 |
213 | }
214 | }
215 |
216 | @Override
217 | public void onParsingErrors(List parsingErrorsList) {
218 | for (PHHueParsingError parsingError: parsingErrorsList) {
219 | Log.e(TAG, "ParsingError : " + parsingError.getMessage());
220 | }
221 | }
222 | };
223 |
224 | /**
225 | * Called when option is selected.
226 | *
227 | * @param item the MenuItem object.
228 | * @return boolean Return false to allow normal menu processing to proceed, true to consume it here.
229 | */
230 | @Override
231 | public boolean onOptionsItemSelected(MenuItem item) {
232 | switch (item.getItemId()) {
233 | case R.id.find_new_bridge:
234 | doBridgeSearch();
235 | break;
236 | }
237 | return true;
238 | }
239 |
240 |
241 | @Override
242 | public void onDestroy() {
243 | super.onDestroy();
244 | if (listener !=null) {
245 | phHueSDK.getNotificationManager().unregisterSDKListener(listener);
246 | }
247 | phHueSDK.disableAllHeartbeat();
248 | }
249 |
250 | @Override
251 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
252 |
253 | PHAccessPoint accessPoint = (PHAccessPoint) adapter.getItem(position);
254 |
255 | PHBridge connectedBridge = phHueSDK.getSelectedBridge();
256 |
257 | if (connectedBridge != null) {
258 | String connectedIP = connectedBridge.getResourceCache().getBridgeConfiguration().getIpAddress();
259 | if (connectedIP != null) { // We are already connected here:-
260 | phHueSDK.disableHeartbeat(connectedBridge);
261 | phHueSDK.disconnect(connectedBridge);
262 | }
263 | }
264 | PHWizardAlertDialog.getInstance().showProgressDialog(R.string.connecting, PHHomeActivity.this);
265 | phHueSDK.connect(accessPoint);
266 | }
267 |
268 | public void doBridgeSearch() {
269 | PHWizardAlertDialog.getInstance().showProgressDialog(R.string.search_progress, PHHomeActivity.this);
270 | PHBridgeSearchManager sm = (PHBridgeSearchManager) phHueSDK.getSDKService(PHHueSDK.SEARCH_BRIDGE);
271 | // Start the UPNP Searching of local bridges.
272 | sm.search(true, true);
273 | }
274 |
275 | // Starting the main activity this way, prevents the PushLink Activity being shown when pressing the back button.
276 | public void startMainActivity() {
277 | Intent intent = new Intent(getApplicationContext(), MyApplicationActivity.class);
278 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
279 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
280 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
281 | intent.addFlags(0x8000); // equal to Intent.FLAG_ACTIVITY_CLEAR_TASK which is only available from API level 11
282 | startActivity(intent);
283 | }
284 |
285 | }
--------------------------------------------------------------------------------