Begin pushing networking to Service class
This commit is contained in:
@ -8,7 +8,7 @@ android {
|
|||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.1"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
android:name="com.google.android.glass.VoiceTrigger"
|
android:name="com.google.android.glass.VoiceTrigger"
|
||||||
android:resource="@xml/voice_trigger" />
|
android:resource="@xml/voice_trigger" />
|
||||||
</activity>
|
</activity>
|
||||||
|
<service android:name="SyncTeslaService" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@ -1,63 +1,85 @@
|
|||||||
package haus.nightmare.GlassTesla;
|
package haus.nightmare.GlassTesla;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
|
||||||
import com.google.android.glass.media.Sounds;
|
import com.google.android.glass.media.Sounds;
|
||||||
import com.google.android.glass.widget.CardBuilder;
|
import com.google.android.glass.widget.CardBuilder;
|
||||||
import com.google.android.glass.widget.CardScrollAdapter;
|
import com.google.android.glass.widget.CardScrollAdapter;
|
||||||
import com.google.android.glass.widget.CardScrollView;
|
import com.google.android.glass.widget.CardScrollView;
|
||||||
import com.google.gson.Gson;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.StrictMode;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
|
|
||||||
import org.conscrypt.Conscrypt;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.Security;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import javax.net.ssl.SSLException;
|
|
||||||
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import okio.BufferedSink;
|
|
||||||
|
|
||||||
|
|
||||||
public class MainActivity extends Activity {
|
public class MainActivity extends Activity {
|
||||||
|
|
||||||
|
private static final String TAG = "GT-Restart";
|
||||||
private CardScrollView cardScroller;
|
private CardScrollView cardScroller;
|
||||||
|
|
||||||
private TeslaResponse vehicleData;
|
private TeslaResponse vehicleData;
|
||||||
private SharedPreferences prefs;
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
private ArrayList<View> scrollerViews = new ArrayList<View>();
|
private ArrayList<View> scrollerViews;
|
||||||
|
|
||||||
|
private SyncTeslaService mService;
|
||||||
|
private boolean mBound = false;
|
||||||
|
|
||||||
|
@SuppressLint("SimpleDateFormat")
|
||||||
|
private SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm");
|
||||||
|
|
||||||
|
/** Defines callbacks for service binding, passed to bindService() */
|
||||||
|
private final ServiceConnection connection = new ServiceConnection() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName className,
|
||||||
|
IBinder service) {
|
||||||
|
// We've bound to LocalService, cast the IBinder and get LocalService instance
|
||||||
|
SyncTeslaService.SyncTeslaBinder binder = (SyncTeslaService.SyncTeslaBinder) service;
|
||||||
|
mService = binder.getService();
|
||||||
|
mBound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName arg0) {
|
||||||
|
mBound = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle bundle) {
|
protected void onCreate(final Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
|
|
||||||
StrictMode.setThreadPolicy(policy);
|
|
||||||
prefs = getPreferences(MODE_PRIVATE);
|
prefs = getPreferences(MODE_PRIVATE);
|
||||||
scrollerViews.add(buildStatusView());
|
Intent intent = new Intent(this, SyncTeslaService.class);
|
||||||
|
startService(intent);
|
||||||
|
bindService(intent, connection, Context.BIND_AUTO_CREATE);
|
||||||
|
scrollerViews = new ArrayList<View>();
|
||||||
|
cardScroller = new CardScrollView(getApplicationContext());
|
||||||
|
|
||||||
|
scrollerViews.add(buildLoadingView());
|
||||||
scrollerViews.add(buildLocksView());
|
scrollerViews.add(buildLocksView());
|
||||||
scrollerViews.add(buildControlView());
|
scrollerViews.add(buildControlView());
|
||||||
|
|
||||||
cardScroller = new CardScrollView(this);
|
|
||||||
cardScroller.setAdapter(new CardScrollAdapter() {
|
cardScroller.setAdapter(new CardScrollAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
@ -83,97 +105,156 @@ public class MainActivity extends Activity {
|
|||||||
cardScroller.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
cardScroller.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
switch(position) {
|
||||||
if (position == 2) {
|
case 2:
|
||||||
postCommand("flash_lights");
|
postCommand("flash_lights");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (vehicleData.vehicle_state.locked) {
|
||||||
|
postCommand("door_unlock");
|
||||||
|
} else {
|
||||||
|
postCommand("door_lock");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
updateIfExpired();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (position == 1) {
|
|
||||||
if (vehicleData.vehicle_state.locked) {
|
|
||||||
postCommand("door_unlock");
|
|
||||||
} else {
|
|
||||||
postCommand("door_lock");
|
|
||||||
}
|
|
||||||
scrollerViews.set(1, buildLocksView());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position == 0) {
|
|
||||||
scrollerViews.set(0, buildStatusView());
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
|
||||||
am.playSoundEffect(Sounds.TAP);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
cardScroller.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
cardScroller.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
switch (position) {
|
||||||
if (position == 2) {
|
case 2:
|
||||||
return postCommand("honk_horn");
|
postCommand("honk_horn");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
postCommand("set_sentry_mode?on=" +
|
||||||
|
!vehicleData.vehicle_state.sentry_mode);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
postCommand("remote_start_drive?password=" + prefs.getString("auth_password", ""));
|
||||||
}
|
}
|
||||||
if (position == 1) {
|
return true;
|
||||||
return postCommand("set_sentry_mode?on=" + !vehicleData.vehicle_state.sentry_mode);
|
|
||||||
}
|
|
||||||
if (position == 0) {
|
|
||||||
return postCommand("remote_start_drive?password=" + prefs.getString("auth_password", ""));
|
|
||||||
}
|
|
||||||
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
|
||||||
am.playSoundEffect(Sounds.DISALLOWED);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setContentView(cardScroller);
|
setContentView(cardScroller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
Intent intent = new Intent(this, SyncTeslaService.class);
|
||||||
|
bindService(intent, connection, Context.BIND_AUTO_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
unbindService(connection);
|
||||||
|
mBound = false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
cardScroller.activate();
|
if (this.cardScroller != null) {
|
||||||
|
cardScroller.activate();
|
||||||
|
} else {
|
||||||
|
updateIfExpired();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateIfExpired() {
|
||||||
|
if (mBound) {
|
||||||
|
Calendar expire = Calendar.getInstance();
|
||||||
|
expire.add(Calendar.MINUTE, -5);
|
||||||
|
vehicleData = mService.getVehicleData();
|
||||||
|
if (vehicleData == null || new Date(vehicleData.vehicle_state.timestamp).after(expire.getTime())) {
|
||||||
|
refreshCards();
|
||||||
|
} else {
|
||||||
|
updateCards();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
refreshCards();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
cardScroller.deactivate();
|
if (cardScroller != null) {
|
||||||
|
cardScroller.deactivate();
|
||||||
|
}
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void playAudio(int sound) {
|
||||||
|
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||||
|
if (am != null) {
|
||||||
|
am.playSoundEffect(sound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshCards() {
|
||||||
|
Thread t = new Thread(new Runnable(){
|
||||||
|
public void run() {
|
||||||
|
mService.updateSharedPrefs(prefs);
|
||||||
|
mService.loadVehicleData(prefs.getString("vehicle_id", ""));
|
||||||
|
vehicleData = mService.getVehicleData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
t.start();
|
||||||
|
try {
|
||||||
|
t.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
updateCards();
|
||||||
|
}
|
||||||
|
private void updateCards() {
|
||||||
|
scrollerViews = new ArrayList<View>();
|
||||||
|
scrollerViews.add(buildStatusView());
|
||||||
|
scrollerViews.add(buildLocksView());
|
||||||
|
scrollerViews.add(buildControlView());
|
||||||
|
cardScroller.animate(0, CardScrollView.Animation.INSERTION);
|
||||||
|
}
|
||||||
|
|
||||||
private View buildControlView() {
|
private View buildControlView() {
|
||||||
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
|
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
|
||||||
card.setText("Tap to flash lights, long press to honk.");
|
card.setText("Tap to flash lights, long press to honk.");
|
||||||
return card.getView();
|
return card.getView();
|
||||||
}
|
}
|
||||||
|
|
||||||
private View buildLocksView() {
|
private View buildLoadingView() {
|
||||||
updateIfNeeded();
|
|
||||||
|
|
||||||
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
|
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
|
||||||
String body = vehicleData.vehicle_state.locked ? "Tap to unlock" : "Tap to lock";
|
card.setText("Tap to load data.");
|
||||||
|
return card.getView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private View buildLocksView() {
|
||||||
|
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
|
||||||
|
String body;
|
||||||
|
if (vehicleData == null) {
|
||||||
|
body = "Tap to lock";
|
||||||
|
} else {
|
||||||
|
body = "Tap to " + (vehicleData.vehicle_state.locked ? "unlock":"lock");
|
||||||
|
}
|
||||||
body += "\nLong press to ";
|
body += "\nLong press to ";
|
||||||
body += vehicleData.vehicle_state.sentry_mode ? "disable" : "enable";
|
if (vehicleData == null) {
|
||||||
|
body += "enable";
|
||||||
|
} else {
|
||||||
|
body += vehicleData.vehicle_state.sentry_mode ? "disable" : "enable";
|
||||||
|
}
|
||||||
|
|
||||||
body += " Sentry Mode";
|
body += " Sentry Mode";
|
||||||
card.setText(body);
|
card.setText(body);
|
||||||
return card.getView();
|
return card.getView();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateIfNeeded() {
|
|
||||||
Calendar expire = Calendar.getInstance();
|
|
||||||
expire.add(Calendar.MINUTE, -5);
|
|
||||||
if (vehicleData == null || new Date(vehicleData.vehicle_state.timestamp).after(expire.getTime())) {
|
|
||||||
try {
|
|
||||||
getVehicleData();
|
|
||||||
} catch(Exception e) {
|
|
||||||
Log.v("Tesla API Setup", "Unable to get Tesla data", e);
|
|
||||||
this.finishAffinity();
|
|
||||||
System.exit(0); // Shouldn't be reached, but just in case let's kill it dead
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private View buildStatusView() {
|
private View buildStatusView() {
|
||||||
updateIfNeeded();
|
|
||||||
|
|
||||||
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
|
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
|
||||||
String chargeDuration = "";
|
String chargeDuration = "";
|
||||||
@ -186,6 +267,9 @@ public class MainActivity extends Activity {
|
|||||||
if (minutes > 0) {
|
if (minutes > 0) {
|
||||||
chargeDuration += minutes + "m";
|
chargeDuration += minutes + "m";
|
||||||
}
|
}
|
||||||
|
if (vehicleData.charge_state.charging_state.equalsIgnoreCase("Disconnected")) {
|
||||||
|
chargeDuration = "N/A";
|
||||||
|
}
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
cal.add(Calendar.HOUR_OF_DAY, hours);
|
cal.add(Calendar.HOUR_OF_DAY, hours);
|
||||||
cal.add(Calendar.MINUTE, minutes);
|
cal.add(Calendar.MINUTE, minutes);
|
||||||
@ -197,92 +281,73 @@ public class MainActivity extends Activity {
|
|||||||
vehicleData.charge_state.charging_state,
|
vehicleData.charge_state.charging_state,
|
||||||
vehicleData.charge_state.charger_power,
|
vehicleData.charge_state.charger_power,
|
||||||
chargeDuration,
|
chargeDuration,
|
||||||
new SimpleDateFormat("hh:mm").format(cal.getTime())
|
timeFormatter.format(cal.getTime())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
card.setFootnote(String.format("%s last updated: %s",
|
card.setFootnote(String.format("%s last updated: %s",
|
||||||
vehicleData.display_name,
|
vehicleData.display_name,
|
||||||
new SimpleDateFormat("hh:mm").format(vehicleData.vehicle_state.timestamp)
|
timeFormatter.format(vehicleData.vehicle_state.timestamp)
|
||||||
));
|
));
|
||||||
View v = card.getView();
|
View v = card.getView();
|
||||||
v.setKeepScreenOn(true);
|
v.setKeepScreenOn(true);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// /api/1/vehicles/{id}/vehicle_data
|
|
||||||
public void getVehicleData() {
|
|
||||||
String vehicleId = prefs.getString("vehicle_id", "");
|
|
||||||
String json = getResponseFromJsonURL("https://owner-api.teslamotors.com/api/1/vehicles/"
|
|
||||||
+ vehicleId +"/vehicle_data");
|
|
||||||
Gson gson = new Gson();
|
|
||||||
ResponseRoot root = gson.fromJson(json, ResponseRoot.class);
|
|
||||||
vehicleData = root.response;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean postCommand(String command) {
|
public void postCommand(String command) {
|
||||||
try {
|
|
||||||
String token = prefs.getString("bearer_token", "");
|
AsyncTask<String, ArrayList<View>, Boolean> task = new AsyncTask<String, ArrayList<View>, Boolean>() {
|
||||||
String vehicleId = prefs.getString("vehicle_id", "");
|
|
||||||
URL object = new URL("https://owner-api.teslamotors.com/api/1/vehicles/"
|
@Override
|
||||||
+ vehicleId +"/command/" + command);
|
protected Boolean doInBackground(String... commands) {
|
||||||
OkHttpClient client = new OkHttpClient();
|
String command = commands[0];
|
||||||
Request request = new Request.Builder()
|
try {
|
||||||
.url(object)
|
String token = prefs.getString("bearer_token", "");
|
||||||
.method("POST", RequestBody.create(null, new byte[]{}))
|
String vehicleId = prefs.getString("vehicle_id", "");
|
||||||
.addHeader("Authorization", "Bearer " + token)
|
URL object = new URL("https://owner-api.teslamotors.com/api/1/vehicles/"
|
||||||
.addHeader("User-Agent", "Tesla-GLASS")
|
+ vehicleId +"/command/" + command);
|
||||||
.addHeader("Content-Type", "application/json")
|
OkHttpClient client = new OkHttpClient();
|
||||||
.build();
|
Request request = new Request.Builder()
|
||||||
|
.url(object)
|
||||||
|
.method("POST", RequestBody.create(null, new byte[]{}))
|
||||||
|
.addHeader("Authorization", "Bearer " + token)
|
||||||
|
.addHeader("User-Agent", "Tesla-GLASS")
|
||||||
|
.addHeader("Content-Type", "application/json")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
Response response = client.newCall(request).execute();
|
Response response = client.newCall(request).execute();
|
||||||
|
if (response.code() == 408) {
|
||||||
return response.code() == 200;
|
postCommand("wake_up");
|
||||||
} catch (Exception e) {
|
}
|
||||||
e.printStackTrace();
|
return response.code() == 200;
|
||||||
}
|
} catch (Exception e) {
|
||||||
return false;
|
e.printStackTrace();
|
||||||
}
|
|
||||||
|
|
||||||
public String getResponseFromJsonURL(String url) {
|
|
||||||
String token = prefs.getString("bearer_token", "");
|
|
||||||
|
|
||||||
String jsonResponse = null;
|
|
||||||
if (url.length() > 0) {
|
|
||||||
try {
|
|
||||||
Security.insertProviderAt(Conscrypt.newProvider(), 1);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************** For getting response from HTTP URL start ***************/
|
|
||||||
URL object = new URL(url);
|
|
||||||
|
|
||||||
OkHttpClient client = new OkHttpClient();
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(object)
|
|
||||||
.addHeader("Authorization", "Bearer " + token)
|
|
||||||
.addHeader("User-Agent", "Tesla-GLASS")
|
|
||||||
.addHeader("Content-Type", "application/json")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
Response response = client.newCall(request).execute();
|
|
||||||
|
|
||||||
int responseCode = response.code();
|
|
||||||
|
|
||||||
if (responseCode == 200) {
|
|
||||||
return response.body().string();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (SSLException e) {
|
return false;
|
||||||
Log.e("DataSSL", "SSL Exception getting json:", e);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return jsonResponse;
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
cardScroller.animate(0, CardScrollView.Animation.NAVIGATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(Boolean result) {
|
||||||
|
if (result) {
|
||||||
|
playAudio(Sounds.SUCCESS);
|
||||||
|
} else {
|
||||||
|
playAudio(Sounds.DISALLOWED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
task.execute(command);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,171 @@
|
|||||||
|
package haus.nightmare.GlassTesla;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.util.Log;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import org.conscrypt.Conscrypt;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.Security;
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
public class SyncTeslaService extends Service {
|
||||||
|
int startMode; // indicates how to behave if the service is killed
|
||||||
|
IBinder binder = new SyncTeslaBinder(); // interface for clients that bind
|
||||||
|
boolean allowRebind; // indicates whether onRebind should be used
|
||||||
|
private TeslaResponse vehicleData;
|
||||||
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
|
|
||||||
|
public class SyncTeslaBinder extends Binder {
|
||||||
|
SyncTeslaService getService() {
|
||||||
|
return SyncTeslaService.this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TeslaResponse getVehicleData() {
|
||||||
|
return vehicleData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
// The service is starting, due to a call to startService()
|
||||||
|
|
||||||
|
new Thread(new Runnable(){
|
||||||
|
public void run() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Thread.sleep(2 * 60000);
|
||||||
|
loadVehicleData();
|
||||||
|
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
return startMode;
|
||||||
|
}
|
||||||
|
public void loadVehicleData(String vehicleId) {
|
||||||
|
String json = getResponseFromJsonURL("https://owner-api.teslamotors.com/api/1/vehicles/"
|
||||||
|
+ vehicleId +"/vehicle_data");
|
||||||
|
Gson gson = new Gson();
|
||||||
|
ResponseRoot root = gson.fromJson(json, ResponseRoot.class);
|
||||||
|
vehicleData = root.response;
|
||||||
|
}
|
||||||
|
public void loadVehicleData() {
|
||||||
|
loadVehicleData(prefs.getString("vehicle_id", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateSharedPrefs(SharedPreferences p) {
|
||||||
|
SharedPreferences.Editor e = prefs.edit();
|
||||||
|
prefs = p;
|
||||||
|
e.putString("bearer_token", p.getString("bearer_token", ""));
|
||||||
|
e.putString("vehicle_id", p.getString("vehicle_id", ""));
|
||||||
|
e.apply();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean postCommand(String command) {
|
||||||
|
try {
|
||||||
|
String token = prefs.getString("bearer_token", "");
|
||||||
|
String vehicleId = prefs.getString("vehicle_id", "");
|
||||||
|
URL object = new URL("https://owner-api.teslamotors.com/api/1/vehicles/"
|
||||||
|
+ vehicleId +"/command/" + command);
|
||||||
|
OkHttpClient client = new OkHttpClient();
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(object)
|
||||||
|
.method("POST", RequestBody.create(null, new byte[]{}))
|
||||||
|
.addHeader("Authorization", "Bearer " + token)
|
||||||
|
.addHeader("User-Agent", "Tesla-GLASS")
|
||||||
|
.addHeader("Content-Type", "application/json")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
if (response.code() == 408) {
|
||||||
|
postCommand("wake_up");
|
||||||
|
}
|
||||||
|
return response.code() == 200;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseFromJsonURL(String url) {
|
||||||
|
String token = prefs.getString("bearer_token", "");
|
||||||
|
|
||||||
|
String jsonResponse = null;
|
||||||
|
if (url.length() > 0) {
|
||||||
|
try {
|
||||||
|
Security.insertProviderAt(Conscrypt.newProvider(), 1);
|
||||||
|
/************** For getting response from HTTP URL start ***************/
|
||||||
|
URL object = new URL(url);
|
||||||
|
|
||||||
|
OkHttpClient client = new OkHttpClient();
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(object)
|
||||||
|
.addHeader("Authorization", "Bearer " + token)
|
||||||
|
.addHeader("User-Agent", "Tesla-GLASS")
|
||||||
|
.addHeader("Content-Type", "application/json")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
|
||||||
|
int responseCode = response.code();
|
||||||
|
|
||||||
|
if (responseCode == 200) {
|
||||||
|
return response.body().string();
|
||||||
|
|
||||||
|
} else if (responseCode == 408) {
|
||||||
|
postCommand("wake_up");
|
||||||
|
}
|
||||||
|
} catch (SSLException e) {
|
||||||
|
Log.e("DataSSL", "SSL Exception getting json:", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
// A client is binding to the service with bindService()
|
||||||
|
return binder;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean onUnbind(Intent intent) {
|
||||||
|
// All clients have unbound with unbindService()
|
||||||
|
return allowRebind;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onRebind(Intent intent) {
|
||||||
|
// A client is binding to the service with bindService(),
|
||||||
|
// after onUnbind() has already been called
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
// The service is no longer used and is being destroyed
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user