summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--native/android/avatar/src/main/AndroidManifest.xml11
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/activity/AvatarActivity.java1145
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/activity/EulaActivity.java37
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/downloader/DownloaderClient.java2
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONAVAController.java141
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONBackendController.java13
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONController.java2
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONRevSDLController.java12
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONVideoController.java714
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/jssupport/JavaScriptFacade.java2
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/media/AvatarOnPreparedListener.java2
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/requests/CancelAccessCommand.java32
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/requests/GrantAccessCommand.java1
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneDownCommand.java35
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneRadioCommand.java1
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneUpCommand.java36
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/responses/CancelAccessResponse.java24
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/service/SDLService.java124
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/util/Const.java6
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/util/WebViewUtils.java2
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/views/AppSetupDialog.java106
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/views/AvatarActivity.java1097
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/views/ConnectionTypeDialog.java17
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/views/EulaActivity.java32
-rw-r--r--native/android/avatar/src/main/java/com/ford/avarsdl/views/SafeToast.java (renamed from native/android/avatar/src/main/java/com/ford/avarsdl/activity/SafeToast.java)2
-rw-r--r--native/android/avatar/src/main/res/layout/sdl_settings.xml99
-rw-r--r--native/android/avatar/src/main/res/raw/faq_welcome_orientation.mp4bin4787548 -> 0 bytes
-rw-r--r--native/android/avatar/src/main/res/values/strings.xml11
-rw-r--r--native/android/avatar_test/src/com/ford/avatar/test/jsoncontroller/JSONAVAControllerTest.java2
-rw-r--r--openxc_backend/README20
-rwxr-xr-xopenxc_backend/installer.sh20
-rw-r--r--openxc_backend/server/Server.py11
-rw-r--r--openxc_backend/web_console/index.html10
-rw-r--r--openxc_backend/web_console/js/index.js21
m---------sdl0
-rw-r--r--web/src/app/controller/AppController.js16
-rw-r--r--web/src/app/controller/MediaController.js11
-rw-r--r--web/src/app/view/media/radio/fmView.js44
-rw-r--r--web/src/css/media.css20
-rw-r--r--web/src/ffw/RevSDLRPC.js61
-rw-r--r--web/src/images/common/car.pngbin0 -> 1688 bytes
-rw-r--r--web/src/images/common/car_red.pngbin0 -> 1704 bytes
-rw-r--r--web/src/images/common/car_yellow.pngbin0 -> 1696 bytes
-rw-r--r--web/src/images/common/header_bg_old.pngbin0 -> 6743 bytes
-rw-r--r--web/src/images/common/phone.pngbin0 -> 1361 bytes
-rw-r--r--web/src/locale/eng.js2
46 files changed, 2203 insertions, 1741 deletions
diff --git a/native/android/avatar/src/main/AndroidManifest.xml b/native/android/avatar/src/main/AndroidManifest.xml
index 9268c3316e..8aa98315c6 100644
--- a/native/android/avatar/src/main/AndroidManifest.xml
+++ b/native/android/avatar/src/main/AndroidManifest.xml
@@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ford.avarsdl"
android:installLocation="preferExternal"
- android:versionCode="1"
- android:versionName="E4" >
+ android:versionCode="2"
+ android:versionName="E5" >
<!-- Required to access Android Market Licensing -->
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
@@ -18,6 +18,9 @@
<!-- Required to read and write the expansion files on shared storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_TASKS" />
+ <uses-permission android:name="android.permission.BLUETOOTH" />
+ <!-- Required to pair Bluetooth devices -->
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-sdk
android:minSdkVersion="12"
@@ -29,7 +32,7 @@
android:name=".business.MainApp"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<activity
- android:name=".activity.AvatarActivity"
+ android:name=".views.AvatarActivity"
android:configChanges="keyboardHidden|orientation"
android:label="@string/app_name"
android:screenOrientation="landscape" >
@@ -39,7 +42,7 @@
</intent-filter>
</activity>
<activity
- android:name=".activity.EulaActivity"
+ android:name=".views.EulaActivity"
android:label="@string/app_name"
android:screenOrientation="landscape" />
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/activity/AvatarActivity.java b/native/android/avatar/src/main/java/com/ford/avarsdl/activity/AvatarActivity.java
deleted file mode 100644
index 7f3ee4b863..0000000000
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/activity/AvatarActivity.java
+++ /dev/null
@@ -1,1145 +0,0 @@
-package com.ford.avarsdl.activity;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Timer;
-import java.util.TimerTask;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.AssetFileDescriptor;
-import android.content.res.AssetManager;
-import android.graphics.Rect;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.StrictMode;
-import android.preference.PreferenceManager;
-import android.util.DisplayMetrics;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.View;
-import android.view.Window;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.webkit.WebChromeClient;
-import android.webkit.WebSettings.RenderPriority;
-import android.webkit.WebView;
-import android.widget.EditText;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.RelativeLayout.LayoutParams;
-import android.widget.Toast;
-
-import com.android.vending.expansion.zipfile.APKExpansionSupport;
-import com.android.vending.expansion.zipfile.ZipResourceFile;
-
-import com.ford.avarsdl.R;
-import com.ford.avarsdl.downloader.DownloaderClient;
-import com.ford.avarsdl.downloader.XAPKFile;
-import com.ford.avarsdl.exception.ExtensionFileException;
-import com.ford.avarsdl.exception.MediaPlayerException;
-import com.ford.avarsdl.jsoncontroller.JSONBackendController;
-import com.ford.avarsdl.jsoncontroller.JSONRateController;
-import com.ford.avarsdl.jsoncontroller.JSONRevSDLController;
-import com.ford.avarsdl.jsoncontroller.JSONVideoController;
-import com.ford.avarsdl.jsonserver.JSONServer;
-import com.ford.avarsdl.media.AvatarOnPreparedListener;
-import com.ford.avarsdl.rater.AppRater;
-import com.ford.avarsdl.service.ISDLServiceConnection;
-import com.ford.avarsdl.service.SDLService;
-import com.ford.avarsdl.service.SDLServiceBinder;
-import com.ford.avarsdl.service.SDLServiceConnectionProxy;
-import com.ford.avarsdl.util.ActivityUtils;
-import com.ford.avarsdl.util.Const;
-import com.ford.avarsdl.util.ExtStorageUtils;
-import com.ford.avarsdl.util.Logger;
-import com.ford.avarsdl.util.MessageConst;
-import com.ford.avarsdl.util.Utils;
-import com.ford.avarsdl.util.WebViewUtils;
-import com.ford.syncV4.proxy.interfaces.IProxyListenerALM;
-
-/**
- * Title: AvatarActivity.java<br>
- * Description: Main application activity, responsible for webview content load
- * and video handling<br>
- *
- * @author vsaenko/Eugene Sagan
- * @co-author Yuriy Chernyshov
- */
-public class AvatarActivity extends Activity implements SurfaceHolder.Callback,
- ISDLServiceConnection {
-
- private final SDLServiceConnectionProxy mSDLServiceConnectionProxy = new SDLServiceConnectionProxy(this);
- private IProxyListenerALM mBoundSDLService;
-
- // for monkey testing
- // adb shell monkey -p com.ford.avarsdl -v 100
-
- public static Boolean fullscreenPreferenceChanged = false;
- public static Boolean vehiclePreferenceChanged = false;
- public static Boolean navigationPreferenceChanged = false;
-
- public static Boolean ratePreferenceEnabled;
-
- @Override
- public void onStart() {
- super.onStart();
-
- Logger.i(getClass().getSimpleName() + " onStart ");
-
- if (mBoundSDLService != null) {
-
- } else {
- bindSDLService(this, mSDLServiceConnectionProxy);
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Logger.i(getClass().getSimpleName() + " onCreate, hash:" + hashCode());
-
- // FIXME: the old code with new SDK crashes with
- // android.os.NetworkOnMainThreadException
- // this hotfix is a bad idea. Don't try this at home!
- StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().
- permitAll().build();
- StrictMode.setThreadPolicy(policy);
-
- if (isFirstStart()) {
- Intent intent = new Intent(this, EulaActivity.class);
- startActivityForResult(intent, Const.REQUESTCODE_EULA);
- } else {
- startAvatarActivity();
- }
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode == RESULT_OK && requestCode == Const.REQUESTCODE_EULA) {
- startAvatarActivity();
- resumeAvatarActivity();
- } else {
- finish();
- }
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public void onBackPressed() {
- // do something on back.
- this.moveTaskToBack(true);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.optionsmenu, menu);
- return true;
- }
- public void bindSDLService(Context context, SDLServiceConnectionProxy connectionProxy) {
- Logger.i("BindStorageService(), connection proxy: " + connectionProxy);
- context.bindService(new Intent(context, SDLService.class), connectionProxy, BIND_AUTO_CREATE);
- }
-
- public void unbindSDLService(Context context, SDLServiceConnectionProxy connectionProxy) {
- if (!connectionProxy.isConnected()) {
- Logger.v("ServiceConnection is not connected, ignoring unbindService: " + connectionProxy);
- return;
- }
- try {
- Logger.i("Unbind Service(), connection proxy: " + connectionProxy);
- context.unbindService(connectionProxy);
- } catch (IllegalArgumentException iae) {
- // sometimes this exception is still thrown, in spite of isConnected() check above
- // simply ignore this exception
- Logger.w("Unbind IllegalArgumentException: " + iae);
- } catch (Exception e) {
- Logger.e("Error unbinding from connection: " + connectionProxy, e);
- }
- }
-
-
- public boolean onOptionsItemSelected(MenuItem item) {
- final int itemId = item.getItemId();
- switch (itemId) {
- case R.id.mnuQuit:
- exitApp();
- break;
- default:
- break;
- }
- return false;
- }
-
- private void exitApp() {
- Logger.d("Exiting application");
-
- finish();
- // the delay should be long enough, so that UnregisterAppInterface and
- // EndSession messages are sent
- new Timer().schedule(new TimerTask() {
- @Override
- public void run() {
- android.os.Process.killProcess(android.os.Process.myPid());
- }
- }, 2000);
- }
-
- public boolean isFirstStart() {
- SharedPreferences prefs = getSharedPreferences(Const.SHPREF_FIRST_LAUNCH, 0);
- int previousCodeVersion = prefs.getInt(Const.SHPREF_PREVIOUS_CODE_VERSION, 0);
- int currentCodeVersion = Utils.getAppVersionCode(this);
- if (previousCodeVersion < currentCodeVersion) {
- return true;
- }
- return false;
- }
-
- public void surfaceCreated(SurfaceHolder holder) {
- Logger.i("surface created");
- playVideo(holder);
-
- }
-
- public void surfaceDestroyed(SurfaceHolder holder) {
- Logger.i("surface destroyed");
- }
-
- // =============================================================
- // GETTERS
- // =============================================================
- public WebView getWebView() {
- return mWebView;
- }
-
- public MediaPlayer getMediaPlayer() {
- return mMediaPlayer;
- }
-
- // get value from application settings
- public Boolean getFullscreenStatus() {
- return mPreferences.getBoolean("FULLSCREEN", true);
- }
-
- // get value from application settings
- public Boolean getMapsStatus() {
- return mPreferences.getBoolean("MAPS", true);
- }
-
- // get value from application settings
- public String getVehicleStatus() {
- return mPreferences.getString("VEHICLES", "Ford");
- }
-
- // get value from application settings
- public Boolean getRateStatus() {
- return mPreferences.getBoolean("RATE", true);
- }
-
- // set value to application settings
- public Boolean setMapsStatus(boolean value) {
- SharedPreferences.Editor editor = mPreferences.edit();
- editor.putBoolean("MAPS", value);
- editor.commit();
- return true;
- }
-
- // set value to application settings
- public boolean setVehicleStatus(String value) {
- SharedPreferences.Editor editor = mPreferences.edit();
- editor.putString("VEHICLES", value);
- editor.commit();
- return true;
- }
-
- public double audioGetPosition() {
- return mediaGetPosition();
- }
-
- public String getPathToDownloadedAudioFile(String fileName) {
- final File file = new File(getExternalFilesDir(null), fileName + ".mp3");
- return file.getAbsolutePath();
- }
-
- public Handler getMainHandler() {
- return handler;
- }
-
- public int getVideoPausedPosition() {
- return mVideoPauseTime;
- }
-
- public double videoGetPosition() {
- return mediaGetPosition();
- }
-
- public boolean videoWasPaused() {
- return mVideoWasPaused;
- }
-
- public boolean getVideoPlayed() {
- return mVideoPlayed;
- }
-
- public JSONVideoController getVideoController() {
- return mVideoController;
- }
-
- public boolean getVideoPrepared() {
- return mVideoPrepared;
- }
-
- public JSONBackendController getBEController() {
- return mBEController;
- }
-
- // setters
-
- public void setVideoPlayed(boolean value) {
- mVideoPlayed = value;
- }
-
- public void setVideoPrepared(boolean value) {
- mVideoPrepared = value;
- }
-
- // ==============================================================
- // OTHER METHODS
- // ==============================================================
-
- public void startVideoTimer() {
- // start timer to send every N ms current time position of video
- Logger.i("Start Timer");
- int N = 500;
-
- stopVideoTimer();
-
- mVideoTimer = new Timer();
- TimerTask timerTask = new TimerTask() {
- @Override
- public void run() {
- // current position in MP never reaches duration value
- // check difference on 500 msec
- if (mVideoPrepared) {
- if ((mMediaPlayer.getDuration() - mMediaPlayer.getCurrentPosition()) < 500)
- mVideoController.sendPositionNotification(mMediaPlayer.getDuration());
- else
- mVideoController.sendPositionNotification(mMediaPlayer.getCurrentPosition());
- }
- }
- };
- mVideoTimer.schedule(timerTask, N, N);
- }
-
- public void setProgresbarVisibility(boolean value) {
- int v = value ? ProgressBar.VISIBLE : ProgressBar.GONE;
- mProgressBar.setVisibility(v);
- }
-
- // =====================================================================
- // private section
- // =====================================================================
-
- // private Context ctx;
-
- private MediaPlayer mMediaPlayer;
-
- private SharedPreferences mPreferences;
- private WebView mWebView;
- private SurfaceView mPreview;
- private SurfaceHolder mHolder;
- private ProgressBar mProgressBar;
- private RelativeLayout mVideoLayout;
- private ImageView mLogo;
-
- private int mSeekTo;
-
- private int mVideoWidth;
- private int mVideoHeight;
- private int mLeftMargin;
- private int mTopMargin;
-
- private String mPath;
-
- private Animation mAnimationShow;
-
- // for JSON communication
- private JSONServer mServerThread;
- private JSONBackendController mBEController;
- private JSONVideoController mVideoController;
-
- // for video time visualization
- private Timer mVideoTimer;// timer to send notifications about current video
- // time
- private boolean mVideoWasPaused = false;// indicate if video was on paused
- // before starting activity
- private int mVideoPauseTime = 0;// time in msec when video was paused before
- // starting activity
- private boolean mVideoPlayed = false;// indicate if video played before
- // starting activity
- // to measure 5 seconds for splash screen;
- private long mStartTime;
- private boolean mVideoPrepared = false; // indicate that video in MP is
- // prepared and timer can be started
-
- private AppRater mAppRater;
-
- private ZipResourceFile apkExpansionZipFile = null;
- private Context mContext;
-
- private final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
-
- super.handleMessage(msg);
-
- switch (msg.what) {
-
- // /// VIDEO
- case Const.VIDEO_START:
- Logger.i("mMediaPlayer.play handler");
- Object[] obj = (Object[]) msg.obj;
- String videoFile = (String) obj[0];
- Double scale = (Double) obj[1];
- int x = (Integer) obj[2];
- int y = (Integer) obj[3];
- videoViewResize(scale, y, x);
- mPath = videoFile;
- initVideoSurface();
- break;
- case Const.VIDEO_PAUSE:
- Logger.i("mMediaPlayer.pause handler");
- stopVideoTimer();
- if (mMediaPlayer != null)
- mMediaPlayer.pause();
- mVideoWasPaused = true;
- mVideoPauseTime = mMediaPlayer.getCurrentPosition();
- break;
- case Const.VIDEO_SET_POSITION:
- Double newPos = (Double) msg.obj * 1000;
- newPos = newPos == 0 ? 1 : newPos; // because media player can
- // not set zero value
- if (mMediaPlayer != null)
- mediaSetPosition(newPos);
- break;
- case Const.VIDEO_SET_POSITION_PAUSED:
- newPos = (Double) msg.obj * 1000;
- newPos = newPos == 0 ? 1 : newPos; // because media player can
- // not set zero value
- if (mMediaPlayer != null)
- mediaSetPositionPaused(newPos);
- break;
- case Const.VIDEO_PLAY:
- startVideoTimer();
- mVideoWasPaused = false;
- Logger.i("mMediaPlayer.start case Const.VIDEO_PLAY");
- if (null != mMediaPlayer) {
- mMediaPlayer.start();
- } else {
- Logger.i("mMediaPlayer == null");
- }
- break;
- case Const.VIDEO_STOP:
- mVideoLayout.setVisibility(View.INVISIBLE);
- stopVideoTimer();
- releaseMediaPlayer();
- mVideoWidth = 0;
- mVideoHeight = 0;
- mLeftMargin = 0;
- mTopMargin = 0;
- mPath = null;
- mVideoWasPaused = false;
- mVideoPlayed = false;
- mVideoPauseTime = 0;
- break;
- case Const.VIDEO_PLAY_AFTER_SCALE:
- Logger.i("mMediaPlayer.play after scale handler");
- obj = (Object[]) msg.obj;
- scale = (Double) obj[0];
- int left = (Integer) obj[1];
- int top = (Integer) obj[2];
- videoViewResize(scale, top, left);
- initVideoSurface();
- break;
-
- case Const.CONTENT_CHECKER_START:
- verifyContent();
- break;
-
- case Const.WEBVIEW_SHOW:
- hideSplashScreen();
- setProgresbarVisibility(false);
- mWebView.startAnimation(mAnimationShow);
- mWebView.setVisibility(View.VISIBLE);
- if (Const.DEBUG) {
- long currTime = System.currentTimeMillis();
- String str = "Application loading time = "
- + String.valueOf(currTime - mStartTime);
- Toast.makeText(getApplicationContext(), str,
- Toast.LENGTH_LONG).show();
- Logger.i(str);
- }
- showSDLSetupDialog();
- break;
-
- default:
- break;
- }
- }
-
- };
-
- private void verifyContent() {
-
- removeOldVideoFiles();
-
- // check main expansion file
- int mainVersionCode = expFileIsDelivered(true);
-
- SharedPreferences prefs = getSharedPreferences(
- Const.SHPREF_DOWNLOADER_PREFS, 0);
- boolean mainMD5IsCalculated = prefs.getBoolean(
- Const.SHPREF_MAIN_EXPFILE_VALID, false);
-
- // check patch expansion file
- int patchVersionCode = expFileIsDelivered(false);
-
- boolean patchMD5IsCalculated = prefs.getBoolean(
- Const.SHPREF_PATCH_EXPFILE_VALID, false);
-
- if (mainVersionCode > 0 && mainMD5IsCalculated
- && (patchVersionCode > 0 || Const.PATCH_EXP_FILE_SIZE == 0)
- && patchMD5IsCalculated) {
- try {
- apkExpansionZipFile = APKExpansionSupport
- .getAPKExpansionZipFile(this, mainVersionCode,
- patchVersionCode);
- } catch (IOException e) {
- Logger.e(e.getMessage(), e);
- }
-
- } else {
- // no expansion file
- SharedPreferences.Editor editor = prefs.edit();
- if (editor != null) {
- editor.putBoolean(Const.SHPREF_MAIN_EXPFILE_VALID, false);
- editor.putBoolean(Const.SHPREF_PATCH_EXPFILE_VALID, false);
- }
- editor.commit();
- // create downloader client
- new DownloaderClient(this, mainVersionCode, mainMD5IsCalculated,
- patchVersionCode, patchMD5IsCalculated);
-
- }
-
- Utils.sendMessageToHandler(Const.WEBVIEW_SHOW,
- MessageConst.NET_DOWNLOAD_FINISHED_SUCC, handler);
- }
-
- /**
- * checks if expansion file was downloaded previously
- *
- * @param isMain
- * - is a main expansion file or a patch
- * @return version code if file exists or 0
- */
-
- private int expFileIsDelivered(boolean isMain) {
- int codeVersion = Utils.getAppVersionCode(getApplicationContext());
- long size = isMain ? Const.MAIN_EXP_FILE_SIZE
- : Const.PATCH_EXP_FILE_SIZE;
- while (codeVersion > 0) {
- XAPKFile xFile = new XAPKFile(isMain, codeVersion, size);
- if (ExtStorageUtils.expansionFilesDelivered(mContext, xFile)) {
- return codeVersion;
- }
- codeVersion--;
- }
- return codeVersion;
- }
-
- public void setExpantionFile(ZipResourceFile file) {
- apkExpansionZipFile = file;
- }
-
- /**
- * removes video files of MFTG 2, that is apart of expansion file
- */
- private boolean removeOldVideoFiles() {
- File oldVideoFilesDirectory = getExternalFilesDir(null);
- if ((oldVideoFilesDirectory != null) &&
- oldVideoFilesDirectory.exists()) {
- boolean success = true;
- final File[] files = oldVideoFilesDirectory.listFiles();
- if (files != null) {
- for (File file : files) {
- success &= file.delete();
- }
- return success;
- }
- }
- Logger.i("Couldn't remove old video files");
- return false;
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- Logger.i(getClass().getSimpleName() + " onPause, hash:" + hashCode());
- if (!isFirstStart()) {
- ActivityUtils.setAppIsForeground(false);
- // switch of timer
- stopVideoTimer();
- // remember last video position
- if (mMediaPlayer != null)
- mVideoPauseTime = mMediaPlayer.getCurrentPosition();
- // delete media player
- releaseMediaPlayer();
- mVideoLayout.removeAllViews();
- }
- }
-
- protected void onResume() {
- super.onResume();
- Logger.i(getClass().getSimpleName() + " onResume, hash:" + hashCode());
- if (!isFirstStart()) {
- resumeAvatarActivity();
- }
- }
-
- private void startAvatarActivity() {
- mStartTime = System.currentTimeMillis();
- mContext = this;
- // Possible work around for market launches. See
- // http://code.google.com/p/android/issues/detail?id=2373
- // for more details. Essentially, the market launches the main activity
- // on top of other activities.
- // we never want this to happen. Instead, we check if we are the root
- // and if not, we finish.
- if (!isTaskRoot()) {
- final Intent intent = getIntent();
- final String intentAction = intent.getAction();
- if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null
- && intentAction.equals(Intent.ACTION_MAIN)) {
- Logger.w("Main Activity is not the root. Finishing Main Activity instead of launching.");
- finish();
- return;
- }
- }
-
- mAppRater = new AppRater(this);
- startRPCComponents();
- prepareMainView();
- WebViewUtils.initWebView(this);
- initVideoSurface();
- }
-
- private void resumeAvatarActivity() {
- ActivityUtils.setAppIsForeground(true);
-
- if (!fullscreenPreferenceChanged && !vehiclePreferenceChanged)
- initVideoSurface(); // to init video after resuming but not
- // after FullScreen or Vehicle changing
-
- if (mPreferences != null) {
- if (fullscreenPreferenceChanged) {
- fullscreenPreferenceChanged = false;
- mBEController.sendFullScreenRequest(getFullscreenStatus());
- }
-
- if (vehiclePreferenceChanged) {
- vehiclePreferenceChanged = false;
- mBEController.sendVehicleNotification(getVehicleStatus());
- }
-
- if (navigationPreferenceChanged) {
- navigationPreferenceChanged = false;
- mBEController.sendHasMapsNotification(getMapsStatus());
- }
-
- if (mWebView.getUrl() == null) {
- if (!loadContent()) {
- Toast.makeText(this, R.string.toast_index_not_found, Toast.LENGTH_LONG).show();
- }
- }
- }
- }
-
- private void showSDLSetupDialog() {
- LayoutInflater inflater = getLayoutInflater();
- View dialogView = inflater.inflate(R.layout.sdl_settings, null);
-
- if (dialogView == null) {
- return;
- }
-
- final EditText ipAddressText = (EditText) dialogView.findViewById(R.id.sdl_ipAddr);
- final EditText tcpPortText = (EditText) dialogView.findViewById(R.id.sdl_tcpPort);
-
- final SharedPreferences prefs = getSharedPreferences(Const.PREFS_NAME, 0);
- String ipAddressString = prefs.getString(Const.PREFS_KEY_IPADDR, Const.PREFS_DEFAULT_IPADDR);
- int tcpPortInt = prefs.getInt(Const.PREFS_KEY_TCPPORT, Const.PREFS_DEFAULT_TCPPORT);
-
- ipAddressText.setText(ipAddressString);
- tcpPortText.setText(String.valueOf(tcpPortInt));
-
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setView(dialogView)
- .setTitle("Please provide SDL address")
- .setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- String ipAddressString = ipAddressText.getText().toString();
- int tcpPortInt;
- try {
- tcpPortInt = Integer.parseInt(tcpPortText.getText().toString());
- } catch (NumberFormatException e) {
- Logger.i("Couldn't parse port number", e);
- tcpPortInt = Const.PREFS_DEFAULT_TCPPORT;
- }
-
- SharedPreferences.Editor prefsEditor =
- getSharedPreferences(Const.PREFS_NAME, 0).edit();
- prefsEditor.putString(Const.PREFS_KEY_IPADDR, ipAddressString);
- prefsEditor.putInt(Const.PREFS_KEY_TCPPORT, tcpPortInt);
- prefsEditor.commit();
-
- Intent intent = new Intent(getApplicationContext(), SDLService.class);
- //intent.putExtra()
- startService(intent);
- }
- })
- .show();
- }
-
- @Override
- protected void onDestroy() {
- Logger.i(getClass().getSimpleName() + " onDestroy, hash:" + hashCode());
-
- unbindSDLService(getBaseContext(), mSDLServiceConnectionProxy);
- stopService(new Intent(this, SDLService.class));
-
- if (!isFirstStart()) {
- // switch of timer
- stopVideoTimer();
-
- releaseMediaPlayer();
- doCleanUp();
- // close JSON server
- try {
- if (mServerThread != null)
- mServerThread.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- super.onDestroy();
- }
-
- /**
- * Checks if the filename exists in the assets.
- *
- * @param assetFilename Filename without any prefix
- * @return true if the file exists
- */
- private boolean assetExists(final String assetFilename) {
- AssetManager am = getResources().getAssets();
- try {
- am.open(assetFilename);
- } catch (IOException e) {
- return false;
- }
- return true;
- }
-
- private boolean loadContent() {
- Logger.i("loadContent");
- boolean successful = false;
- if (assetExists(Const.INDEX_PAGE)) {
- mWebView.loadUrl(Const.WEB_MAIN_PAGE_PATH);
- successful = true;
- }
- return successful;
- }
-
- private void startRPCComponents() {
- Logger.i(getClass().getSimpleName() + " Start RPC Components");
-
- mServerThread = new JSONServer();
- mServerThread.setName("ServerThread");
- mServerThread.start();
-
- // wait for a while
- while (!mServerThread.isReady()) {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- mBEController = new JSONBackendController(this);
- mBEController.register(27);
- // wait for a while
- while (!mBEController.isRegistered()) {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- mVideoController = new JSONVideoController(this);
- mVideoController.register(28);
- // wait for a while
- while (!mVideoController.isRegistered()) {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- JSONRateController mRateController = new JSONRateController(mAppRater);
- mRateController.register(29);
- // wait for a while
- while (!mRateController.isRegistered()) {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- JSONRevSDLController mRevSDLController = new JSONRevSDLController();
- mRevSDLController.register(30);
- // wait for a while
- while (!mRevSDLController.isRegistered()) {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- private void prepareMainView() {
- Logger.i("prepareMainView");
- setContentView(R.layout.main);
-
- mPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
- Boolean fullScreen = getFullscreenStatus();
- mLogo = (ImageView) findViewById(R.id.logo);
- Logger.i("mFullScreen is " + fullScreen.toString());
- if (fullScreen) {
- RelativeLayout.LayoutParams params = new LayoutParams(
- LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- mLogo.setLayoutParams(params);
- // mLogo.setLayoutParams(params);
- } else {
-
- RelativeLayout.LayoutParams params = new LayoutParams(800, 480);
- params.addRule(RelativeLayout.CENTER_HORIZONTAL);
- params.addRule(RelativeLayout.CENTER_VERTICAL);
- mLogo.setLayoutParams(params);
- }
- mWebView = (WebView) findViewById(R.id.webView1);
- mWebView.setWebChromeClient(new WebChromeClient());
- mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
- // mWebView.getSettings().setLoadWithOverviewMode(true);
- // mWebView.getSettings().setUseWideViewPort(true);
- // mWebView.setInitialScale(10);
-
- mVideoLayout = (RelativeLayout) findViewById(R.id.videoLayout);
- // set progress bar
- mProgressBar = (ProgressBar) findViewById(R.id.pbProgress);
- LayoutParams progressParams = (LayoutParams) mProgressBar
- .getLayoutParams();
- double loaderHeight = Const.WEB_HEIGHT * getScale() * 0.07 * getWindowDensity();
- progressParams.height = (int) loaderHeight;
- progressParams.width = progressParams.height;
- double loaderVerticalCenter = getWindowHeight() * 0.5;
- double loaderVerticalShift = Const.WEB_HEIGHT * getScale() * 0.5 * 0.41 * getWindowDensity();
- double top = (loaderVerticalCenter - 0.5 * loaderHeight) + loaderVerticalShift;
- progressParams.topMargin = (int) Math.round(top);
- mProgressBar.setLayoutParams(progressParams);
-
- mAnimationShow = AnimationUtils.loadAnimation(this, R.anim.show);
- }
-
- private double getScale() {
- double res = 1;
- if (isFullScreen()) {
- /** Calculate Scale Point */
- double scalePointW = (double) getWindowWidth()
- / (double) Const.WEB_WIDTH / getWindowDensity();
- double scalePointH = (double) getWindowHeight()
- / (double) Const.WEB_HEIGHT / getWindowDensity();
- /** Set calculated ScalePoint */
- res = (scalePointW >= scalePointH) ? scalePointH : scalePointW;
- } else {
- res /= getWindowDensity();
- }
- return res;
- }
-
- private boolean isFullScreen() {
- SharedPreferences preferences = PreferenceManager
- .getDefaultSharedPreferences(this.getApplicationContext());
- return preferences.getBoolean("FULLSCREEN", true);
- }
-
- private Integer getWindowHeight() {
- Integer height;
- if ((Build.VERSION.SDK_INT > 10)/* && (Build.VERSION.SDK_INT < 14) */) {
- // return height without tabs bar
- Rect rectgle = new Rect();
- Window window = this.getWindow();
- window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
- height = rectgle.bottom; // height = - panel height
- } else {
- DisplayMetrics dm = new DisplayMetrics();
- this.getWindowManager().getDefaultDisplay().getMetrics(dm);
- if (dm.heightPixels > dm.widthPixels) {
- height = dm.widthPixels;
- } else {
- height = dm.heightPixels;
- }
- }
- return height;
- }
-
- private Integer getWindowWidth() {
- Integer width;
- DisplayMetrics dm = new DisplayMetrics();
- this.getWindowManager().getDefaultDisplay().getMetrics(dm);
- if (dm.heightPixels > dm.widthPixels) {
- width = dm.heightPixels;
- } else {
- width = dm.widthPixels;
- }
- return width;
- }
-
- private void initVideoSurface() {
- Logger.i("init surface");
-
- mVideoLayout.setVisibility(View.INVISIBLE);
- mVideoLayout.removeAllViews();
-
- LayoutParams params = (LayoutParams) mVideoLayout.getLayoutParams();
-
- params.height = mVideoHeight;
- params.width = mVideoWidth;
- params.leftMargin = mLeftMargin;
- params.topMargin = mTopMargin;
-
- mVideoLayout.setLayoutParams(params);
- mPreview = new SurfaceView(this);
-
- mVideoLayout.addView(mPreview);
- mHolder = mPreview.getHolder();
- mHolder.addCallback(this);
- mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- mVideoLayout.forceLayout();
- mVideoLayout.setVisibility(View.VISIBLE);
-
- }
-
- private void hideSplashScreen() {
- Logger.i("hide screen ");
- mVideoLayout.setVisibility(View.VISIBLE);
- mLogo.setVisibility(View.INVISIBLE);
- }
-
- private double mediaGetPosition() {
- // setIsGetPosition(true);
- Logger.i("mediaGetPosition");
- // isDoubleSeek = true;
- if (mMediaPlayer == null) {
- return -1;
- }
- try {
- return Utils
- .getShortDouble(mMediaPlayer.getCurrentPosition() / 1000.0);
- } catch (IllegalStateException e) {
- Logger.e(e.getMessage(), e);
- return -1;
- }
- }
-
- private void mediaSetPosition(double position) {
- /* convert to milliseconds */
- // setIsGetPosition(false);
- // position *= 1000;
- mSeekTo = (int) position;
- Logger.i("mediaSetPosition=" + position);
-
- try {
- if (mSeekTo != 0)
- mMediaPlayer.seekTo(mSeekTo);
- } catch (IllegalStateException e) {
- Logger.e(e.getMessage(), e);
- }
- }
-
- private void mediaSetPositionPaused(double position) {
- /* convert to milliseconds */
- mSeekTo = (int) position;
-
- Logger.i("mediaSetPositionPaused=" + position);
-
- AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
- audioManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
- try {
- mMediaPlayer.seekTo(mSeekTo);
- } catch (IllegalStateException e) {
- Logger.e(e.getMessage(), e);
- }
- }
-
- private void releaseMediaPlayer() {
- if (mMediaPlayer != null) {
- mMediaPlayer.reset();
- mMediaPlayer.release();
- mMediaPlayer = null;
- }
- mVideoPrepared = false;
- }
-
- private void videoViewResize(double scale, int top, int left) {
- mVideoWidth = (int) (Const.ORIG_VIDEO_WIDTH * scale * getWindowDensity() - 1);
- mVideoHeight = (int) (Const.ORIG_VIDEO_HEIGHT * scale * getWindowDensity() - 1);
- mLeftMargin = (int) Math.round(left * getWindowDensity());
- mTopMargin = (int) Math.round(top * getWindowDensity());
- }
-
- private double getWindowDensity() {
- DisplayMetrics dm = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(dm);
- return dm.density;
- }
-
- private void playVideo(SurfaceHolder holder) {
- Logger.i("playVideo");
- if (mPath != null) {
- try {
- if (mMediaPlayer != null) {
- releaseMediaPlayer();
- }
- // TODO : optimize MP instantiation
- // Create a new media player and set the listeners
- mMediaPlayer = new MediaPlayer();
-
- initDatasourceWith(mPath);
-
- Logger.i("video file path : " + mPath);
-
- mMediaPlayer.setDisplay(holder);
-
- mMediaPlayer.setOnPreparedListener(new AvatarOnPreparedListener(this));
- mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
-
- mMediaPlayer.prepare();
- } catch (Exception e) {
- Logger.e("error: " + e.getMessage(), e);
- // set duration of video
- mVideoController.setVideoDuration(-1);
- }
- } else {
- Logger.i("No video to play");
- }
- }
-
- private void stopVideoTimer() {
- if (mVideoTimer != null) {
- mVideoTimer.cancel();
- mVideoTimer.purge();
- }
- mVideoTimer = null;
- }
-
- private void doCleanUp() {
- mVideoWidth = 0;
- mVideoHeight = 0;
- if (mVideoLayout != null)
- mVideoLayout.removeAllViews();
- mHolder = null;
- mPreview = null;
- mVideoWasPaused = false;
- mVideoPauseTime = 0;
- mVideoPlayed = false;
- }
-
- private void initDatasourceWith(String fileName)
- throws ExtensionFileException, MediaPlayerException {
-
- AssetFileDescriptor assetFileDescriptor;
- // welcome orientation video is in raw resources
- if (fileName.toLowerCase().compareTo(Const.WELCOME_VIDEO_FILE_NAME) == 0) {
- assetFileDescriptor = getResources().openRawResourceFd(R.raw.faq_welcome_orientation);
- } else {
- // get file from expansion archive
- if (apkExpansionZipFile == null) {
- throw new ExtensionFileException("Expansion zip file variable is not initialized");
- }
- assetFileDescriptor = apkExpansionZipFile.getAssetFileDescriptor(fileName);
- }
-
- if (assetFileDescriptor == null) {
- throw new ExtensionFileException("Assert file descriptor for file: " + fileName +
- " not found");
- }
-
- try {
- mMediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(),
- assetFileDescriptor.getStartOffset(),
- assetFileDescriptor.getLength());
- } catch (IllegalArgumentException e) {
- throw new MediaPlayerException(e);
- } catch (IllegalStateException e) {
- throw new MediaPlayerException(e);
- } catch (IOException e) {
- throw new MediaPlayerException(e);
- }
- }
-
- @Override
- public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
- }
-
- @Override
- public void onSDLServiceConnected(SDLServiceBinder service) {
- Logger.i("SDLService connected " + service);
-
- mBoundSDLService = service.getService();
- }
-
- @Override
- public void onSDLServiceDisconnected() {
- Logger.i("SDLService disconnected");
-
- mBoundSDLService = null;
- }
-} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/activity/EulaActivity.java b/native/android/avatar/src/main/java/com/ford/avarsdl/activity/EulaActivity.java
deleted file mode 100644
index 2bb9916006..0000000000
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/activity/EulaActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.ford.avarsdl.activity;
-
-import com.ford.avarsdl.R;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-
-public class EulaActivity extends Activity {
-
- private Button btnAgree;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.eula);
- btnAgree=(Button)findViewById(R.id.btnAgree);
- Bundle extras = getIntent().getExtras();
- if (extras != null && !extras.getBoolean("firstStart")){
- btnAgree.setText("Done");
- }
- btnAgree.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- Intent intent = getIntent();
- setResult(Activity.RESULT_OK, intent);
- finish();
- }
- });
- }
-
-
-}
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/downloader/DownloaderClient.java b/native/android/avatar/src/main/java/com/ford/avarsdl/downloader/DownloaderClient.java
index 7a48f7880b..e2590e820a 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/downloader/DownloaderClient.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/downloader/DownloaderClient.java
@@ -33,7 +33,7 @@ import android.widget.Toast;
import com.android.vending.expansion.zipfile.APKExpansionSupport;
import com.android.vending.expansion.zipfile.ZipResourceFile;
import com.ford.avarsdl.R;
-import com.ford.avarsdl.activity.AvatarActivity;
+import com.ford.avarsdl.views.AvatarActivity;
import com.ford.avarsdl.util.ActivityUtils;
import com.ford.avarsdl.util.Const;
import com.ford.avarsdl.util.LogUtils;
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONAVAController.java b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONAVAController.java
index f3185ce582..e7f75dd6df 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONAVAController.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONAVAController.java
@@ -1,84 +1,67 @@
package com.ford.avarsdl.jsoncontroller;
-import android.util.Log;
-
-import com.ford.avarsdl.activity.AvatarActivity;
-import com.ford.avarsdl.util.Const;
+import com.ford.avarsdl.views.AvatarActivity;
+import com.ford.avarsdl.util.Logger;
import com.ford.avarsdl.util.RPCConst;
-public class JSONAVAController extends JSONController{
-
- private final boolean DEBUG = true;
- private String mJSComponentName = null;
- private final String TAG_NAME = "AVAController";
- private AvatarActivity mActivity;
-
- public JSONAVAController(AvatarActivity activity, String cname) {
- super(RPCConst.CN_AVATAR);
- mActivity = activity;
- mJSComponentName = cname;
- }
-
- public JSONAVAController(String cname, ITcpClient client) {
- super(RPCConst.CN_AVATAR,client);
- mJSComponentName = cname;
- }
-
-
- protected void processRequest(String request){
- processNotification(request);
- }
-
- protected String processNotification(String notification){
- logMsg("Process notification");
- mJSONParser.putJSONObject(notification);
- final String func = "FFW.WebSocketSimulator.receive('" + mJSComponentName
- + "','" + notification + "')";
- //LogMsg(func);
- logMsg("Send notification to JS");
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mActivity.getWebView().loadUrl("javascript:" + func);
- }
- });
- return null;
- }
-
- protected void processResponse(String response){
- if (!processRegistrationResponse(response)){
- final String func = "FFW.WebSocketSimulator.receive('" + mJSComponentName
- + "','" + response + "')";
- logMsg(func);
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mActivity.getWebView().loadUrl("javascript:" + func);
- }
- });
- }
-
-
- }
-
- public void sendJSMessage(String cName, String jsonMsg){
- logMsg("SendJSMessage : " + jsonMsg);
- mJSONParser.putJSONObject(jsonMsg);
- if(mJSONParser.getId()>=0 &&
- mJSONParser.getResult() == null &&
- mJSONParser.getError() == null){
- mJSComponentName = cName;
- }
- jsonMsg += System.getProperty("line.separator");
- sendJSONMsg(jsonMsg);
-
- }
-
- private void logMsg(String msg){
- if (DEBUG && Const.DEBUG){
- Log.i(TAG_NAME, msg);
- }
- }
+public class JSONAVAController extends JSONController {
+
+ private String mJSComponentName = null;
+ private AvatarActivity mActivity;
+
+ public JSONAVAController(AvatarActivity activity, String cname) {
+ super(RPCConst.CN_AVATAR);
+ mActivity = activity;
+ mJSComponentName = cname;
+ }
+
+ public JSONAVAController(String cname, ITcpClient client) {
+ super(RPCConst.CN_AVATAR, client);
+ mJSComponentName = cname;
+ }
+
+ protected void processRequest(String request) {
+ processNotification(request);
+ }
+
+ protected String processNotification(String notification) {
+ Logger.d(getClass().getSimpleName() + " Process notification: " + notification);
+ mJSONParser.putJSONObject(notification);
+ final String func = "FFW.WebSocketSimulator.receive('" + mJSComponentName
+ + "','" + notification + "')";
+ Logger.d(getClass().getSimpleName() + " Send notification to JS");
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.getWebView().loadUrl("javascript:" + func);
+ }
+ });
+ return null;
+ }
+
+ protected void processResponse(String response) {
+ if (!processRegistrationResponse(response)) {
+ final String func = "FFW.WebSocketSimulator.receive('" + mJSComponentName
+ + "','" + response + "')";
+ Logger.d(getClass().getSimpleName() + " : " + func);
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mActivity.getWebView().loadUrl("javascript:" + func);
+ }
+ });
+ }
+ }
-
-}
+ public void sendJSMessage(String cName, String jsonMsg) {
+ //Logger.d(getClass().getSimpleName() + " SendJSMessage : " + jsonMsg);
+ mJSONParser.putJSONObject(jsonMsg);
+ if (mJSONParser.getId() >= 0 &&
+ mJSONParser.getResult() == null &&
+ mJSONParser.getError() == null) {
+ mJSComponentName = cName;
+ }
+ jsonMsg += System.getProperty("line.separator");
+ sendJSONMsg(jsonMsg);
+ }
+} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONBackendController.java b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONBackendController.java
index e5592be997..2414cb46b7 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONBackendController.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONBackendController.java
@@ -8,9 +8,9 @@ import android.os.Message;
import android.util.DisplayMetrics;
import android.view.Window;
-import com.ford.avarsdl.activity.AvatarActivity;
-import com.ford.avarsdl.activity.EulaActivity;
-import com.ford.avarsdl.activity.SafeToast;
+import com.ford.avarsdl.views.AvatarActivity;
+import com.ford.avarsdl.views.EulaActivity;
+import com.ford.avarsdl.views.SafeToast;
import com.ford.avarsdl.jsonparser.EBEMethods;
import com.ford.avarsdl.util.Const;
import com.ford.avarsdl.util.Logger;
@@ -166,18 +166,15 @@ public class JSONBackendController extends JSONController {
* @return
*/
private String isFirstStart() {
-
boolean firstStart = mActivity.isFirstStart();
if (firstStart) {
firstStart = true;
// set new code version
- SharedPreferences prefs = mActivity.getSharedPreferences(
- Const.SHPREF_FIRST_LAUNCH, 0);
+ SharedPreferences prefs = mActivity.getSharedPreferences(Const.SHPREF_FIRST_LAUNCH, 0);
SharedPreferences.Editor editor = prefs.edit();
if (editor != null) {
int currentCodeVersion = Utils.getAppVersionCode(mActivity);
- editor.putInt(Const.SHPREF_PREVIOUS_CODE_VERSION,
- currentCodeVersion);
+ editor.putInt(Const.SHPREF_PREVIOUS_CODE_VERSION, currentCodeVersion);
}
editor.commit();
// set redownload counter to 0
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONController.java b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONController.java
index d6d86e3e32..f3b731b842 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONController.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONController.java
@@ -126,7 +126,7 @@ public class JSONController {
protected void sendJSONMsg(String jsonMsg) {
mTCPClient.sendMsg(jsonMsg);
- Logger.i(getClass().getSimpleName() + " sent: " + jsonMsg);
+ Logger.i(getClass().getSimpleName() + " JSON Msg sent: " + jsonMsg);
}
/**
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONRevSDLController.java b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONRevSDLController.java
index 7c8dfbcad3..a498e9575b 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONRevSDLController.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONRevSDLController.java
@@ -1,10 +1,13 @@
package com.ford.avarsdl.jsoncontroller;
+import com.ford.avarsdl.requests.CancelAccessCommand;
import com.ford.avarsdl.requests.GrantAccessCommand;
import com.ford.avarsdl.requests.RequestCommand;
import com.ford.avarsdl.requests.StartScanCommand;
import com.ford.avarsdl.requests.StopScanCommand;
+import com.ford.avarsdl.requests.TuneDownCommand;
import com.ford.avarsdl.requests.TuneRadioCommand;
+import com.ford.avarsdl.requests.TuneUpCommand;
import com.ford.avarsdl.util.Logger;
import com.ford.avarsdl.util.RPCConst;
import com.ford.syncV4.proxy.constants.Names;
@@ -45,6 +48,9 @@ public class JSONRevSDLController extends JSONController {
GrantAccessCommand grantAccessCommand = new GrantAccessCommand();
commandsHashTable.put(Names.GrantAccess, grantAccessCommand);
+ CancelAccessCommand cancelAccessCommand = new CancelAccessCommand();
+ commandsHashTable.put(Names.CancelAccess, cancelAccessCommand);
+
StartScanCommand startScanCommand = new StartScanCommand();
commandsHashTable.put(Names.StartScan, startScanCommand);
@@ -53,5 +59,11 @@ public class JSONRevSDLController extends JSONController {
TuneRadioCommand tuneRadioCommand = new TuneRadioCommand();
commandsHashTable.put(Names.TuneRadio, tuneRadioCommand);
+
+ TuneUpCommand tuneUpCommand = new TuneUpCommand();
+ commandsHashTable.put(Names.TuneUp, tuneUpCommand);
+
+ TuneDownCommand tuneDownCommand = new TuneDownCommand();
+ commandsHashTable.put(Names.TuneDown, tuneDownCommand);
}
} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONVideoController.java b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONVideoController.java
index 1af78f0b8c..adfc0ac732 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONVideoController.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/jsoncontroller/JSONVideoController.java
@@ -1,10 +1,11 @@
package com.ford.avarsdl.jsoncontroller;
import java.io.File;
+
import android.content.SharedPreferences;
import android.util.Log;
-import com.ford.avarsdl.activity.AvatarActivity;
+import com.ford.avarsdl.views.AvatarActivity;
import com.ford.avarsdl.downloader.DownloaderClient;
import com.ford.avarsdl.exception.SDCardException;
import com.ford.avarsdl.jsonparser.EVideoMethods;
@@ -20,398 +21,381 @@ import com.ford.avarsdl.util.WebViewUtils;
* <b>File:</b> JSONVideoController.java <br>
* <b>Description:</b> Controller that is responsible for video data
* transferring through JSON RPC 2.0 protocol <br>
- *
+ *
* @author kbotnar
- *
*/
public class JSONVideoController extends JSONController {
- /**
- * Constructor
- *
- * @param activity
- * : the application main activity
- */
- public JSONVideoController(AvatarActivity activity) {
- super(RPCConst.CN_VIDEO);
- mActivity = activity;
- }
+ /**
+ * Constructor
+ *
+ * @param activity : the application main activity
+ */
+ public JSONVideoController(AvatarActivity activity) {
+ super(RPCConst.CN_VIDEO);
+ mActivity = activity;
+ }
- /**
- * Send notification to web UI with video progress bar position
- *
- * @param position
- * : video progress bar position
- */
- public void sendPositionNotification(int position) {
- String method = RPCConst.CN_VIDEO + "."
- + EVideoMethods.positionChanged.toString();
- mJSONParser.putEmptyJSONObject();
- mJSONParser.putIntValue(RPCConst.TAG_VIDEO_CURRENT_POSITION, position);
- this.sendNotification(method, mJSONParser.getJSONObject());
- }
+ /**
+ * Send notification to web UI with video progress bar position
+ *
+ * @param position : video progress bar position
+ */
+ public void sendPositionNotification(int position) {
+ String method = RPCConst.CN_VIDEO + "."
+ + EVideoMethods.positionChanged.toString();
+ mJSONParser.putEmptyJSONObject();
+ mJSONParser.putIntValue(RPCConst.TAG_VIDEO_CURRENT_POSITION, position);
+ this.sendNotification(method, mJSONParser.getJSONObject());
+ }
- /**
- * Set started video duration
- *
- * @param value
- * : video duration
- */
- public void setVideoDuration(int value) {
- mVideoDuration = value;
- }
+ /**
+ * Set started video duration
+ *
+ * @param value : video duration
+ */
+ public void setVideoDuration(int value) {
+ mVideoDuration = value;
+ }
- // ===================================================================
- // private section
- // ===================================================================
- /**
- * To show debug messages from current class
- */
- private final boolean DEBUG = true;
- private final String TAG_NAME = JSONVideoController.class.getSimpleName();
- private AvatarActivity mActivity;
- /**
- * Video file name in expansion file
- */
- private String mVideoName;
- private int mVideoDuration = 0;
- private boolean mVideoIsStarted = false; // to prevent double start of video
+ // ===================================================================
+ // private section
+ // ===================================================================
+ /**
+ * To show debug messages from current class
+ */
+ private final boolean DEBUG = true;
+ private final String TAG_NAME = JSONVideoController.class.getSimpleName();
+ private AvatarActivity mActivity;
+ /**
+ * Video file name in expansion file
+ */
+ private String mVideoName;
+ private int mVideoDuration = 0;
+ private boolean mVideoIsStarted = false; // to prevent double start of video
- @Override
- protected void processRequest(String request) {
- logMsg("Process request");
- String result = processNotification(request);
- if (result != null) {
- mJSONParser.putJSONObject(request);
- sendResponse(mJSONParser.getId(), result);
- }
- }
+ @Override
+ protected void processRequest(String request) {
+ logMsg("Process request");
+ String result = processNotification(request);
+ if (result != null) {
+ mJSONParser.putJSONObject(request);
+ sendResponse(mJSONParser.getId(), result);
+ }
+ }
- @Override
- protected String processNotification(String notification) {
- logMsg("Process notification : " + notification);
- mJSONParser.putJSONObject(notification);
- String method = mJSONParser.getMethod();
- method = method.substring(method.indexOf('.') + 1, method.length());
- String out = null;
- switch (EVideoMethods.valueOf(method)) {
- case start:
- mJSONParser.putJSONObject(mJSONParser.getParams());
- mVideoName = mJSONParser
- .getStringParam(RPCConst.TAG_VIDEO_FILE_NAME);
- double scale = mJSONParser.getDoubleParam(RPCConst.TAG_SCALE);
- mJSONParser.putJSONObject(mJSONParser
- .getJSONObjectParam(RPCConst.TAG_VIDEO_POSITION));
- int left = mJSONParser.getIntParam(RPCConst.TAG_VIDEO_POSITION_X);
- int top = mJSONParser.getIntParam(RPCConst.TAG_VIDEO_POSITION_Y);
- out = start(scale, left, top);
- break;
- case stop:
- out = stop();
- break;
- case pause:
- out = pause();
- break;
- case resume:
- out = resume();
- break;
- case setPositionPaused:
- mJSONParser.putJSONObject(mJSONParser.getParams());
- double pos = mJSONParser
- .getDoubleParam(RPCConst.TAG_VIDEO_POSITION);
- logMsg("POSITION = " + String.valueOf(pos));
- out = setPositionPaused(pos);
- break;
- case setPosition:
- mJSONParser.putJSONObject(mJSONParser.getParams());
- pos = mJSONParser.getDoubleParam(RPCConst.TAG_VIDEO_POSITION);
- logMsg("POSITION = " + String.valueOf(pos));
- out = setPosition(pos);
- break;
- case getPosition:
- out = getPosition();
- break;
- case stateChanged:
- out = stateChanged();
- break;
- case positionChanged:
- out = positionChanged();
- break;
- case setDragState:
- mJSONParser.putJSONObject(mJSONParser.getParams());
- boolean state = mJSONParser
- .getBooleanParam(RPCConst.TAG_VIDEO_DRAG_STATE);
- out = setDragState(state);
- break;
- default:
- mJSONParser.putEmptyJSONRPCObject();
- mJSONParser.putStringValue(RPCConst.TAG_ERROR,
- "VideoController does not support function : " + method);
- out = mJSONParser.getJSONObject();
- break;
- }
- return out;
+ @Override
+ protected String processNotification(String notification) {
+ logMsg("Process notification : " + notification);
+ mJSONParser.putJSONObject(notification);
+ String method = mJSONParser.getMethod();
+ method = method.substring(method.indexOf('.') + 1, method.length());
+ String out = null;
+ switch (EVideoMethods.valueOf(method)) {
+ case start:
+ mJSONParser.putJSONObject(mJSONParser.getParams());
+ mVideoName = mJSONParser.getStringParam(RPCConst.TAG_VIDEO_FILE_NAME);
+ double scale = mJSONParser.getDoubleParam(RPCConst.TAG_SCALE);
+ mJSONParser.putJSONObject(mJSONParser.getJSONObjectParam(RPCConst.TAG_VIDEO_POSITION));
+ int left = mJSONParser.getIntParam(RPCConst.TAG_VIDEO_POSITION_X);
+ int top = mJSONParser.getIntParam(RPCConst.TAG_VIDEO_POSITION_Y);
+ out = start(scale, left, top);
+ break;
+ case stop:
+ out = stop();
+ break;
+ case pause:
+ out = pause();
+ break;
+ case resume:
+ out = resume();
+ break;
+ case setPositionPaused:
+ mJSONParser.putJSONObject(mJSONParser.getParams());
+ double pos = mJSONParser
+ .getDoubleParam(RPCConst.TAG_VIDEO_POSITION);
+ logMsg("POSITION = " + String.valueOf(pos));
+ out = setPositionPaused(pos);
+ break;
+ case setPosition:
+ mJSONParser.putJSONObject(mJSONParser.getParams());
+ pos = mJSONParser.getDoubleParam(RPCConst.TAG_VIDEO_POSITION);
+ logMsg("POSITION = " + String.valueOf(pos));
+ out = setPosition(pos);
+ break;
+ case getPosition:
+ out = getPosition();
+ break;
+ case stateChanged:
+ out = stateChanged();
+ break;
+ case positionChanged:
+ out = positionChanged();
+ break;
+ case setDragState:
+ mJSONParser.putJSONObject(mJSONParser.getParams());
+ boolean state = mJSONParser
+ .getBooleanParam(RPCConst.TAG_VIDEO_DRAG_STATE);
+ out = setDragState(state);
+ break;
+ default:
+ mJSONParser.putEmptyJSONRPCObject();
+ mJSONParser.putStringValue(RPCConst.TAG_ERROR,
+ "VideoController does not support function : " + method);
+ out = mJSONParser.getJSONObject();
+ break;
+ }
+ return out;
- }
+ }
- @Override
- protected void processResponse(String response) {
- logMsg("Process response");
- if (!processRegistrationResponse(response)) {
- mJSONParser.putJSONObject(response);
- mRequestResponse = mJSONParser.getResult();
- }
- }
+ @Override
+ protected void processResponse(String response) {
+ logMsg("Process response");
+ if (!processRegistrationResponse(response)) {
+ mJSONParser.putJSONObject(response);
+ mRequestResponse = mJSONParser.getResult();
+ }
+ }
- /**
- * Subscription on properties
- */
- protected void subscribeToProperties() {
- subscribeTo("VideoPlayerClient.setDragState");
- }
+ /**
+ * Subscription on properties
+ */
+ protected void subscribeToProperties() {
+ subscribeTo("VideoPlayerClient.setDragState");
+ }
- /**
- * Start a video with parameters from web UI
- *
- * @param scale
- * : video scale
- * @param leftOffset
- * : left video offset
- * @param topOffset
- * : top video offset
- * @return result JSON object with video duration or error JSON object
- */
- private String start(double scale, int leftOffset, int topOffset) {
- // check if expansion files are available
- SharedPreferences prefs = mActivity.getSharedPreferences(
- Const.SHPREF_DOWNLOADER_PREFS, 0);
- boolean expFielsAreValid = prefs.getBoolean(
- Const.SHPREF_MAIN_EXPFILE_VALID, false)
- && prefs.getBoolean(Const.SHPREF_PATCH_EXPFILE_VALID, false);
+ /**
+ * Start a video with parameters from web UI
+ *
+ * @param scale : video scale
+ * @param leftOffset : left video offset
+ * @param topOffset : top video offset
+ * @return result JSON object with video duration or error JSON object
+ */
+ private String start(double scale, int leftOffset, int topOffset) {
+ // check if expansion files are available
+ SharedPreferences prefs = mActivity.getSharedPreferences(Const.SHPREF_DOWNLOADER_PREFS, 0);
+ boolean expFielsAreValid = prefs.getBoolean(Const.SHPREF_MAIN_EXPFILE_VALID, false)
+ && prefs.getBoolean(Const.SHPREF_PATCH_EXPFILE_VALID, false);
- // additionally check if it is a welcome video
- if (expFielsAreValid
- || mVideoName.toLowerCase().compareTo(
- Const.WELCOME_VIDEO_FILE_NAME) == 0) {
- if (!mVideoIsStarted) {
- mVideoIsStarted = true;
- logMsg("Play video " + mVideoName);
- Object obj[] = { mVideoName, scale, leftOffset, topOffset };
- Utils.sendMessageToHandler(Const.VIDEO_START, obj,
- mActivity.getMainHandler());
- }
- // wait for initializing video file and getting its duration
- while (mVideoDuration == 0) {
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
+ // additionally check if it is a welcome video
+ if (expFielsAreValid ||
+ mVideoName.toLowerCase().compareTo(Const.WELCOME_VIDEO_FILE_NAME) == 0) {
+ if (!mVideoIsStarted) {
+ mVideoIsStarted = true;
+ logMsg("Play video " + mVideoName);
+ Object obj[] = {mVideoName, scale, leftOffset, topOffset};
+ Utils.sendMessageToHandler(Const.VIDEO_START, obj, mActivity.getMainHandler());
+ }
+ // wait for initializing video file and getting its duration
+ while (mVideoDuration == 0) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
- if (mVideoDuration >= 0) {
- mJSONParser.putEmptyJSONObject();
- mJSONParser.putIntValue(RPCConst._TAG_VIDEO_TOTAL_DURATION,
- mVideoDuration);
- return mJSONParser.getJSONObject();
- }
- }
- return findVideoPlayError();
- }
+ if (mVideoDuration >= 0) {
+ mJSONParser.putEmptyJSONObject();
+ mJSONParser.putIntValue(RPCConst._TAG_VIDEO_TOTAL_DURATION,
+ mVideoDuration);
+ return mJSONParser.getJSONObject();
+ }
+ }
+ return findVideoPlayError();
+ }
- /**
- * Finds out what is wrong with video playing
- *
- * @return error JSON object
- */
- private String findVideoPlayError() {
- mJSONParser.putEmptyJSONObject();
- //put error value as an indicator for parser
- mJSONParser.putStringValue(RPCConst.TAG_ERROR, "");
- // get redownload count
- SharedPreferences prefs = mActivity.getSharedPreferences(
- Const.SHPREF_DOWNLOADER_PREFS, 0);
- int redownload_count = prefs.getInt(Const.SHPREF_REDOWNLOAD_COUNTER, 0);
+ /**
+ * Finds out what is wrong with video playing
+ *
+ * @return error JSON object
+ */
+ private String findVideoPlayError() {
+ mJSONParser.putEmptyJSONObject();
+ //put error value as an indicator for parser
+ mJSONParser.putStringValue(RPCConst.TAG_ERROR, "");
+ // get redownload count
+ SharedPreferences prefs = mActivity.getSharedPreferences(
+ Const.SHPREF_DOWNLOADER_PREFS, 0);
+ int redownload_count = prefs.getInt(Const.SHPREF_REDOWNLOAD_COUNTER, 0);
- // no network connection
- if (!NetUtils.isOnline(mActivity)) {
- mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
- MessageConst.NET_NET_NOT_AVAILABLE);
- mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
- Const.VC_NO_NETWORK_ERR_CODE);
- } // video files are still downloading
- else if (DownloaderClient.IS_PROCESSING_VIDEO) {
- mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
- MessageConst.VC_VIDEO_IS_BEING_PROCESSED_ERR);
- mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
- Const.VC_VIDEO_IS_BEING_DOWNLOADED_ERR_CODE);
- mJSONParser.putIntValue(RPCConst.TAG_ERROR_DATA,
- DownloaderClient.DOWNLOADED_PERSENS);
- DownloaderClient.FINISH_NOTIFY = true;
- }// no space on SD card
- else if (DownloaderClient.SDCARD_IS_FULL) {
- mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
- MessageConst.VC_NO_SPACE_ERR);
- mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
- Const.VC_NO_SPACE_ERR_CODE);
- }// video downloading count is exceeded
- else if (redownload_count < Const.DOWNLOADER_LAUNCH_MAX_NUMBER) {
- mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
- MessageConst.VC_VIDEO_IS_CORRUPTED_ERR);
- mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
- Const.VC_VIDEO_IS_CORRUPTED_ERR_CODE);
- } // video is unavailable due to file corruption
- else {
- mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
- MessageConst.VC_VIDEO_IS_UNAVAILABLE_ERR);
- mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
- Const.VC_VIDEO_IS_UNAVAILABLE_ERR_CODE);
- }
- return mJSONParser.getJSONObject();
- }
+ // no network connection
+ if (!NetUtils.isOnline(mActivity)) {
+ mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
+ MessageConst.NET_NET_NOT_AVAILABLE);
+ mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
+ Const.VC_NO_NETWORK_ERR_CODE);
+ } // video files are still downloading
+ else if (DownloaderClient.IS_PROCESSING_VIDEO) {
+ mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
+ MessageConst.VC_VIDEO_IS_BEING_PROCESSED_ERR);
+ mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
+ Const.VC_VIDEO_IS_BEING_DOWNLOADED_ERR_CODE);
+ mJSONParser.putIntValue(RPCConst.TAG_ERROR_DATA,
+ DownloaderClient.DOWNLOADED_PERSENS);
+ DownloaderClient.FINISH_NOTIFY = true;
+ }// no space on SD card
+ else if (DownloaderClient.SDCARD_IS_FULL) {
+ mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
+ MessageConst.VC_NO_SPACE_ERR);
+ mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
+ Const.VC_NO_SPACE_ERR_CODE);
+ }// video downloading count is exceeded
+ else if (redownload_count < Const.DOWNLOADER_LAUNCH_MAX_NUMBER) {
+ mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
+ MessageConst.VC_VIDEO_IS_CORRUPTED_ERR);
+ mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
+ Const.VC_VIDEO_IS_CORRUPTED_ERR_CODE);
+ } // video is unavailable due to file corruption
+ else {
+ mJSONParser.putStringValue(RPCConst.TAG_ERROR_MESSAGE,
+ MessageConst.VC_VIDEO_IS_UNAVAILABLE_ERR);
+ mJSONParser.putIntValue(RPCConst.TAG_ERROR_CODE,
+ Const.VC_VIDEO_IS_UNAVAILABLE_ERR_CODE);
+ }
+ return mJSONParser.getJSONObject();
+ }
- /**
- * stop video playing
- *
- * @return null, because it is a notification
- */
- private String stop() {
- logMsg("VideoStop");
- mVideoIsStarted = false;
- Utils.sendMessageToHandler(Const.VIDEO_STOP, null,
- mActivity.getMainHandler());
- mVideoDuration = 0;
- return null;
- }
+ /**
+ * stop video playing
+ *
+ * @return null, because it is a notification
+ */
+ private String stop() {
+ logMsg("VideoStop");
+ mVideoIsStarted = false;
+ Utils.sendMessageToHandler(Const.VIDEO_STOP, null,
+ mActivity.getMainHandler());
+ mVideoDuration = 0;
+ return null;
+ }
- /**
- * pause video playing
- *
- * @return null, because it is a notification
- */
- private String pause() {
- logMsg("VideoPause");
- Utils.sendMessageToHandler(Const.VIDEO_PAUSE, null,
- mActivity.getMainHandler());
- return null;
- }
+ /**
+ * pause video playing
+ *
+ * @return null, because it is a notification
+ */
+ private String pause() {
+ logMsg("VideoPause");
+ Utils.sendMessageToHandler(Const.VIDEO_PAUSE, null,
+ mActivity.getMainHandler());
+ return null;
+ }
- /**
- * resume video playing
- *
- * @return null, because it is a notification
- */
- private String resume() {
- logMsg("VideoPlay");
- Utils.sendMessageToHandler(Const.VIDEO_PLAY, null,
- mActivity.getMainHandler());
- return null;
- }
+ /**
+ * resume video playing
+ *
+ * @return null, because it is a notification
+ */
+ private String resume() {
+ logMsg("VideoPlay");
+ Utils.sendMessageToHandler(Const.VIDEO_PLAY, null,
+ mActivity.getMainHandler());
+ return null;
+ }
- /**
- * Set a new position of video while it is paused
- *
- * @param position
- * : new position
- * @return null, because it is a notification
- */
- private String setPositionPaused(double position) {
- logMsg("VideoSetPositionPaused:" + position + " convert to=" + position);
- Utils.sendMessageToHandler(Const.VIDEO_SET_POSITION_PAUSED, position,
- mActivity.getMainHandler());
- return null;
- }
+ /**
+ * Set a new position of video while it is paused
+ *
+ * @param position : new position
+ * @return null, because it is a notification
+ */
+ private String setPositionPaused(double position) {
+ logMsg("VideoSetPositionPaused:" + position + " convert to=" + position);
+ Utils.sendMessageToHandler(Const.VIDEO_SET_POSITION_PAUSED, position,
+ mActivity.getMainHandler());
+ return null;
+ }
- /**
- * Set a new position of video while it is playing
- *
- * @param position
- * : new position
- * @return null, because it is a notification
- */
- private String setPosition(double position) {
- logMsg("VideoSetPosition:" + position + " covert to=" + position);
- Utils.sendMessageToHandler(Const.VIDEO_SET_POSITION, position,
- mActivity.getMainHandler());
- return null;
- }
+ /**
+ * Set a new position of video while it is playing
+ *
+ * @param position : new position
+ * @return null, because it is a notification
+ */
+ private String setPosition(double position) {
+ logMsg("VideoSetPosition:" + position + " covert to=" + position);
+ Utils.sendMessageToHandler(Const.VIDEO_SET_POSITION, position,
+ mActivity.getMainHandler());
+ return null;
+ }
- /**
- * Get current position in seconds
- *
- * @return current position in seconds
- */
- private String getPosition() {
- double out = mActivity.videoGetPosition();
- logMsg("VideoGetPosition Position=" + out);
- return String.valueOf(out);
- }
+ /**
+ * Get current position in seconds
+ *
+ * @return current position in seconds
+ */
+ private String getPosition() {
+ double out = mActivity.videoGetPosition();
+ logMsg("VideoGetPosition Position=" + out);
+ return String.valueOf(out);
+ }
- /**
- * Stub for future
- *
- * @return null
- */
- private String stateChanged() {
- return null;
- }
+ /**
+ * Stub for future
+ *
+ * @return null
+ */
+ private String stateChanged() {
+ return null;
+ }
- /**
- * Stub for future
- *
- * @return null
- */
- private String positionChanged() {
- return null;
- }
+ /**
+ * Stub for future
+ *
+ * @return null
+ */
+ private String positionChanged() {
+ return null;
+ }
- /**
- * Disable and enable dragging in the application. It should be available
- * only during video playing
- *
- * @param activate
- * : activates dragging
- * @return null, because it is a notification
- */
- private String setDragState(boolean activate) {
- if (activate) {
- // allow dragging only if dragging video
- WebViewUtils.setOnTouchListener(mActivity,
- WebViewUtils.NONBLOCKING_ACTION_MOVE_MODE);
- } else {
- // disable dragging when stop scrolling video
- WebViewUtils.setOnTouchListener(mActivity,
- WebViewUtils.BLOCKING_ACTION_MOVE_MODE);
- }
- return null;
- }
+ /**
+ * Disable and enable dragging in the application. It should be available
+ * only during video playing
+ *
+ * @param activate : activates dragging
+ * @return null, because it is a notification
+ */
+ private String setDragState(boolean activate) {
+ if (activate) {
+ // allow dragging only if dragging video
+ WebViewUtils.setOnTouchListener(mActivity,
+ WebViewUtils.NONBLOCKING_ACTION_MOVE_MODE);
+ } else {
+ // disable dragging when stop scrolling video
+ WebViewUtils.setOnTouchListener(mActivity,
+ WebViewUtils.BLOCKING_ACTION_MOVE_MODE);
+ }
+ return null;
+ }
- /**
- * Check if file exists on SD card.
- *
- * @param fileName
- * : file name
- * @return true if file exists and false otherwise.
- */
- public boolean isFileExist(String fileName) {
- if (fileName == null || "".equals(fileName.trim())) {
- return false;
- }
- try {
+ /**
+ * Check if file exists on SD card.
+ *
+ * @param fileName : file name
+ * @return true if file exists and false otherwise.
+ */
+ public boolean isFileExist(String fileName) {
+ if (fileName == null || "".equals(fileName.trim())) {
+ return false;
+ }
+ try {
- File file = ExtStorageUtils.getFileOnSDCard(mActivity,
- fileName.toLowerCase());
- return file.exists();
- } catch (SDCardException e) {
- e.printStackTrace();
- return false;
- }
- }
+ File file = ExtStorageUtils.getFileOnSDCard(mActivity,
+ fileName.toLowerCase());
+ return file.exists();
+ } catch (SDCardException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
- private void logMsg(String msg) {
- if (DEBUG && Const.DEBUG) {
- Log.i(TAG_NAME, msg);
- }
- }
+ private void logMsg(String msg) {
+ if (DEBUG && Const.DEBUG) {
+ Log.i(TAG_NAME, msg);
+ }
+ }
}
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/jssupport/JavaScriptFacade.java b/native/android/avatar/src/main/java/com/ford/avarsdl/jssupport/JavaScriptFacade.java
index f0bb511a91..3480733826 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/jssupport/JavaScriptFacade.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/jssupport/JavaScriptFacade.java
@@ -4,7 +4,7 @@ import java.util.HashMap;
import android.util.Log;
-import com.ford.avarsdl.activity.AvatarActivity;
+import com.ford.avarsdl.views.AvatarActivity;
import com.ford.avarsdl.jsoncontroller.JSONAVAController;
import com.ford.avarsdl.util.Const;
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/media/AvatarOnPreparedListener.java b/native/android/avatar/src/main/java/com/ford/avarsdl/media/AvatarOnPreparedListener.java
index 76984fcbeb..a335bde2c0 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/media/AvatarOnPreparedListener.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/media/AvatarOnPreparedListener.java
@@ -4,7 +4,7 @@ import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.util.Log;
-import com.ford.avarsdl.activity.AvatarActivity;
+import com.ford.avarsdl.views.AvatarActivity;
import com.ford.avarsdl.util.Const;
public class AvatarOnPreparedListener implements OnPreparedListener {
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/requests/CancelAccessCommand.java b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/CancelAccessCommand.java
new file mode 100644
index 0000000000..eb92b6fcc9
--- /dev/null
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/CancelAccessCommand.java
@@ -0,0 +1,32 @@
+package com.ford.avarsdl.requests;
+
+import com.ford.avarsdl.service.SDLService;
+import com.ford.avarsdl.util.Logger;
+import com.ford.syncV4.proxy.SyncProxyALM;
+import com.ford.syncV4.proxy.rpc.CancelAccess;
+
+import org.json.JSONObject;
+
+/**
+ * Created with Android Studio.
+ * Author: Chernyshov Yuriy - Mobile Development
+ * Date: 11/26/13
+ * Time: 11:41 AM
+ */
+public class CancelAccessCommand implements RequestCommand {
+
+ @Override
+ public void execute(int id, JSONObject jsonParameters) {
+ SyncProxyALM proxy = SDLService.getProxyInstance();
+ if (proxy != null) {
+ CancelAccess msg = new CancelAccess();
+ msg.setCorrelationID(id);
+ try {
+ //Logger.d(getClass().getSimpleName() + " Sending Cancel Access: " + jsonParameters);
+ proxy.sendRPCRequest(msg);
+ } catch (Throwable e) {
+ Logger.e(getClass().getSimpleName() + " can't send message", e);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/requests/GrantAccessCommand.java b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/GrantAccessCommand.java
index dd335f3cb4..25f01a5998 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/requests/GrantAccessCommand.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/GrantAccessCommand.java
@@ -22,6 +22,7 @@ public class GrantAccessCommand implements RequestCommand {
GrantAccess msg = new GrantAccess();
msg.setCorrelationID(id);
try {
+ //Logger.d(getClass().getSimpleName() + " Sending Grant Access: " + jsonParameters);
proxy.sendRPCRequest(msg);
} catch (Throwable e) {
Logger.e(getClass().getSimpleName() + " can't send message", e);
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneDownCommand.java b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneDownCommand.java
new file mode 100644
index 0000000000..9fbdc1f3fc
--- /dev/null
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneDownCommand.java
@@ -0,0 +1,35 @@
+package com.ford.avarsdl.requests;
+
+import com.ford.avarsdl.service.SDLService;
+import com.ford.avarsdl.util.Logger;
+import com.ford.syncV4.exception.SyncException;
+import com.ford.syncV4.proxy.SyncProxyALM;
+import com.ford.syncV4.proxy.rpc.TuneDown;
+
+import org.json.JSONObject;
+
+/**
+ * Created with Android Studio.
+ * Author: Chernyshov Yuriy - Mobile Development
+ * Date: 11/28/13
+ * Time: 12:26 PM
+ */
+public class TuneDownCommand implements RequestCommand {
+
+ @Override
+ public void execute(int id, JSONObject jsonParameters) {
+ SyncProxyALM proxy = SDLService.getProxyInstance();
+ if (proxy != null) {
+ TuneDown msg = new TuneDown();
+ msg.setCorrelationID(id);
+
+ try {
+ proxy.sendRPCRequest(msg);
+ } catch (SyncException e) {
+ Logger.e(getClass().getSimpleName() + " can't send message", e);
+ }
+ } else {
+ Logger.e(getClass().getSimpleName() + " proxy is NULL");
+ }
+ }
+} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneRadioCommand.java b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneRadioCommand.java
index 5dd6b0d6d2..a9ea9f8706 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneRadioCommand.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneRadioCommand.java
@@ -1,6 +1,5 @@
package com.ford.avarsdl.requests;
-import com.ford.avarsdl.business.MainApp;
import com.ford.avarsdl.service.SDLService;
import com.ford.avarsdl.util.Logger;
import com.ford.syncV4.exception.SyncException;
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneUpCommand.java b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneUpCommand.java
new file mode 100644
index 0000000000..aaa71c2d72
--- /dev/null
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/requests/TuneUpCommand.java
@@ -0,0 +1,36 @@
+package com.ford.avarsdl.requests;
+
+import com.ford.avarsdl.service.SDLService;
+import com.ford.avarsdl.util.Logger;
+import com.ford.syncV4.exception.SyncException;
+import com.ford.syncV4.proxy.SyncProxyALM;
+import com.ford.syncV4.proxy.rpc.TuneUp;
+
+import org.json.JSONObject;
+
+/**
+ * Created with Android Studio.
+ * Author: Chernyshov Yuriy - Mobile Development
+ * Date: 11/28/13
+ * Time: 12:24 PM
+ */
+public class TuneUpCommand implements RequestCommand {
+
+ @Override
+ public void execute(int id, JSONObject jsonParameters) {
+ SyncProxyALM proxy = SDLService.getProxyInstance();
+ if (proxy != null) {
+ TuneUp msg = new TuneUp();
+ msg.setCorrelationID(id);
+
+ try {
+ //Logger.d(getClass().getSimpleName() + "Sending Tune Up: " + jsonParameters);
+ proxy.sendRPCRequest(msg);
+ } catch (SyncException e) {
+ Logger.e(getClass().getSimpleName() + " can't send message", e);
+ }
+ } else {
+ Logger.e(getClass().getSimpleName() + " proxy is NULL");
+ }
+ }
+} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/responses/CancelAccessResponse.java b/native/android/avatar/src/main/java/com/ford/avarsdl/responses/CancelAccessResponse.java
new file mode 100644
index 0000000000..391c755528
--- /dev/null
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/responses/CancelAccessResponse.java
@@ -0,0 +1,24 @@
+package com.ford.avarsdl.responses;
+
+import com.ford.avarsdl.jsoncontroller.JSONController;
+import com.ford.avarsdl.util.Logger;
+import com.ford.avarsdl.util.RPCConst;
+
+/**
+ * Created with Android Studio.
+ * Author: Chernyshov Yuriy - Mobile Development
+ * Date: 11/29/13
+ * Time: 2:34 PM
+ */
+public class CancelAccessResponse extends JSONController implements ResponseCommand {
+
+ public CancelAccessResponse() {
+ super(RPCConst.CN_REVSDL);
+ }
+
+ @Override
+ public void execute(int id, String result) {
+ //Logger.d(getClass().getSimpleName() + " id: " + id + ", result: " + result);
+ sendResponse(id, result);
+ }
+} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/service/SDLService.java b/native/android/avatar/src/main/java/com/ford/avarsdl/service/SDLService.java
index c78178b936..eb17f98744 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/service/SDLService.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/service/SDLService.java
@@ -1,15 +1,16 @@
package com.ford.avarsdl.service;
import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
+import android.util.Log;
-import com.ford.avarsdl.activity.SafeToast;
+import com.ford.avarsdl.views.SafeToast;
import com.ford.avarsdl.notifications.NotificationCommand;
import com.ford.avarsdl.notifications.NotificationCommandImpl;
import com.ford.avarsdl.responses.ResponseCommand;
-import com.ford.avarsdl.util.APIObjectsSimulator;
import com.ford.avarsdl.util.Const;
import com.ford.avarsdl.util.Logger;
import com.ford.avarsdl.util.RPCConst;
@@ -22,6 +23,7 @@ import com.ford.syncV4.proxy.rpc.AddCommandResponse;
import com.ford.syncV4.proxy.rpc.AddSubMenuResponse;
import com.ford.syncV4.proxy.rpc.AlertManeuverResponse;
import com.ford.syncV4.proxy.rpc.AlertResponse;
+import com.ford.syncV4.proxy.rpc.CancelAccessResponse;
import com.ford.syncV4.proxy.rpc.ChangeRegistrationResponse;
import com.ford.syncV4.proxy.rpc.CreateInteractionChoiceSetResponse;
import com.ford.syncV4.proxy.rpc.DeleteCommandResponse;
@@ -46,6 +48,7 @@ import com.ford.syncV4.proxy.rpc.OnHMIStatus;
import com.ford.syncV4.proxy.rpc.OnKeyboardInput;
import com.ford.syncV4.proxy.rpc.OnLanguageChange;
import com.ford.syncV4.proxy.rpc.OnPermissionsChange;
+import com.ford.syncV4.proxy.rpc.OnPresetsChanged;
import com.ford.syncV4.proxy.rpc.OnRadioDetails;
import com.ford.syncV4.proxy.rpc.OnSyncPData;
import com.ford.syncV4.proxy.rpc.OnTBTClientState;
@@ -107,10 +110,11 @@ public class SDLService extends Service implements IProxyListenerALM {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- Logger.d("onStartCommand " + intent + ", " + flags + ", " + startId);
+ Logger.d(getClass().getSimpleName() + " onStartCommand " + intent + ", " + flags + ", " +
+ startId);
initializeCommandsHashTable();
- startProxy();
+ startProxyIfNetworkConnected();
return START_STICKY;
}
@@ -124,17 +128,47 @@ public class SDLService extends Service implements IProxyListenerALM {
@Override
public IBinder onBind(Intent intent) {
- Logger.d("onBind unsupported");
- // binding is not supported
+ Logger.d(getClass().getSimpleName() + " onBind, hash: " + hashCode());
return mBinder;
}
+ private void startProxyIfNetworkConnected() {
+ final SharedPreferences prefs = getSharedPreferences(Const.PREFS_NAME,
+ MODE_PRIVATE);
+ final int transportType = prefs.getInt(
+ Const.PREFS_KEY_TRANSPORT_TYPE,
+ Const.PREFS_DEFAULT_TRANSPORT_TYPE);
+
+ if (transportType == Const.KEY_BLUETOOTH) {
+ Logger.d(getClass().getSimpleName() + " ProxyService. onStartCommand(). Transport = Bluetooth.");
+ BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ if (bluetoothAdapter != null) {
+ if (bluetoothAdapter.isEnabled()) {
+ startProxy();
+ }
+ }
+ } else {
+ //TODO: This code is commented out for simulator purposes
+ /*
+ Log.d(TAG, "ProxyService. onStartCommand(). Transport = WiFi.");
+ if (hasWiFiConnection() == true) {
+ Log.d(TAG, "ProxyService. onStartCommand(). WiFi enabled.");
+ startProxy();
+ } else {
+ Log.w(TAG,
+ "ProxyService. onStartCommand(). WiFi is not enabled.");
+ }
+ */
+ startProxy();
+ }
+ }
+
private void startProxy() {
- Logger.d("starting proxy");
+ Logger.d(getClass().getSimpleName() + " Starting proxy ...");
- SharedPreferences prefs = getSharedPreferences(Const.PREFS_NAME, 0);
- String ipAddressString = prefs.getString(Const.PREFS_KEY_IPADDR, Const.PREFS_DEFAULT_IPADDR);
- int tcpPortInt = prefs.getInt(Const.PREFS_KEY_TCPPORT, Const.PREFS_DEFAULT_TCPPORT);
+ SharedPreferences sharedPreferences = getSharedPreferences(Const.PREFS_NAME, 0);
+ String ipAddressString = sharedPreferences.getString(Const.PREFS_KEY_IPADDR, Const.PREFS_DEFAULT_IPADDR);
+ int tcpPortInt = sharedPreferences.getInt(Const.PREFS_KEY_TCPPORT, Const.PREFS_DEFAULT_TCPPORT);
SyncMsgVersion syncMsgVersion = new SyncMsgVersion();
syncMsgVersion.setMajorVersion(2);
@@ -143,11 +177,23 @@ public class SDLService extends Service implements IProxyListenerALM {
Vector<AppHMIType> appHMIType = new Vector<AppHMIType>();
appHMIType.add(AppHMIType.RADIO);
+ int transportType = sharedPreferences.getInt(
+ Const.PREFS_KEY_TRANSPORT_TYPE,
+ Const.PREFS_DEFAULT_TRANSPORT_TYPE);
+
try {
- mSyncProxy = new SyncProxyALM(this, null, APPNAME, null, null, true,
- appHMIType, syncMsgVersion, Language.EN_US, Language.EN_US, APPID,
- null, false, false, 2,
- new TCPTransportConfig(tcpPortInt, ipAddressString));
+ if (transportType == Const.KEY_BLUETOOTH) {
+ Logger.i(getClass().getSimpleName() + " Start Bluetooth Proxy");
+ mSyncProxy = new SyncProxyALM(this, null, APPNAME, null, null, true,
+ appHMIType, syncMsgVersion, Language.EN_US, Language.EN_US, APPID,
+ null, false, false, 2);
+ } else {
+ Logger.i(getClass().getSimpleName() + " Start WiFi Proxy");
+ mSyncProxy = new SyncProxyALM(this, null, APPNAME, null, null, true,
+ appHMIType, syncMsgVersion, Language.EN_US, Language.EN_US, APPID,
+ null, false, false, 2,
+ new TCPTransportConfig(tcpPortInt, ipAddressString));
+ }
} catch (SyncException e) {
Logger.e("Failed to start proxy", e);
if (mSyncProxy == null) {
@@ -443,9 +489,29 @@ public class SDLService extends Service implements IProxyListenerALM {
}
@Override
+ public void onCancelAccessResponse(CancelAccessResponse response) {
+ ResponseCommand command = new com.ford.avarsdl.responses.CancelAccessResponse();
+ try {
+ byte serializeMethod = 2;
+ command.execute(response.getCorrelationID(),
+ response.serializeJSON(serializeMethod).toString());
+ } catch (JSONException e) {
+ e.printStackTrace();
+ Logger.e(getClass().getSimpleName() + " onCancelAccessResponse " + e);
+ }
+ }
+
+ @Override
public void onOnControlChanged(OnControlChanged notification) {
- final String msg = "onControlChanged " + notification.getReason();
- SafeToast.showToastAnyThread(msg);
+ //SafeToast.showToastAnyThread("onControlChanged " + notification);
+ Logger.d(getClass().getSimpleName() + " onControlChanged " + notification);
+ NotificationCommand command = commandsHashTable.get(Names.OnControlChanged);
+ if (command != null) {
+ String method = RPCConst.CN_REVSDL + "." + Names.OnControlChanged;
+ command.execute(method, notification);
+ } else {
+ Logger.w(getClass().getSimpleName() + " NotificationCommand NULL");
+ }
}
@Override
@@ -474,6 +540,19 @@ public class SDLService extends Service implements IProxyListenerALM {
}
@Override
+ public void onOnPresetsChanged(OnPresetsChanged notification) {
+ //SafeToast.showToastAnyThread("OnPresetsChanged: " + notification);
+
+ NotificationCommand command = commandsHashTable.get(Names.OnPresetsChanged);
+ if (command != null) {
+ String method = RPCConst.CN_REVSDL + "." + Names.OnPresetsChanged;
+ command.execute(method, notification);
+ } else {
+ Logger.w(getClass().getSimpleName() + " NotificationCommand NULL");
+ }
+ }
+
+ @Override
public void onOnRadioDetails(OnRadioDetails notification) {
// TODO: Expand notification information here
final RadioStation radioStation = notification.getRadioStation();
@@ -518,7 +597,16 @@ public class SDLService extends Service implements IProxyListenerALM {
}
private void initializeCommandsHashTable() {
- NotificationCommand command = new NotificationCommandImpl();
- commandsHashTable.put(Names.OnRadioDetails, command);
+ // TODO: Probably in the future version there will be differences between notification
+ // objects, but up to now they contain general information structure
+
+ NotificationCommand onRadioDetailsNotification = new NotificationCommandImpl();
+ commandsHashTable.put(Names.OnRadioDetails, onRadioDetailsNotification);
+
+ NotificationCommand onControlChangedNotification = new NotificationCommandImpl();
+ commandsHashTable.put(Names.OnControlChanged, onControlChangedNotification);
+
+ NotificationCommand onPresetsChangedNotification = new NotificationCommandImpl();
+ commandsHashTable.put(Names.OnPresetsChanged, onPresetsChangedNotification);
}
} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/util/Const.java b/native/android/avatar/src/main/java/com/ford/avarsdl/util/Const.java
index df16906e45..a3385bf989 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/util/Const.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/util/Const.java
@@ -93,6 +93,12 @@ public class Const {
public static final String PREFS_KEY_IPADDR = "ipAddr";
public static final String PREFS_KEY_TCPPORT = "tcpPort";
+ public static final String PREFS_KEY_TRANSPORT_TYPE = "TransportType";
+ public static final String TCP = "WiFi";
+ public static final String BLUETOOTH = "Bluetooth";
+ public static final int KEY_TCP = 1;
+ public static final int KEY_BLUETOOTH = 2;
+ public static final int PREFS_DEFAULT_TRANSPORT_TYPE = KEY_TCP;
public static final String PREFS_DEFAULT_IPADDR = "10.10.0.1";
public static final Integer PREFS_DEFAULT_TCPPORT = 12345;
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/util/WebViewUtils.java b/native/android/avatar/src/main/java/com/ford/avarsdl/util/WebViewUtils.java
index 4b4b92ec8f..43b37ec050 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/util/WebViewUtils.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/util/WebViewUtils.java
@@ -16,7 +16,7 @@ import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
-import com.ford.avarsdl.activity.AvatarActivity;
+import com.ford.avarsdl.views.AvatarActivity;
import com.ford.avarsdl.jssupport.AvatarWebViewClient;
import com.ford.avarsdl.jssupport.JavaScriptFacade;
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/views/AppSetupDialog.java b/native/android/avatar/src/main/java/com/ford/avarsdl/views/AppSetupDialog.java
new file mode 100644
index 0000000000..c6ae3e66ec
--- /dev/null
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/views/AppSetupDialog.java
@@ -0,0 +1,106 @@
+package com.ford.avarsdl.views;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.RadioGroup;
+
+import com.ford.avarsdl.R;
+import com.ford.avarsdl.service.SDLService;
+import com.ford.avarsdl.util.Const;
+import com.ford.avarsdl.util.Logger;
+
+/**
+ * Created with Android Studio.
+ * Author: Chernyshov Yuriy - Mobile Development
+ * Date: 11/28/13
+ * Time: 4:11 PM
+ */
+public class AppSetupDialog extends DialogFragment {
+
+ private static final String TITLE_KEY = "dialog_title";
+
+ public static AppSetupDialog newInstance(int title) {
+ AppSetupDialog appSetupDialog = new AppSetupDialog();
+ Bundle bundle = new Bundle();
+ bundle.putInt(TITLE_KEY, title);
+ appSetupDialog.setArguments(bundle);
+ return appSetupDialog;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ int title = getArguments().getInt(TITLE_KEY);
+ View dialogView = getActivity().getLayoutInflater().inflate(R.layout.sdl_settings, null);
+ final EditText ipAddressText = (EditText) dialogView.findViewById(R.id.sdl_ipAddr);
+ final EditText tcpPortText = (EditText) dialogView.findViewById(R.id.sdl_tcpPort);
+ final RadioGroup transportGroup =
+ (RadioGroup) dialogView.findViewById(R.id.selectprotocol_radioGroupTransport);
+
+ ipAddressText.setEnabled(false);
+ tcpPortText.setEnabled(false);
+
+ transportGroup
+ .setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(RadioGroup group, int checkedId) {
+ boolean transportOptionsEnabled = checkedId == R.id.selectprotocol_radioWiFi;
+ ipAddressText.setEnabled(transportOptionsEnabled);
+ tcpPortText.setEnabled(transportOptionsEnabled);
+ }
+ });
+
+ final SharedPreferences prefs = getActivity().getSharedPreferences(Const.PREFS_NAME, 0);
+ String ipAddressString = prefs.getString(Const.PREFS_KEY_IPADDR, Const.PREFS_DEFAULT_IPADDR);
+ int tcpPortInt = prefs.getInt(Const.PREFS_KEY_TCPPORT, Const.PREFS_DEFAULT_TCPPORT);
+ int transportType = prefs.getInt(
+ Const.PREFS_KEY_TRANSPORT_TYPE,
+ Const.PREFS_DEFAULT_TRANSPORT_TYPE);
+
+ ipAddressText.setText(ipAddressString);
+ tcpPortText.setText(String.valueOf(tcpPortInt));
+
+ transportGroup.check(transportType == Const.KEY_TCP ? R.id.selectprotocol_radioWiFi :
+ R.id.selectprotocol_radioBT);
+
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(title)
+ .setCancelable(false)
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String ipAddressString = ipAddressText.getText().toString();
+ int tcpPortInt;
+ try {
+ tcpPortInt = Integer.parseInt(tcpPortText.getText().toString());
+ } catch (NumberFormatException e) {
+ Logger.i("Couldn't parse port number", e);
+ tcpPortInt = Const.PREFS_DEFAULT_TCPPORT;
+ }
+ int transportType = transportGroup.getCheckedRadioButtonId() ==
+ R.id.selectprotocol_radioWiFi ? Const.KEY_TCP :
+ Const.KEY_BLUETOOTH;
+
+ SharedPreferences.Editor prefsEditor =
+ getActivity().getSharedPreferences(Const.PREFS_NAME, 0).edit();
+ prefsEditor.putString(Const.PREFS_KEY_IPADDR, ipAddressString);
+ prefsEditor.putInt(Const.PREFS_KEY_TCPPORT, tcpPortInt);
+ prefsEditor.putInt(Const.PREFS_KEY_TRANSPORT_TYPE, transportType);
+ prefsEditor.commit();
+
+ Intent intent = new Intent(getActivity().getApplicationContext(), SDLService.class);
+ getActivity().startService(intent);
+ }
+ }
+ )
+ .setView(dialogView)
+ .create();
+ }
+} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/views/AvatarActivity.java b/native/android/avatar/src/main/java/com/ford/avarsdl/views/AvatarActivity.java
new file mode 100644
index 0000000000..19c6db1ef0
--- /dev/null
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/views/AvatarActivity.java
@@ -0,0 +1,1097 @@
+package com.ford.avarsdl.views;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import android.app.Activity;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.graphics.Rect;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.StrictMode;
+import android.preference.PreferenceManager;
+import android.util.DisplayMetrics;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.Window;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings.RenderPriority;
+import android.webkit.WebView;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.RelativeLayout.LayoutParams;
+
+import com.android.vending.expansion.zipfile.APKExpansionSupport;
+import com.android.vending.expansion.zipfile.ZipResourceFile;
+
+import com.ford.avarsdl.R;
+import com.ford.avarsdl.downloader.DownloaderClient;
+import com.ford.avarsdl.downloader.XAPKFile;
+import com.ford.avarsdl.exception.ExtensionFileException;
+import com.ford.avarsdl.exception.MediaPlayerException;
+import com.ford.avarsdl.jsoncontroller.JSONBackendController;
+import com.ford.avarsdl.jsoncontroller.JSONRateController;
+import com.ford.avarsdl.jsoncontroller.JSONRevSDLController;
+import com.ford.avarsdl.jsoncontroller.JSONVideoController;
+import com.ford.avarsdl.jsonserver.JSONServer;
+import com.ford.avarsdl.media.AvatarOnPreparedListener;
+import com.ford.avarsdl.rater.AppRater;
+import com.ford.avarsdl.service.ISDLServiceConnection;
+import com.ford.avarsdl.service.SDLService;
+import com.ford.avarsdl.service.SDLServiceBinder;
+import com.ford.avarsdl.service.SDLServiceConnectionProxy;
+import com.ford.avarsdl.util.ActivityUtils;
+import com.ford.avarsdl.util.Const;
+import com.ford.avarsdl.util.ExtStorageUtils;
+import com.ford.avarsdl.util.Logger;
+import com.ford.avarsdl.util.MessageConst;
+import com.ford.avarsdl.util.Utils;
+import com.ford.avarsdl.util.WebViewUtils;
+import com.ford.syncV4.proxy.interfaces.IProxyListenerALM;
+
+/**
+ * Title: AvatarActivity.java<br>
+ * Description: Main application activity, responsible for webview content load
+ * and video handling<br>
+ *
+ * @author vsaenko/Eugene Sagan
+ * @co-author Yuriy Chernyshov
+ */
+public class AvatarActivity extends Activity implements SurfaceHolder.Callback,
+ ISDLServiceConnection {
+
+ private final static String APP_SETUP_DIALOG_TAG = "AppSetupDialogTag";
+ private final SDLServiceConnectionProxy mSDLServiceConnectionProxy = new SDLServiceConnectionProxy(this);
+ private IProxyListenerALM mBoundSDLService;
+
+ // for monkey testing
+ // adb shell monkey -p com.ford.avarsdl -v 100
+
+ public static Boolean fullscreenPreferenceChanged = false;
+ public static Boolean vehiclePreferenceChanged = false;
+ public static Boolean navigationPreferenceChanged = false;
+
+ public static Boolean ratePreferenceEnabled;
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ Logger.i(getClass().getSimpleName() + " onStart ");
+
+ if (mBoundSDLService != null) {
+
+ } else {
+ bindSDLService(this, mSDLServiceConnectionProxy);
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Logger.i(getClass().getSimpleName() + " onCreate, hash:" + hashCode());
+
+ // FIXME: the old code with new SDK crashes with
+ // android.os.NetworkOnMainThreadException
+ // this hotfix is a bad idea. Don't try this at home!
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(policy);
+
+ if (isFirstStart()) {
+ Intent intent = new Intent(this, EulaActivity.class);
+ startActivityForResult(intent, Const.REQUESTCODE_EULA);
+ } else {
+ startAvatarActivity();
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == RESULT_OK && requestCode == Const.REQUESTCODE_EULA) {
+ startAvatarActivity();
+ resumeAvatarActivity();
+ } else {
+ finish();
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public void onBackPressed() {
+ // do something on back.
+ this.moveTaskToBack(true);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.optionsmenu, menu);
+ return true;
+ }
+
+ public void bindSDLService(Context context, SDLServiceConnectionProxy connectionProxy) {
+ Logger.i("BindStorageService(), connection proxy: " + connectionProxy);
+ context.bindService(new Intent(context, SDLService.class), connectionProxy, BIND_AUTO_CREATE);
+ }
+
+ public void unbindSDLService(Context context, SDLServiceConnectionProxy connectionProxy) {
+ if (!connectionProxy.isConnected()) {
+ Logger.v("ServiceConnection is not connected, ignoring unbindService: " + connectionProxy);
+ return;
+ }
+ try {
+ Logger.i("Unbind Service(), connection proxy: " + connectionProxy);
+ context.unbindService(connectionProxy);
+ } catch (IllegalArgumentException iae) {
+ // sometimes this exception is still thrown, in spite of isConnected() check above
+ // simply ignore this exception
+ Logger.w("Unbind IllegalArgumentException: " + iae);
+ } catch (Exception e) {
+ Logger.e("Error unbinding from connection: " + connectionProxy, e);
+ }
+ }
+
+
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final int itemId = item.getItemId();
+ switch (itemId) {
+ case R.id.mnuQuit:
+ exitApp();
+ break;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ private void exitApp() {
+ Logger.d("Exiting application");
+
+ finish();
+ // the delay should be long enough, so that UnregisterAppInterface and
+ // EndSession messages are sent
+ new Timer().schedule(new TimerTask() {
+ @Override
+ public void run() {
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+ }, 2000);
+ }
+
+ public boolean isFirstStart() {
+ // Commit according to REVSDL-116
+
+ /*SharedPreferences prefs = getSharedPreferences(Const.SHPREF_FIRST_LAUNCH, 0);
+ int previousCodeVersion = prefs.getInt(Const.SHPREF_PREVIOUS_CODE_VERSION, 0);
+ int currentCodeVersion = Utils.getAppVersionCode(this);
+ return previousCodeVersion < currentCodeVersion;*/
+
+ return false;
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ Logger.i("surface created");
+ playVideo(holder);
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ Logger.i("surface destroyed");
+ }
+
+ // =============================================================
+ // GETTERS
+ // =============================================================
+ public WebView getWebView() {
+ return mWebView;
+ }
+
+ public MediaPlayer getMediaPlayer() {
+ return mMediaPlayer;
+ }
+
+ // get value from application settings
+ public Boolean getFullscreenStatus() {
+ return mPreferences.getBoolean("FULLSCREEN", true);
+ }
+
+ // get value from application settings
+ public Boolean getMapsStatus() {
+ return mPreferences.getBoolean("MAPS", true);
+ }
+
+ // get value from application settings
+ public String getVehicleStatus() {
+ return mPreferences.getString("VEHICLES", "Ford");
+ }
+
+ // get value from application settings
+ public Boolean getRateStatus() {
+ return mPreferences.getBoolean("RATE", true);
+ }
+
+ // set value to application settings
+ public Boolean setMapsStatus(boolean value) {
+ SharedPreferences.Editor editor = mPreferences.edit();
+ editor.putBoolean("MAPS", value);
+ editor.commit();
+ return true;
+ }
+
+ // set value to application settings
+ public boolean setVehicleStatus(String value) {
+ SharedPreferences.Editor editor = mPreferences.edit();
+ editor.putString("VEHICLES", value);
+ editor.commit();
+ return true;
+ }
+
+ public double audioGetPosition() {
+ return mediaGetPosition();
+ }
+
+ public String getPathToDownloadedAudioFile(String fileName) {
+ final File file = new File(getExternalFilesDir(null), fileName + ".mp3");
+ return file.getAbsolutePath();
+ }
+
+ public Handler getMainHandler() {
+ return handler;
+ }
+
+ public int getVideoPausedPosition() {
+ return mVideoPauseTime;
+ }
+
+ public double videoGetPosition() {
+ return mediaGetPosition();
+ }
+
+ public boolean videoWasPaused() {
+ return mVideoWasPaused;
+ }
+
+ public boolean getVideoPlayed() {
+ return mVideoPlayed;
+ }
+
+ public JSONVideoController getVideoController() {
+ return mVideoController;
+ }
+
+ public boolean getVideoPrepared() {
+ return mVideoPrepared;
+ }
+
+ public JSONBackendController getBEController() {
+ return mBEController;
+ }
+
+ // setters
+
+ public void setVideoPlayed(boolean value) {
+ mVideoPlayed = value;
+ }
+
+ public void setVideoPrepared(boolean value) {
+ mVideoPrepared = value;
+ }
+
+ // ==============================================================
+ // OTHER METHODS
+ // ==============================================================
+
+ public void startVideoTimer() {
+ // start timer to send every N ms current time position of video
+ Logger.i("Start Timer");
+ int N = 500;
+
+ stopVideoTimer();
+
+ mVideoTimer = new Timer();
+ TimerTask timerTask = new TimerTask() {
+ @Override
+ public void run() {
+ // current position in MP never reaches duration value
+ // check difference on 500 msec
+ if (mVideoPrepared) {
+ if ((mMediaPlayer.getDuration() - mMediaPlayer.getCurrentPosition()) < 500)
+ mVideoController.sendPositionNotification(mMediaPlayer.getDuration());
+ else
+ mVideoController.sendPositionNotification(mMediaPlayer.getCurrentPosition());
+ }
+ }
+ };
+ mVideoTimer.schedule(timerTask, N, N);
+ }
+
+ public void setProgresbarVisibility(boolean value) {
+ int v = value ? ProgressBar.VISIBLE : ProgressBar.GONE;
+ mProgressBar.setVisibility(v);
+ }
+
+ // =====================================================================
+ // private section
+ // =====================================================================
+
+ // private Context ctx;
+
+ private MediaPlayer mMediaPlayer;
+
+ private SharedPreferences mPreferences;
+ private WebView mWebView;
+ private SurfaceView mPreview;
+ private SurfaceHolder mHolder;
+ private ProgressBar mProgressBar;
+ private RelativeLayout mVideoLayout;
+ private ImageView mLogo;
+
+ private int mSeekTo;
+
+ private int mVideoWidth;
+ private int mVideoHeight;
+ private int mLeftMargin;
+ private int mTopMargin;
+
+ private String mPath;
+
+ private Animation mAnimationShow;
+
+ // for JSON communication
+ private JSONServer mServerThread;
+ private JSONBackendController mBEController;
+ private JSONVideoController mVideoController;
+
+ // for video time visualization
+ private Timer mVideoTimer;// timer to send notifications about current video
+ // time
+ private boolean mVideoWasPaused = false;// indicate if video was on paused
+ // before starting activity
+ private int mVideoPauseTime = 0;// time in msec when video was paused before
+ // starting activity
+ private boolean mVideoPlayed = false;// indicate if video played before
+ // starting activity
+ // to measure 5 seconds for splash screen;
+ private long mStartTime;
+ private boolean mVideoPrepared = false; // indicate that video in MP is
+ // prepared and timer can be started
+
+ private AppRater mAppRater;
+
+ private ZipResourceFile apkExpansionZipFile = null;
+ private Context mContext;
+
+ private final Handler handler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+
+ super.handleMessage(msg);
+
+ switch (msg.what) {
+
+ // /// VIDEO
+ case Const.VIDEO_START:
+ Logger.i("mMediaPlayer.play handler");
+ Object[] obj = (Object[]) msg.obj;
+ String videoFile = (String) obj[0];
+ Double scale = (Double) obj[1];
+ int x = (Integer) obj[2];
+ int y = (Integer) obj[3];
+ videoViewResize(scale, y, x);
+ mPath = videoFile;
+ initVideoSurface();
+ break;
+ case Const.VIDEO_PAUSE:
+ Logger.i("mMediaPlayer.pause handler");
+ stopVideoTimer();
+ if (mMediaPlayer != null)
+ mMediaPlayer.pause();
+ mVideoWasPaused = true;
+ mVideoPauseTime = mMediaPlayer.getCurrentPosition();
+ break;
+ case Const.VIDEO_SET_POSITION:
+ Double newPos = (Double) msg.obj * 1000;
+ newPos = newPos == 0 ? 1 : newPos; // because media player can
+ // not set zero value
+ if (mMediaPlayer != null)
+ mediaSetPosition(newPos);
+ break;
+ case Const.VIDEO_SET_POSITION_PAUSED:
+ newPos = (Double) msg.obj * 1000;
+ newPos = newPos == 0 ? 1 : newPos; // because media player can
+ // not set zero value
+ if (mMediaPlayer != null)
+ mediaSetPositionPaused(newPos);
+ break;
+ case Const.VIDEO_PLAY:
+ startVideoTimer();
+ mVideoWasPaused = false;
+ Logger.i("mMediaPlayer.start case Const.VIDEO_PLAY");
+ if (null != mMediaPlayer) {
+ mMediaPlayer.start();
+ } else {
+ Logger.i("mMediaPlayer == null");
+ }
+ break;
+ case Const.VIDEO_STOP:
+ mVideoLayout.setVisibility(View.INVISIBLE);
+ stopVideoTimer();
+ releaseMediaPlayer();
+ mVideoWidth = 0;
+ mVideoHeight = 0;
+ mLeftMargin = 0;
+ mTopMargin = 0;
+ mPath = null;
+ mVideoWasPaused = false;
+ mVideoPlayed = false;
+ mVideoPauseTime = 0;
+ break;
+ case Const.VIDEO_PLAY_AFTER_SCALE:
+ Logger.i("mMediaPlayer.play after scale handler");
+ obj = (Object[]) msg.obj;
+ scale = (Double) obj[0];
+ int left = (Integer) obj[1];
+ int top = (Integer) obj[2];
+ videoViewResize(scale, top, left);
+ initVideoSurface();
+ break;
+
+ case Const.CONTENT_CHECKER_START:
+ verifyContent();
+ break;
+
+ case Const.WEBVIEW_SHOW:
+ hideSplashScreen();
+ setProgresbarVisibility(false);
+ mWebView.startAnimation(mAnimationShow);
+ mWebView.setVisibility(View.VISIBLE);
+ if (Const.DEBUG) {
+ long currTime = System.currentTimeMillis();
+ String str = "Application loading time = " + String.valueOf(currTime - mStartTime);
+ Logger.i(str);
+ SafeToast.showToastAnyThread(str);
+ }
+ DialogFragment appSetupDialogFragment = AppSetupDialog.newInstance(R.string.app_setup_dialog_title);
+ appSetupDialogFragment.show(getFragmentManager(), APP_SETUP_DIALOG_TAG);
+ appSetupDialogFragment.setCancelable(false);
+ break;
+
+ default:
+ break;
+ }
+ }
+ };
+
+ private void verifyContent() {
+
+ removeOldVideoFiles();
+
+ // check main expansion file
+ int mainVersionCode = expFileIsDelivered(true);
+
+ SharedPreferences prefs = getSharedPreferences(
+ Const.SHPREF_DOWNLOADER_PREFS, 0);
+ boolean mainMD5IsCalculated = prefs.getBoolean(
+ Const.SHPREF_MAIN_EXPFILE_VALID, false);
+
+ // check patch expansion file
+ int patchVersionCode = expFileIsDelivered(false);
+
+ boolean patchMD5IsCalculated = prefs.getBoolean(
+ Const.SHPREF_PATCH_EXPFILE_VALID, false);
+
+ if (mainVersionCode > 0 && mainMD5IsCalculated
+ && (patchVersionCode > 0 || Const.PATCH_EXP_FILE_SIZE == 0)
+ && patchMD5IsCalculated) {
+ try {
+ apkExpansionZipFile = APKExpansionSupport
+ .getAPKExpansionZipFile(this, mainVersionCode,
+ patchVersionCode);
+ } catch (IOException e) {
+ Logger.e(e.getMessage(), e);
+ }
+
+ } else {
+ // no expansion file
+ SharedPreferences.Editor editor = prefs.edit();
+ if (editor != null) {
+ editor.putBoolean(Const.SHPREF_MAIN_EXPFILE_VALID, false);
+ editor.putBoolean(Const.SHPREF_PATCH_EXPFILE_VALID, false);
+ }
+ editor.commit();
+ // create downloader client
+ new DownloaderClient(this, mainVersionCode, mainMD5IsCalculated,
+ patchVersionCode, patchMD5IsCalculated);
+
+ }
+
+ Utils.sendMessageToHandler(Const.WEBVIEW_SHOW,
+ MessageConst.NET_DOWNLOAD_FINISHED_SUCC, handler);
+ }
+
+ /**
+ * checks if expansion file was downloaded previously
+ *
+ * @param isMain - is a main expansion file or a patch
+ * @return version code if file exists or 0
+ */
+
+ private int expFileIsDelivered(boolean isMain) {
+ int codeVersion = Utils.getAppVersionCode(getApplicationContext());
+ long size = isMain ? Const.MAIN_EXP_FILE_SIZE
+ : Const.PATCH_EXP_FILE_SIZE;
+ while (codeVersion > 0) {
+ XAPKFile xFile = new XAPKFile(isMain, codeVersion, size);
+ if (ExtStorageUtils.expansionFilesDelivered(mContext, xFile)) {
+ return codeVersion;
+ }
+ codeVersion--;
+ }
+ return codeVersion;
+ }
+
+ public void setExpantionFile(ZipResourceFile file) {
+ apkExpansionZipFile = file;
+ }
+
+ /**
+ * removes video files of MFTG 2, that is apart of expansion file
+ */
+ private boolean removeOldVideoFiles() {
+ File oldVideoFilesDirectory = getExternalFilesDir(null);
+ if ((oldVideoFilesDirectory != null) &&
+ oldVideoFilesDirectory.exists()) {
+ boolean success = true;
+ final File[] files = oldVideoFilesDirectory.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ success &= file.delete();
+ }
+ return success;
+ }
+ }
+ Logger.i("Couldn't remove old video files");
+ return false;
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ Logger.i(getClass().getSimpleName() + " onPause, hash:" + hashCode());
+ if (!isFirstStart()) {
+ ActivityUtils.setAppIsForeground(false);
+ // switch of timer
+ stopVideoTimer();
+ // remember last video position
+ if (mMediaPlayer != null)
+ mVideoPauseTime = mMediaPlayer.getCurrentPosition();
+ // delete media player
+ releaseMediaPlayer();
+ mVideoLayout.removeAllViews();
+ }
+ }
+
+ protected void onResume() {
+ super.onResume();
+ Logger.i(getClass().getSimpleName() + " onResume, hash:" + hashCode());
+ if (!isFirstStart()) {
+ resumeAvatarActivity();
+ }
+ }
+
+ private void startAvatarActivity() {
+ mStartTime = System.currentTimeMillis();
+ mContext = this;
+ // Possible work around for market launches. See
+ // http://code.google.com/p/android/issues/detail?id=2373
+ // for more details. Essentially, the market launches the main activity
+ // on top of other activities.
+ // we never want this to happen. Instead, we check if we are the root
+ // and if not, we finish.
+ if (!isTaskRoot()) {
+ final Intent intent = getIntent();
+ final String intentAction = intent.getAction();
+ if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null
+ && intentAction.equals(Intent.ACTION_MAIN)) {
+ Logger.w("Main Activity is not the root. Finishing Main Activity instead of launching.");
+ finish();
+ return;
+ }
+ }
+
+ mAppRater = new AppRater(this);
+ startRPCComponents();
+ prepareMainView();
+ WebViewUtils.initWebView(this);
+ initVideoSurface();
+ }
+
+ private void resumeAvatarActivity() {
+ ActivityUtils.setAppIsForeground(true);
+
+ if (!fullscreenPreferenceChanged && !vehiclePreferenceChanged)
+ initVideoSurface(); // to init video after resuming but not
+ // after FullScreen or Vehicle changing
+
+ if (mPreferences != null) {
+ if (fullscreenPreferenceChanged) {
+ fullscreenPreferenceChanged = false;
+ mBEController.sendFullScreenRequest(getFullscreenStatus());
+ }
+
+ if (vehiclePreferenceChanged) {
+ vehiclePreferenceChanged = false;
+ mBEController.sendVehicleNotification(getVehicleStatus());
+ }
+
+ if (navigationPreferenceChanged) {
+ navigationPreferenceChanged = false;
+ mBEController.sendHasMapsNotification(getMapsStatus());
+ }
+
+ if (mWebView.getUrl() == null) {
+ if (!loadContent()) {
+ SafeToast.showToastAnyThread(getString(R.string.toast_index_not_found));
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ Logger.i(getClass().getSimpleName() + " onDestroy, hash:" + hashCode());
+
+ unbindSDLService(getBaseContext(), mSDLServiceConnectionProxy);
+ stopService(new Intent(this, SDLService.class));
+
+ if (!isFirstStart()) {
+ // switch of timer
+ stopVideoTimer();
+
+ releaseMediaPlayer();
+ doCleanUp();
+ // close JSON server
+ try {
+ if (mServerThread != null)
+ mServerThread.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ super.onDestroy();
+ }
+
+ /**
+ * Checks if the filename exists in the assets.
+ *
+ * @param assetFilename Filename without any prefix
+ * @return true if the file exists
+ */
+ private boolean assetExists(final String assetFilename) {
+ AssetManager am = getResources().getAssets();
+ try {
+ am.open(assetFilename);
+ } catch (IOException e) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean loadContent() {
+ Logger.i("loadContent");
+ boolean successful = false;
+ if (assetExists(Const.INDEX_PAGE)) {
+ mWebView.loadUrl(Const.WEB_MAIN_PAGE_PATH);
+ successful = true;
+ }
+ return successful;
+ }
+
+ private void startRPCComponents() {
+ Logger.i(getClass().getSimpleName() + " Start RPC Components");
+
+ mServerThread = new JSONServer();
+ mServerThread.setName("ServerThread");
+ mServerThread.start();
+
+ // wait for a while
+ while (!mServerThread.isReady()) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ mBEController = new JSONBackendController(this);
+ mBEController.register(27);
+ // wait for a while
+ while (!mBEController.isRegistered()) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ mVideoController = new JSONVideoController(this);
+ mVideoController.register(28);
+ // wait for a while
+ while (!mVideoController.isRegistered()) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ JSONRateController mRateController = new JSONRateController(mAppRater);
+ mRateController.register(29);
+ // wait for a while
+ while (!mRateController.isRegistered()) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ JSONRevSDLController mRevSDLController = new JSONRevSDLController();
+ mRevSDLController.register(30);
+ // wait for a while
+ while (!mRevSDLController.isRegistered()) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void prepareMainView() {
+ Logger.i("prepareMainView");
+ setContentView(R.layout.main);
+
+ mPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+ Boolean fullScreen = getFullscreenStatus();
+ mLogo = (ImageView) findViewById(R.id.logo);
+ Logger.i("mFullScreen is " + fullScreen.toString());
+ if (fullScreen) {
+ RelativeLayout.LayoutParams params = new LayoutParams(
+ LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+ mLogo.setLayoutParams(params);
+ // mLogo.setLayoutParams(params);
+ } else {
+
+ RelativeLayout.LayoutParams params = new LayoutParams(800, 480);
+ params.addRule(RelativeLayout.CENTER_HORIZONTAL);
+ params.addRule(RelativeLayout.CENTER_VERTICAL);
+ mLogo.setLayoutParams(params);
+ }
+ mWebView = (WebView) findViewById(R.id.webView1);
+ mWebView.setWebChromeClient(new WebChromeClient());
+ mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
+ // mWebView.getSettings().setLoadWithOverviewMode(true);
+ // mWebView.getSettings().setUseWideViewPort(true);
+ // mWebView.setInitialScale(10);
+
+ mVideoLayout = (RelativeLayout) findViewById(R.id.videoLayout);
+ // set progress bar
+ mProgressBar = (ProgressBar) findViewById(R.id.pbProgress);
+ LayoutParams progressParams = (LayoutParams) mProgressBar
+ .getLayoutParams();
+ double loaderHeight = Const.WEB_HEIGHT * getScale() * 0.07 * getWindowDensity();
+ progressParams.height = (int) loaderHeight;
+ progressParams.width = progressParams.height;
+ double loaderVerticalCenter = getWindowHeight() * 0.5;
+ double loaderVerticalShift = Const.WEB_HEIGHT * getScale() * 0.5 * 0.41 * getWindowDensity();
+ double top = (loaderVerticalCenter - 0.5 * loaderHeight) + loaderVerticalShift;
+ progressParams.topMargin = (int) Math.round(top);
+ mProgressBar.setLayoutParams(progressParams);
+
+ mAnimationShow = AnimationUtils.loadAnimation(this, R.anim.show);
+ }
+
+ private double getScale() {
+ double res = 1;
+ if (isFullScreen()) {
+ /** Calculate Scale Point */
+ double scalePointW = (double) getWindowWidth()
+ / (double) Const.WEB_WIDTH / getWindowDensity();
+ double scalePointH = (double) getWindowHeight()
+ / (double) Const.WEB_HEIGHT / getWindowDensity();
+ /** Set calculated ScalePoint */
+ res = (scalePointW >= scalePointH) ? scalePointH : scalePointW;
+ } else {
+ res /= getWindowDensity();
+ }
+ return res;
+ }
+
+ private boolean isFullScreen() {
+ SharedPreferences preferences = PreferenceManager
+ .getDefaultSharedPreferences(this.getApplicationContext());
+ return preferences.getBoolean("FULLSCREEN", true);
+ }
+
+ private Integer getWindowHeight() {
+ Integer height;
+ if ((Build.VERSION.SDK_INT > 10)/* && (Build.VERSION.SDK_INT < 14) */) {
+ // return height without tabs bar
+ Rect rectgle = new Rect();
+ Window window = this.getWindow();
+ window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
+ height = rectgle.bottom; // height = - panel height
+ } else {
+ DisplayMetrics dm = new DisplayMetrics();
+ this.getWindowManager().getDefaultDisplay().getMetrics(dm);
+ if (dm.heightPixels > dm.widthPixels) {
+ height = dm.widthPixels;
+ } else {
+ height = dm.heightPixels;
+ }
+ }
+ return height;
+ }
+
+ private Integer getWindowWidth() {
+ Integer width;
+ DisplayMetrics dm = new DisplayMetrics();
+ this.getWindowManager().getDefaultDisplay().getMetrics(dm);
+ if (dm.heightPixels > dm.widthPixels) {
+ width = dm.heightPixels;
+ } else {
+ width = dm.widthPixels;
+ }
+ return width;
+ }
+
+ private void initVideoSurface() {
+ Logger.i("init surface");
+
+ mVideoLayout.setVisibility(View.INVISIBLE);
+ mVideoLayout.removeAllViews();
+
+ LayoutParams params = (LayoutParams) mVideoLayout.getLayoutParams();
+
+ params.height = mVideoHeight;
+ params.width = mVideoWidth;
+ params.leftMargin = mLeftMargin;
+ params.topMargin = mTopMargin;
+
+ mVideoLayout.setLayoutParams(params);
+ mPreview = new SurfaceView(this);
+
+ mVideoLayout.addView(mPreview);
+ mHolder = mPreview.getHolder();
+ mHolder.addCallback(this);
+ mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+ mVideoLayout.forceLayout();
+ mVideoLayout.setVisibility(View.VISIBLE);
+
+ }
+
+ private void hideSplashScreen() {
+ Logger.i("hide screen ");
+ mVideoLayout.setVisibility(View.VISIBLE);
+ mLogo.setVisibility(View.INVISIBLE);
+ }
+
+ private double mediaGetPosition() {
+ // setIsGetPosition(true);
+ Logger.i("mediaGetPosition");
+ // isDoubleSeek = true;
+ if (mMediaPlayer == null) {
+ return -1;
+ }
+ try {
+ return Utils
+ .getShortDouble(mMediaPlayer.getCurrentPosition() / 1000.0);
+ } catch (IllegalStateException e) {
+ Logger.e(e.getMessage(), e);
+ return -1;
+ }
+ }
+
+ private void mediaSetPosition(double position) {
+ /* convert to milliseconds */
+ // setIsGetPosition(false);
+ // position *= 1000;
+ mSeekTo = (int) position;
+ Logger.i("mediaSetPosition=" + position);
+
+ try {
+ if (mSeekTo != 0)
+ mMediaPlayer.seekTo(mSeekTo);
+ } catch (IllegalStateException e) {
+ Logger.e(e.getMessage(), e);
+ }
+ }
+
+ private void mediaSetPositionPaused(double position) {
+ /* convert to milliseconds */
+ mSeekTo = (int) position;
+
+ Logger.i("mediaSetPositionPaused=" + position);
+
+ AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
+ audioManager.setStreamMute(AudioManager.STREAM_MUSIC, true);
+ try {
+ mMediaPlayer.seekTo(mSeekTo);
+ } catch (IllegalStateException e) {
+ Logger.e(e.getMessage(), e);
+ }
+ }
+
+ private void releaseMediaPlayer() {
+ if (mMediaPlayer != null) {
+ mMediaPlayer.reset();
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ }
+ mVideoPrepared = false;
+ }
+
+ private void videoViewResize(double scale, int top, int left) {
+ mVideoWidth = (int) (Const.ORIG_VIDEO_WIDTH * scale * getWindowDensity() - 1);
+ mVideoHeight = (int) (Const.ORIG_VIDEO_HEIGHT * scale * getWindowDensity() - 1);
+ mLeftMargin = (int) Math.round(left * getWindowDensity());
+ mTopMargin = (int) Math.round(top * getWindowDensity());
+ }
+
+ private double getWindowDensity() {
+ DisplayMetrics dm = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(dm);
+ return dm.density;
+ }
+
+ private void playVideo(SurfaceHolder holder) {
+ Logger.i("playVideo");
+ if (mPath != null) {
+ try {
+ if (mMediaPlayer != null) {
+ releaseMediaPlayer();
+ }
+ // TODO : optimize MP instantiation
+ // Create a new media player and set the listeners
+ mMediaPlayer = new MediaPlayer();
+
+ initDatasourceWith(mPath);
+
+ Logger.i("video file path : " + mPath);
+
+ mMediaPlayer.setDisplay(holder);
+
+ mMediaPlayer.setOnPreparedListener(new AvatarOnPreparedListener(this));
+ mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+
+ mMediaPlayer.prepare();
+ } catch (Exception e) {
+ Logger.e("error: " + e.getMessage(), e);
+ // set duration of video
+ mVideoController.setVideoDuration(-1);
+ }
+ } else {
+ Logger.i("No video to play");
+ }
+ }
+
+ private void stopVideoTimer() {
+ if (mVideoTimer != null) {
+ mVideoTimer.cancel();
+ mVideoTimer.purge();
+ }
+ mVideoTimer = null;
+ }
+
+ private void doCleanUp() {
+ mVideoWidth = 0;
+ mVideoHeight = 0;
+ if (mVideoLayout != null)
+ mVideoLayout.removeAllViews();
+ mHolder = null;
+ mPreview = null;
+ mVideoWasPaused = false;
+ mVideoPauseTime = 0;
+ mVideoPlayed = false;
+ }
+
+ private void initDatasourceWith(String fileName)
+ throws ExtensionFileException, MediaPlayerException {
+
+ AssetFileDescriptor assetFileDescriptor;
+ // welcome orientation video is in raw resources
+ if (fileName.toLowerCase().compareTo(Const.WELCOME_VIDEO_FILE_NAME) == 0) {
+
+ // Commit according to REVSDL-116
+ //assetFileDescriptor = getResources().openRawResourceFd(R.raw.faq_welcome_orientation);
+ Logger.w("Welcome Video is disabled in current version");
+ return;
+
+ } else {
+ // get file from expansion archive
+ if (apkExpansionZipFile == null) {
+ throw new ExtensionFileException("Expansion zip file variable is not initialized");
+ }
+ assetFileDescriptor = apkExpansionZipFile.getAssetFileDescriptor(fileName);
+ }
+
+ if (assetFileDescriptor == null) {
+ throw new ExtensionFileException("Assert file descriptor for file: " + fileName +
+ " not found");
+ }
+
+ try {
+ mMediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(),
+ assetFileDescriptor.getStartOffset(),
+ assetFileDescriptor.getLength());
+ } catch (IllegalArgumentException e) {
+ throw new MediaPlayerException(e);
+ } catch (IllegalStateException e) {
+ throw new MediaPlayerException(e);
+ } catch (IOException e) {
+ throw new MediaPlayerException(e);
+ }
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
+ }
+
+ @Override
+ public void onSDLServiceConnected(SDLServiceBinder service) {
+ Logger.i("SDLService connected " + service);
+
+ mBoundSDLService = service.getService();
+ }
+
+ @Override
+ public void onSDLServiceDisconnected() {
+ Logger.i("SDLService disconnected");
+
+ mBoundSDLService = null;
+ }
+} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/views/ConnectionTypeDialog.java b/native/android/avatar/src/main/java/com/ford/avarsdl/views/ConnectionTypeDialog.java
new file mode 100644
index 0000000000..0ae6cf2419
--- /dev/null
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/views/ConnectionTypeDialog.java
@@ -0,0 +1,17 @@
+package com.ford.avarsdl.views;
+
+import android.app.Dialog;
+import android.content.Context;
+
+/**
+ * Created with Android Studio.
+ * Author: Chernyshov Yuriy - Mobile Development
+ * Date: 11/28/13
+ * Time: 3:08 PM
+ */
+public class ConnectionTypeDialog extends Dialog {
+
+ public ConnectionTypeDialog(Context context) {
+ super(context);
+ }
+} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/views/EulaActivity.java b/native/android/avatar/src/main/java/com/ford/avarsdl/views/EulaActivity.java
new file mode 100644
index 0000000000..b27a41ced1
--- /dev/null
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/views/EulaActivity.java
@@ -0,0 +1,32 @@
+package com.ford.avarsdl.views;
+
+import com.ford.avarsdl.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class EulaActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.eula);
+ Button btnAgree = (Button) findViewById(R.id.btnAgree);
+ Bundle extras = getIntent().getExtras();
+ if (extras != null && !extras.getBoolean("firstStart")) {
+ btnAgree.setText("Done");
+ }
+ btnAgree.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = getIntent();
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+ });
+ }
+} \ No newline at end of file
diff --git a/native/android/avatar/src/main/java/com/ford/avarsdl/activity/SafeToast.java b/native/android/avatar/src/main/java/com/ford/avarsdl/views/SafeToast.java
index a0ad493431..272b29fa06 100644
--- a/native/android/avatar/src/main/java/com/ford/avarsdl/activity/SafeToast.java
+++ b/native/android/avatar/src/main/java/com/ford/avarsdl/views/SafeToast.java
@@ -1,4 +1,4 @@
-package com.ford.avarsdl.activity;
+package com.ford.avarsdl.views;
import android.content.Context;
import android.widget.Toast;
diff --git a/native/android/avatar/src/main/res/layout/sdl_settings.xml b/native/android/avatar/src/main/res/layout/sdl_settings.xml
index e4a2e4bd51..d0ad268357 100644
--- a/native/android/avatar/src/main/res/layout/sdl_settings.xml
+++ b/native/android/avatar/src/main/res/layout/sdl_settings.xml
@@ -1,56 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:orientation="vertical"
+ android:padding="10dp"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <RadioGroup
+ android:id="@+id/selectprotocol_radioGroupTransport"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginBottom="20dp"
+ android:orientation="horizontal" >
+
+ <RadioButton
+ android:id="@+id/selectprotocol_radioWiFi"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="50dp"
+ android:text="@string/app_setup_protocol_wifi" />
+
+ <RadioButton
+ android:id="@+id/selectprotocol_radioBT"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="@string/app_setup_protocol_bluetooth" />
+ </RadioGroup>
<LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_marginBottom="20dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
<TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="5dp"
- android:layout_marginRight="5dp"
- android:text="@string/selectprotocol_ipAddress"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="5dp"
+ android:layout_marginRight="5dp"
+ android:text="@string/app_setup_protocol_ip_address"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
- android:id="@+id/sdl_ipAddr"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginRight="5dp"
- android:layout_weight="1"
- android:ems="10"
- android:inputType="text"
- android:maxLength="15"
- android:text="@string/selectprotocol_ipAddressDefault"/>
+ android:id="@+id/sdl_ipAddr"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dp"
+ android:layout_weight="1"
+ android:ems="10"
+ android:inputType="text"
+ android:maxLength="15"
+ android:text="@string/app_setup_protocol_ip_address_default" />
</LinearLayout>
<LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
<TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="5dp"
- android:layout_marginRight="5dp"
- android:text="@string/selectprotocol_tcpPort"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="5dp"
+ android:layout_marginRight="5dp"
+ android:text="@string/app_setup_protocol_tcp_port"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
- android:id="@+id/sdl_tcpPort"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginRight="5dp"
- android:layout_weight="1"
- android:ems="10"
- android:inputType="number"
- android:maxLength="5"
- android:text="@string/selectprotocol_tcpPortDefault"/>
+ android:id="@+id/sdl_tcpPort"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dp"
+ android:layout_weight="1"
+ android:ems="10"
+ android:inputType="number"
+ android:maxLength="5"
+ android:text="@string/app_setup_protocol_tcp_port_default" />
</LinearLayout>
</LinearLayout> \ No newline at end of file
diff --git a/native/android/avatar/src/main/res/raw/faq_welcome_orientation.mp4 b/native/android/avatar/src/main/res/raw/faq_welcome_orientation.mp4
deleted file mode 100644
index 07b2aaf2df..0000000000
--- a/native/android/avatar/src/main/res/raw/faq_welcome_orientation.mp4
+++ /dev/null
Binary files differ
diff --git a/native/android/avatar/src/main/res/values/strings.xml b/native/android/avatar/src/main/res/values/strings.xml
index 712185c86e..0ea9e076f7 100644
--- a/native/android/avatar/src/main/res/values/strings.xml
+++ b/native/android/avatar/src/main/res/values/strings.xml
@@ -37,9 +37,12 @@
Download Complete.\nVideos are available to view.
</string>
- <string name="selectprotocol_ipAddress">IP Address:</string>
- <string name="selectprotocol_ipAddressDefault">10.10.0.1</string>
- <string name="selectprotocol_tcpPort">TCP Port:</string>
- <string name="selectprotocol_tcpPortDefault">12345</string>
+ <string name="app_setup_dialog_title">Please set up application properties</string>
+ <string name="app_setup_protocol_ip_address">IP Address:</string>
+ <string name="app_setup_protocol_ip_address_default">10.10.0.1</string>
+ <string name="app_setup_protocol_tcp_port">TCP Port:</string>
+ <string name="app_setup_protocol_tcp_port_default">12345</string>
+ <string name="app_setup_protocol_wifi">WiFi</string>
+ <string name="app_setup_protocol_bluetooth">Bluetooth</string>
</resources> \ No newline at end of file
diff --git a/native/android/avatar_test/src/com/ford/avatar/test/jsoncontroller/JSONAVAControllerTest.java b/native/android/avatar_test/src/com/ford/avatar/test/jsoncontroller/JSONAVAControllerTest.java
index b3c17f9d03..b2ad105513 100644
--- a/native/android/avatar_test/src/com/ford/avatar/test/jsoncontroller/JSONAVAControllerTest.java
+++ b/native/android/avatar_test/src/com/ford/avatar/test/jsoncontroller/JSONAVAControllerTest.java
@@ -56,7 +56,7 @@ public class JSONAVAControllerTest extends TestCase {
}
/**
- * Test method for {@link com.ford.avarsdl.jsoncontroller.JSONAVAController#JSONAVAController(com.ford.avarsdl.activity.AvatarActivity, java.lang.String)}.
+ * Test method for {@link com.ford.avarsdl.jsoncontroller.JSONAVAController#JSONAVAController(com.ford.avarsdl.views.AvatarActivity, java.lang.String)}.
*/
public final void testJSONAVAController() {
JSONAVAController controller = new JSONAVAController(RPCConst.CN_AVATAR, mTcpStub);
diff --git a/openxc_backend/README b/openxc_backend/README
new file mode 100644
index 0000000000..51353d22a1
--- /dev/null
+++ b/openxc_backend/README
@@ -0,0 +1,20 @@
+Dependency libraries (need to install first and check their successfull installation):
+- python 2.7
+- pip (http://www.pip-installer.org/en/latest/installing.html)
+- openxc (http://python.openxcplatform.com/en/latest/installation.html)
+
+1. It is necessary to have appropriate firmware for the OpenXC (the one Chris creates with the name "vi-firmware-FORDBOARD-radiocontrols-20-11-13.bin")
+
+2. Once OpenXC connected to the USB need to be sure that all data transferring well (cammand "openxc-dump" http://python.openxcplatform.com/en/latest/tools/dump.html)
+ Be sure that only one connection with OpenXC via USB exists! (after successfull command line test close all terminals)
+
+3. Run Server.py with next parameter:
+ PYTHONUNBUFFERED=1 python ~/<path_to_file>/Server.py
+
+ To be sure that OpenXC server works navigate to "openxc_backend/web_console" and run index.html
+ You should see "Server status:" panel at the left side and "Dump:" panel at rigth side with a data flow.
+ If there are no data flow, please be sure that at the terminal window where server was launched there are no errors (is there are errors - restart server)
+
+ When server run with success please press "Stop" and close index.html page (as pointed in N2 it occupies connection)
+
+4. When HMI simulator run it automatically create connection to the server
diff --git a/openxc_backend/installer.sh b/openxc_backend/installer.sh
new file mode 100755
index 0000000000..ba758b87c6
--- /dev/null
+++ b/openxc_backend/installer.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+echo "Check Python installation ..."
+command -v python >/dev/null 2>&1 || { echo >&2 "Python is not installed. Installing Python now ...";
+sudo apt-get install python; }
+echo " Python is installed"
+
+echo "Check Python Pip installation ..."
+command -v python-pip >/dev/null 2>&1 || { echo >&2 "Python Pip is not installed. Installing Python Pip now ...";
+sudo apt-get install python-pip; }
+echo " Python Pip is installed"
+
+echo "Check OpenXC installation ..."
+command -v openxc-control version >/dev/null 2>&1 || { echo >&2 " OpenXC is not installed. Installing OpenXC now ...";
+sudo pip install -U openxc; }
+echo " OpenXC is installed"
+
+echo "Installing Tornado ..."
+sudo pip install tornado --upgrade
+echo " Tornado is installed"
diff --git a/openxc_backend/server/Server.py b/openxc_backend/server/Server.py
index 5c9bc9bb12..02b4bc2cbd 100644
--- a/openxc_backend/server/Server.py
+++ b/openxc_backend/server/Server.py
@@ -23,6 +23,8 @@ class MainHandler(WebSocketHandler):
print "Socket message: " + message
openxc_command = ""
+ if message.startswith("stop_server"):
+ return
if message.startswith("set_preset_"):
#print ("Set Preset", message[11:])
openxc_command = 'openxc-control write --name tune --value preset --event ' + message[11:]
@@ -59,8 +61,13 @@ class MainHandler(WebSocketHandler):
print "Socket close"
def line_from_net_tail(self, data):
- self.write_message(data)
- self.stream.read_until("\n", self.line_from_net_tail)
+ try:
+ self.write_message(data)
+ self.stream.read_until("\n", self.line_from_net_tail)
+ except Exception:
+ self.p.terminate()
+ self.stream.close()
+ pass
def open_dump_stream(self):
self.p = subprocess.Popen(["openxc-dump"], stdout=subprocess.PIPE)
diff --git a/openxc_backend/web_console/index.html b/openxc_backend/web_console/index.html
index caf9eadc8b..467d62f956 100644
--- a/openxc_backend/web_console/index.html
+++ b/openxc_backend/web_console/index.html
@@ -8,7 +8,15 @@
</head>
<body>
<div style="width: 100%; height: 100%">
- <div style="width: 38%; height: 400px;float: left; background-color: gainsboro; padding: 10px">
+ <div style="width: 10%; height: 400px;float: left; background-color: aliceblue; padding: 10px">
+ <label>Server status:</label>
+ <label id="server_status_label">stopped</label>
+ <div style="margin-top: 10px">
+ <button id="server_start_btn">Start</button>
+ <button id="server_stop_btn">Stop</button>
+ </div>
+ </div>
+ <div style="width: 28%; height: 400px;float: left; background-color: gainsboro; padding: 10px">
<div>
<label>Tuner Band:</label>
<select id="tuner_band_select">
diff --git a/openxc_backend/web_console/js/index.js b/openxc_backend/web_console/js/index.js
index 1f8c1f9efb..f90d625520 100644
--- a/openxc_backend/web_console/js/index.js
+++ b/openxc_backend/web_console/js/index.js
@@ -1,3 +1,4 @@
+var socketURL = "localhost:9092";
var socket;
var Socket = {
webSocket: null,
@@ -7,10 +8,12 @@ var Socket = {
ws.onopen = function () {
console.log('Socket opened at ' + url);
+ $("#server_status_label").html("running ...");
};
ws.onclose = function () {
console.log('Socket close at ' + url);
+ $("#server_status_label").html("stopped");
};
ws.onmessage = function (e) {
@@ -20,7 +23,7 @@ var Socket = {
};
this.webSocket = ws;
- }
+ },
};
function parseMessage(message) {
@@ -57,11 +60,20 @@ function updateDumpTextArea(message) {
function init() {
setListeners();
- Socket.init("localhost:9092");
+ Socket.init(socketURL);
socket = Socket.webSocket;
}
function setListeners() {
+ $('#server_start_btn').on('click', function() {
+ console.info("Start server");
+ Socket.init(socketURL);
+ socket = Socket.webSocket;
+ });
+ $('#server_stop_btn').on('click', function() {
+ console.info("Stop server");
+ sendCommand("stop_server");
+ });
$('#station_up_btn_id').on('click', function() {
console.info("Station +");
sendCommand("station_up");
@@ -106,6 +118,11 @@ function sendCommand(command) {
}
}
+window.onbeforeunload = function() {
+ Socket.onclose = function () {}; // disable onclose handler first
+ Socket.close()
+};
+
$(document).ready(function() {
init();
}); \ No newline at end of file
diff --git a/sdl b/sdl
-Subproject 7acc9dd11e86c52907fb98ba82b90de30f19507
+Subproject 66256d76b80048b523027dc42d8cc7874c05256
diff --git a/web/src/app/controller/AppController.js b/web/src/app/controller/AppController.js
index b6805f913c..828728d010 100644
--- a/web/src/app/controller/AppController.js
+++ b/web/src/app/controller/AppController.js
@@ -94,7 +94,7 @@ MFT.AppController = Em.Object.create({
* Show popup and close it after closeTime, if it exists
* @param {number} closeTime time, after which the popup will close
* @param {string} message, displaying message popup
- * @param {string} callback function
+ * @param {function} callback function
*/
showPopup: function(elementId, closeTime, message, callback){
var self = this;
@@ -155,13 +155,19 @@ MFT.AppController = Em.Object.create({
this.showPopup('SDLMessagesPopup', 2000, MFT.locale.label.view_sdl_messages_popup_driverControl);
},
- changeAccessStatus: function(data) {
+ changeAccessStatus: function(method, data) {
var self = this;
if (data.success) {
- this.set('sdlAccessStatus', true);
- this.set('sdlControlStatus', 4);
- this.showPopup('SDLMessagesPopup', 2000, MFT.locale.label.view_sdl_messages_popup_granted);
+ if (method == 'grant') {
+ this.set('sdlAccessStatus', true);
+ this.set('sdlControlStatus', 4);
+ this.showPopup('SDLMessagesPopup', 2000, MFT.locale.label.view_sdl_messages_popup_granted);
+ } else if (method == 'cancel') {
+ this.set('sdlAccessStatus', false);
+ this.set('sdlControlStatus', 1);
+ this.showPopup('SDLMessagesPopup', 2000, MFT.locale.label.view_sdl_messages_popup_driverControl);
+ }
} else if(data.resultCode == 'REJECTED') {
this.set('sdlControlStatus', 3);
this.showPopup('SDLMessagesPopup', 2000, MFT.locale.label.view_sdl_messages_popup_denied, function () {
diff --git a/web/src/app/controller/MediaController.js b/web/src/app/controller/MediaController.js
index 61c8fc3e4e..f4f2bbc876 100644
--- a/web/src/app/controller/MediaController.js
+++ b/web/src/app/controller/MediaController.js
@@ -931,8 +931,7 @@ MFT.MediaController = Em.Object.create({
}
MFT.FmModel.fm1.set('items', items);
-
- FFW.RevSDL.sendGetRadioDetailsRequest();
+ FFW.RevSDL.sendShowRequest();
},
/** Player Next track event*/
@@ -1198,6 +1197,14 @@ MFT.MediaController = Em.Object.create({
}
},
+ tuneUp: function() {
+ FFW.RevSDL.tuneUp();
+ },
+
+ tuneDown: function() {
+ FFW.RevSDL.tuneDown();
+ },
+
turnReplayHelpVideoOn: function(){
if ( MFT.helpMode ) {
MFT.VideoPlayerController.start('ent_Replay');
diff --git a/web/src/app/view/media/radio/fmView.js b/web/src/app/view/media/radio/fmView.js
index 6e453add96..e7ca251d42 100644
--- a/web/src/app/view/media/radio/fmView.js
+++ b/web/src/app/view/media/radio/fmView.js
@@ -192,7 +192,8 @@ MFT.FMView = Em.ContainerView.create(MFT.LoadableView,{
'scanButton',
'optionsButton',
'directTuneButton',
- 'sendRequestButton'
+ 'sendRequestButton',
+ 'tuneButtons'
],
hdButton: MFT.Button.extend({
@@ -211,13 +212,13 @@ MFT.FMView = Em.ContainerView.create(MFT.LoadableView,{
onDown: false,
icon: 'images/media/passiv_horiz_led.png',
// Change Icon for HD State
- onIconChange: function(){
- if(MFT.MediaController.get('isHDActive') && MFT.SettingsModel.isEnglish){
- this.set('icon', 'images/media/active_horiz_led.png');
- }else{
- this.set('icon', 'images/media/passiv_horiz_led.png');
- }
- }.observes('MFT.MediaController.isHDActive'),
+// onIconChange: function(){
+// if(MFT.MediaController.get('isHDActive') && MFT.SettingsModel.isEnglish){
+// this.set('icon', 'images/media/active_horiz_led.png');
+// }else{
+// this.set('icon', 'images/media/passiv_horiz_led.png');
+// }
+// }.observes('MFT.MediaController.isHDActive'),
disabledBinding: 'MFT.MediaController.isHDButtonActive'
@@ -295,6 +296,33 @@ MFT.FMView = Em.ContainerView.create(MFT.LoadableView,{
disabled: function() {
return (MFT.AppController.sdlControlStatus == 2);
}.property('MFT.AppController.sdlControlStatus')
+ }),
+
+ tuneButtons: Em.ContainerView.extend({
+ elementId: 'media_fm_tuneButtons',
+
+ childViews: [
+ 'tuneDown',
+ 'tuneUp'
+ ],
+
+ tuneUp: MFT.Button.extend({
+ elementId: 'media_fm_tuneUpButton',
+ target: 'MFT.MediaController',
+ action: 'tuneUp',
+ onDown: false,
+ templateName: 'text',
+ text: '>>'
+ }),
+
+ tuneDown: MFT.Button.extend({
+ elementId: 'media_fm_tuneDownButton',
+ target: 'MFT.MediaController',
+ action: 'tuneDown',
+ onDown: false,
+ templateName: 'text',
+ text: '<<'
+ })
})
})
diff --git a/web/src/css/media.css b/web/src/css/media.css
index b3b5199244..c8b62785e4 100644
--- a/web/src/css/media.css
+++ b/web/src/css/media.css
@@ -18,7 +18,7 @@
}
#media_directTune {
- z-index: 503;
+ z-index: 5;
position: absolute;
top: 290px;
left: 165px;
@@ -2199,4 +2199,22 @@
/* cancel scrollbar animation */
.cancelBarAnimation {
-webkit-transition: none !important;
+}
+
+#media_fm_tuneButtons {
+ margin: 4px 5px 0 5px;
+}
+
+#media_fm_tuneButtons .ffw-button {
+ width: 60px;
+ height: 40px;
+ font-size: 22px;
+ text-align: center;
+ line-height: 40px;
+ display: inline-block;
+ vertical-align: top;
+ border: 1px solid #333;
+ border-radius: 3px;
+ position: relative;
+ margin: 0 4px;
} \ No newline at end of file
diff --git a/web/src/ffw/RevSDLRPC.js b/web/src/ffw/RevSDLRPC.js
index b4c7ff1ba7..9502301fb9 100644
--- a/web/src/ffw/RevSDLRPC.js
+++ b/web/src/ffw/RevSDLRPC.js
@@ -90,17 +90,34 @@ FFW.RevSDL = FFW.RPCObserver.create({
switch (response.id) {
case this.GrantAccessRequestId:
- MFT.AppController.changeAccessStatus(response.result);
+ MFT.AppController.changeAccessStatus('grant', response.result);
break;
-// case this.StartScanRequestId:
-// MFT.MediaController.set('isFrequencyScan', response.result.success);
-// break;
-// case this.StopScanRequestId:
-// MFT.MediaController.set('isFrequencyScan', !response.result.success);
-// break;
- case this.GetRadioDetailsRequestId:
- MFT.MediaController.setSDLDirectTuneStation(response.result);
- this.sendShowRequest();
+ case this.CancelAccessRequestId:
+ MFT.AppController.changeAccessStatus('cancel', response.result);
+ break;
+ case this.StartScanRequestId:
+ if (!response.result.success) {
+ Em.Logger.error("Error StartScan request:" + response.result.resultCode);
+ } else {
+ MFT.MediaController.set('isFrequencyScan', response.result.success);
+ }
+ break;
+ case this.StopScanRequestId:
+ if (!response.result.success) {
+ Em.Logger.error("Error StopScan request:" + response.result.resultCode);
+ } else {
+ MFT.MediaController.set('isFrequencyScan', !response.result.success);
+ }
+ break;
+ case this.TuneUpRequestId:
+ if (!response.result.success) {
+ Em.Logger.error("Error TuneUp request:" + response.result.resultCode);
+ }
+ break;
+ case this.TuneDownRequestId:
+ if (!response.result.success) {
+ Em.Logger.error("Error TuneDown request:" + response.result.resultCode);
+ }
break;
}
},
@@ -147,6 +164,8 @@ FFW.RevSDL = FFW.RPCObserver.create({
StartScanRequestId: -1,
StopScanRequestId: -1,
GetRadioDetailsRequestId: -1,
+ TuneUpRequestId: -1,
+ TuneDownRequestId: -1,
/**
* Sends a request for access to the management of HMI, through SDL interface
@@ -227,13 +246,27 @@ FFW.RevSDL = FFW.RPCObserver.create({
/**
* Stop frequency scan on head unit, through SDL interface
**/
- sendGetRadioDetailsRequest: function(){
- this.GetRadioDetailsRequestId = this.client.generateId();
+ tuneUp: function(){
+ this.TuneUpRequestId = this.client.generateId();
+
+ var JSONMessage = {
+ "jsonrpc": "2.0",
+ "id": this.TuneUpRequestId,
+ "method": "RevSDL.TuneUp"
+ };
+ this.client.send(JSONMessage);
+ },
+
+ /**
+ * Stop frequency scan on head unit, through SDL interface
+ **/
+ tuneDown: function(){
+ this.TuneDownRequestId = this.client.generateId();
var JSONMessage = {
"jsonrpc": "2.0",
- "id": this.GetRadioDetailsRequestId,
- "method": "RevSDL.GetRadioDetails"
+ "id": this.TuneDownRequestId,
+ "method": "RevSDL.TuneDown"
};
this.client.send(JSONMessage);
},
diff --git a/web/src/images/common/car.png b/web/src/images/common/car.png
new file mode 100644
index 0000000000..141c4f3c14
--- /dev/null
+++ b/web/src/images/common/car.png
Binary files differ
diff --git a/web/src/images/common/car_red.png b/web/src/images/common/car_red.png
new file mode 100644
index 0000000000..ee2b88ac27
--- /dev/null
+++ b/web/src/images/common/car_red.png
Binary files differ
diff --git a/web/src/images/common/car_yellow.png b/web/src/images/common/car_yellow.png
new file mode 100644
index 0000000000..b5f8fccc60
--- /dev/null
+++ b/web/src/images/common/car_yellow.png
Binary files differ
diff --git a/web/src/images/common/header_bg_old.png b/web/src/images/common/header_bg_old.png
new file mode 100644
index 0000000000..f2752149f0
--- /dev/null
+++ b/web/src/images/common/header_bg_old.png
Binary files differ
diff --git a/web/src/images/common/phone.png b/web/src/images/common/phone.png
new file mode 100644
index 0000000000..30590dba1d
--- /dev/null
+++ b/web/src/images/common/phone.png
Binary files differ
diff --git a/web/src/locale/eng.js b/web/src/locale/eng.js
index 48e91bf9da..e6f4435c7f 100644
--- a/web/src/locale/eng.js
+++ b/web/src/locale/eng.js
@@ -382,7 +382,7 @@ MFT.eng = {
view_media_presets: 'Presets',
view_media_directTune: 'Direct Tune',
view_media_browse: 'Browse',
- view_media_grantAccess: 'Grant access',
+ view_media_grantAccess: 'Request access',
view_media_cancelAccess: 'Cancel access',
view_media_moreInfo_title: 'Song Information',