/* * This file is part of Domodroid. * * Domodroid is Copyright (C) 2011 Pierre LAINE, Maxime CHOFARDET * * Domodroid is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * Domodroid is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * Domodroid. If not, see <http://www.gnu.org/licenses/>. */ package widgets; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Handler; import android.os.Message; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.FrameLayout; import android.widget.TextView; import android.widget.Toast; import com.github.curioustechizen.ago.RelativeTimeTextView; import org.domogik.domodroid13.BuildConfig; import org.domogik.domodroid13.R; import org.json.JSONException; import org.json.JSONObject; import org.osmdroid.api.IMapController; import org.osmdroid.tileprovider.tilesource.TileSourceFactory; import org.osmdroid.util.GeoPoint; import org.osmdroid.views.overlay.ItemizedIconOverlay; import org.osmdroid.views.overlay.OverlayItem; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; import Abstract.display_sensor_info; import Abstract.translate; import Entity.Entity_Feature; import Entity.Entity_Map; import Entity.Entity_client; import database.WidgetUpdate; import misc.tracerengine; import static activities.Activity_Main.SV_Main_ScrollView; public class Graphical_Openstreetmap extends Basic_Graphical_widget implements OnClickListener { private org.osmdroid.views.MapView osmMapview; private ArrayList<HashMap<String, String>> listItem; private TextView TV_Value; private RelativeTimeTextView TV_Timestamp; private TextView state; private int id; private static String mytag; private Message msg; public static FrameLayout container = null; private static FrameLayout myself = null; private Boolean realtime = false; private Animation animation; private final Entity_Feature feature; private String state_key; private int dev_id; private final int session_type; private final SharedPreferences params; private boolean isopen = false; private Float Float_graph_size; private TextView state_key_view; private String stateS; private String test_unite; public Graphical_Openstreetmap(tracerengine Trac, final Activity activity, int widgetSize, int session_type, int place_id, String place_type, SharedPreferences params, final Entity_Feature feature, Handler handler) { super(params, activity, Trac, feature.getId(), feature.getDescription(), feature.getState_key(), feature.getIcon_name(), widgetSize, place_id, place_type, mytag, container, handler); this.feature = feature; this.params = params; this.session_type = session_type; onCreate(); } public Graphical_Openstreetmap(tracerengine Trac, final Activity activity, int widgetSize, int session_type, int place_id, String place_type, SharedPreferences params, final Entity_Map feature_map, Handler handler) { super(params, activity, Trac, feature_map.getId(), feature_map.getDescription(), feature_map.getState_key(), feature_map.getIcon_name(), widgetSize, place_id, place_type, mytag, container, handler); this.feature = feature_map; this.session_type = session_type; this.params = params; onCreate(); } private void onCreate() { String parameters = feature.getParameters(); this.dev_id = feature.getDevId(); this.state_key = feature.getState_key(); this.id = feature.getId(); this.isopen = false; try { int graphics_height_size = params.getInt("graphics_height_size", 262); this.Float_graph_size = Float.valueOf(graphics_height_size); } catch (Exception e) { //This is due to old way to store it as a string String graph_size = params.getString("graph_size", "262.5"); this.Float_graph_size = Float.valueOf(graph_size); } myself = this; mytag = "Graphical_History(" + dev_id + ")"; try { stateS = getResources().getString(translate.do_translate(getContext(), Tracer, state_key)); } catch (Exception e) { stateS = state_key; } if (stateS.equals("null")) stateS = state_key; test_unite = ""; try { //Basilic add, number feature has a unit parameter JSONObject jparam = new JSONObject(parameters.replaceAll(""", "\"")); test_unite = jparam.getString("unit"); } catch (JSONException jsonerror) { Tracer.i(mytag, "No unit for this feature"); } setOnClickListener(this); //state key state_key_view = new TextView(activity); state_key_view.setText(stateS); state_key_view.setTextColor(Color.parseColor("#333333")); //TV_Value TV_Value = new TextView(activity); TV_Value.setTextSize(28); TV_Value.setTextColor(Color.BLACK); TV_Value.setGravity(Gravity.RIGHT); TV_Timestamp = new RelativeTimeTextView(activity, null); TV_Timestamp.setTextSize(10); TV_Timestamp.setTextColor(Color.BLUE); TV_Timestamp.setGravity(Gravity.RIGHT); animation = new AlphaAnimation(0.0f, 1.0f); animation.setDuration(1000); super.LL_featurePan.addView(TV_Value); super.LL_featurePan.addView(TV_Timestamp); super.LL_infoPan.addView(state_key_view); Handler handler = new Handler() { @Override public void handleMessage(Message msg) { String status; if (msg.what == 9999) { if (session == null) return; String new_val = session.getValue(); String Value_timestamp = session.getTimestamp(); Tracer.d(mytag, "Handler receives a new TV_Value <" + new_val + "> at " + Value_timestamp); TV_Value.setAnimation(animation); Long Value_timestamplong = null; Value_timestamplong = Long.valueOf(Value_timestamp) * 1000; final String uri = String.format(Locale.ENGLISH, "geo:" + new_val + "?q=" + new_val + "(" + name + "-" + state_key + ")"); TV_Value.setOnClickListener(new OnClickListener() { public void onClick(View v) { try { Intent unrestrictedIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); activity.startActivity(unrestrictedIntent); } catch (ActivityNotFoundException innerEx) { //todo to translate Toast.makeText(activity, R.string.missing_maps_applications, Toast.LENGTH_LONG).show(); } } } ); display_sensor_info.display(Tracer, new_val, Value_timestamplong, mytag, feature.getParameters(), TV_Value, TV_Timestamp, activity, LL_featurePan, typefaceweather, typefaceawesome, state_key, state_key_view, stateS, test_unite); //TV_Value.setTypeface(typefaceawesome, Typeface.NORMAL); //TV_Value.setText(new_val + " \uF064"); //To have the icon colored as it has no state change_this_icon(2); } else if (msg.what == 9998) { // state_engine send us a signal to notify it'll die ! Tracer.d(mytag, "state engine disappeared ===> Harakiri !"); session = null; realtime = false; removeView(LL_background); myself.setVisibility(GONE); if (container != null) { container.removeView(myself); container.recomputeViewAttributes(myself); } try { finalize(); } catch (Throwable t) { t.printStackTrace(); } //kill the handler thread itself } } }; //================================================================================ /* * New mechanism to be notified by widgetupdate engine when our TV_Value is changed * */ WidgetUpdate cache_engine = WidgetUpdate.getInstance(); if (cache_engine != null) { if (api_version <= 0.6f) { session = new Entity_client(dev_id, state_key, mytag, handler, session_type); } else if (api_version >= 0.7f) { session = new Entity_client(id, "", mytag, handler, session_type); } try { if (Tracer.get_engine().subscribe(session)) { realtime = true; //we're connected to engine //each time our TV_Value change, the engine will call handler handler.sendEmptyMessage(9999); //Force to consider current TV_Value in session } } catch (Exception e) { e.printStackTrace(); } } //================================================================================ //updateTimer(); //Don't use anymore cyclic refresh.... } @Override protected void onWindowVisibilityChanged(int visibility) { } private void display_position_on_map() { //Get value display to set lat/lon of current position String[] position = TV_Value.getText().toString().split(","); Float lat = Float.parseFloat(position[0]); Float lon = Float.parseFloat(position[1]); osmMapview = new org.osmdroid.views.MapView(activity); //important! set your user agent to prevent getting banned from the osm servers org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants.setUserAgentValue(BuildConfig.APPLICATION_ID); osmMapview.setTileSource(TileSourceFactory.MAPNIK); //Then we add default zoom buttons, and ability to zoom with 2 fingers (multi-touch) osmMapview.setBuiltInZoomControls(true); osmMapview.setMultiTouchControls(true); //We can move the map on a default view point. For this, we need access to the map controller: IMapController mapController = osmMapview.getController(); mapController.setZoom(15); GeoPoint startPoint = new GeoPoint(lat, lon); //Center on position mapController.setCenter(startPoint); //Add a marker on position OverlayItem myLocationOverlayItem = new OverlayItem("", "", startPoint); Drawable myCurrentLocationMarker = this.getResources().getDrawable(R.drawable.marker_default); myLocationOverlayItem.setMarker(myCurrentLocationMarker); final ArrayList<OverlayItem> items = new ArrayList<OverlayItem>(); items.add(myLocationOverlayItem); ItemizedIconOverlay currentLocationOverlay = new ItemizedIconOverlay<OverlayItem>(items, new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() { public boolean onItemSingleTapUp(final int index, final OverlayItem item) { return true; } public boolean onItemLongPress(final int index, final OverlayItem item) { return true; } }, activity); this.osmMapview.getOverlays().add(currentLocationOverlay); } private void display_history_position_on_map() { //todo add a way to handle history position to display them on Openstreetmap /* JSONObject json_LastValues = null; JSONArray itemArray = null; listItem = new ArrayList<>(); try { if (api_version <= 0.6f) { Tracer.i(mytag, "UpdateThread (" + dev_id + ") : " + url + "stats/" + dev_id + "/" + state_key + "/last/" + nb_item_for_history + "/"); json_LastValues = Rest_com.connect_jsonobject(Tracer, url + "stats/" + dev_id + "/" + state_key + "/last/" + nb_item_for_history + "/", login, password, 10000, SSL); } else if (api_version >= 0.7f) { Tracer.i(mytag, "UpdateThread (" + id + ") : " + url + "sensorhistory/id/" + id + "/last/5"); //Don't forget old "dev_id"+"state_key" is replaced by "id" JSONArray json_LastValues_0_4 = Rest_com.connect_jsonarray(Tracer, url + "sensorhistory/id/" + id + "/last/" + nb_item_for_history + "", login, password, 10000, SSL); json_LastValues = new JSONObject(); json_LastValues.put("stats", json_LastValues_0_4); } itemArray = json_LastValues.getJSONArray("stats"); if (api_version <= 0.6f) { for (int i = itemArray.length(); i >= 0; i--) { try { HashMap<String, String> map = new HashMap<>(); try { map.put("TV_Value", activity.getString(translate.do_translate(getactivity(), Tracer, itemArray.getJSONObject(i).getString("TV_Value")))); } catch (Exception e1) { map.put("TV_Value", itemArray.getJSONObject(i).getString("TV_Value")); } map.put("date", itemArray.getJSONObject(i).getString("date")); listItem.add(map); Tracer.d(mytag, map.toString()); } catch (Exception e) { Tracer.e(mytag, "Error getting json TV_Value"); } } } else if (api_version >= 0.7f) { for (int i = 0; i < itemArray.length(); i++) { try { HashMap<String, String> map = new HashMap<>(); try { map.put("TV_Value", activity.getString(translate.do_translate(getactivity(), Tracer, itemArray.getJSONObject(i).getString("value_str")))); } catch (Exception e1) { map.put("TV_Value", itemArray.getJSONObject(i).getString("value_str")); } if (api_version == 0.7f) { map.put("date", itemArray.getJSONObject(i).getString("date")); } else if (api_version >= 0.8f) { String currenTimestamp = String.valueOf((long) (itemArray.getJSONObject(i).getInt("timestamp")) * 1000); map.put("date", display_sensor_info.timestamp_convertion(currenTimestamp, activity)); } listItem.add(map); Tracer.d(mytag, map.toString()); } catch (Exception e) { Tracer.e(mytag, "Error getting json TV_Value"); } } } } catch (Exception e) { //return null; Tracer.e(mytag, "Error fetching json object"); } SimpleAdapter adapter_feature = new SimpleAdapter(this.activity, listItem, R.layout.item_history_in_graphical_history, new String[]{"TV_Value", "date"}, new int[]{R.id.value, R.id.date}); listeChoices.setAdapter(adapter_feature); listeChoices.setScrollingCacheEnabled(false); */ } public void onClick(View arg0) { //Done correct 350px because it's the source of http://tracker.domogik.org/issues/1804 float size = Float_graph_size * activity.getResources().getDisplayMetrics().density + 0.5f; int sizeint = (int) size; int currentint = LL_background.getHeight(); if (!isopen) { Tracer.d(mytag, "on click"); try { LL_background.removeView(osmMapview); Tracer.d(mytag, "removeView(osmMapview)"); } catch (Exception e) { e.printStackTrace(); } Tracer.d(mytag, "display_position_on_map"); display_position_on_map(); Tracer.d(mytag, "addView(osmMapview)"); LL_background.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, currentint + sizeint)); try { LL_background.removeView(osmMapview); } catch (Exception e) { //to avoid #135 } LL_background.addView(osmMapview); this.osmMapview.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { SV_Main_ScrollView.requestDisallowInterceptTouchEvent(true); int action = event.getActionMasked(); switch (action) { case MotionEvent.ACTION_UP: SV_Main_ScrollView.requestDisallowInterceptTouchEvent(false); break; } return false; } }); this.isopen = true; } else { this.isopen = false; LL_background.removeView(osmMapview); LL_background.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); } } }