├── .gitattributes ├── .gitignore ├── Examples └── HorizonSDKDemo │ ├── .gitignore │ ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── hvt │ │ │ └── petrakeas │ │ │ └── simpleapp │ │ │ ├── MainActivity.java │ │ │ └── SimpleApp.java │ │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── horizon_sdk_customization.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── libs │ └── horizonsdk.aar │ └── settings.gradle ├── HorizonSDK └── horizonsdk.aar ├── LICENSE ├── README.md └── docs ├── assets ├── customizations.css ├── customizations.js ├── doclava-developer-core.css ├── doclava-developer-docs.css ├── doclava-developer-docs.js ├── doclava-developer-reference.js ├── images │ ├── bg_fade.jpg │ ├── bg_logo.png │ ├── body-gradient-tab.png │ ├── body-gradient.png │ ├── grad-rule-qv.png │ ├── horizonsdk-logo.png │ ├── hr_gray_main.jpg │ ├── hr_gray_side.jpg │ ├── left_off.jpg │ ├── left_on.jpg │ ├── preliminary.png │ ├── resizable-e.gif │ ├── resizable-e2.gif │ ├── resizable-eg.gif │ ├── resizable-s.gif │ ├── resizable-s2.gif │ ├── resizable-sg.gif │ ├── right_off.jpg │ ├── right_on.jpg │ ├── sidenav-rule.png │ ├── spacer.gif │ ├── triangle-closed-small.png │ ├── triangle-closed.png │ ├── triangle-opened-small.png │ └── triangle-opened.png ├── jquery-history.js ├── jquery-resizable.min.js ├── navtree_data.js ├── prettify.js ├── search_autocomplete.js ├── style.css └── triangle-none.gif ├── index.html └── reference ├── classes.html ├── com └── hvt │ └── horizonSDK │ ├── CameraHelper.html │ ├── HVTCamcorderProfile.html │ ├── HVTCamera.html │ ├── HVTCameraListener.html │ ├── HVTVars.CameraMode.html │ ├── HVTVars.HVTLevelerCropMode.html │ ├── HVTVars.HVTLevelerFlexSpeed.html │ ├── HVTVars.HVTLevelerLockedOrientation.html │ ├── HVTVars.html │ ├── HVTView.FillMode.html │ ├── HVTView.ViewType.html │ ├── HVTView.html │ ├── HorizonSDK.html │ ├── Size.html │ ├── package-descr.html │ └── package-summary.html ├── current.xml ├── hierarchy.html ├── index.html ├── lists.js ├── package-list └── packages.html /.gitattributes: -------------------------------------------------------------------------------- 1 | *.html text 2 | *.css text -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .DS_Store 5 | /build 6 | /captures 7 | 8 | 9 | # Android Studio 10 | #http://stackoverflow.com/questions/5533050/gitignore-exclude-folder-but-include-specific-subfolder 11 | !.idea/ 12 | .idea/* 13 | !.idea/scopes/ 14 | *.ipr 15 | *.iws 16 | *.iml 17 | 18 | # Log Files 19 | *.log -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .DS_Store 5 | /build 6 | /captures 7 | 8 | 9 | # Android Studio 10 | #http://stackoverflow.com/questions/5533050/gitignore-exclude-folder-but-include-specific-subfolder 11 | !.idea/ 12 | .idea/* 13 | !.idea/scopes/ 14 | *.ipr 15 | *.iws 16 | *.iml 17 | 18 | # Log Files 19 | *.log -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /bin -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 33 5 | 6 | defaultConfig { 7 | applicationId "com.hvt.petrakeas.simpleapp" 8 | minSdkVersion 19 9 | targetSdkVersion 33 10 | versionCode 5 11 | versionName "1.04" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled true 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | 20 | compileOptions { 21 | sourceCompatibility 1.8 22 | targetCompatibility 1.8 23 | } 24 | 25 | packagingOptions { 26 | exclude 'META-INF/LICENSE.txt' 27 | exclude 'META-INF/NOTICE.txt' 28 | } 29 | } 30 | 31 | 32 | dependencies { 33 | implementation fileTree(include: ['*.jar'], dir: 'libs') 34 | implementation 'androidx.appcompat:appcompat:1.6.1' 35 | 36 | implementation(name: 'horizonsdk', ext: 'aar') 37 | // HorizonSDK dependencies 38 | implementation 'com.google.guava:guava:31.1-android' 39 | 40 | testImplementation 'junit:junit:4.13.2' 41 | } 42 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Petrakeas\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 9 | 11 | 12 | 20 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/java/com/hvt/petrakeas/simpleapp/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016. Horizon Video Technologies. All rights reserved. 3 | */ 4 | 5 | package com.hvt.petrakeas.simpleapp; 6 | 7 | import android.Manifest; 8 | import android.app.Activity; 9 | import android.content.Context; 10 | import android.content.pm.PackageManager; 11 | import android.content.res.Configuration; 12 | import android.hardware.Camera; 13 | import android.media.MediaScannerConnection; 14 | import android.os.Build; 15 | import android.os.Bundle; 16 | import android.os.Environment; 17 | import androidx.core.app.ActivityCompat; 18 | import androidx.appcompat.app.AppCompatActivity; 19 | import androidx.appcompat.widget.AppCompatButton; 20 | import android.view.View; 21 | import android.widget.Toast; 22 | 23 | import com.hvt.horizonSDK.CameraHelper; 24 | import com.hvt.horizonSDK.HVTCamcorderProfile; 25 | import com.hvt.horizonSDK.HVTCamera; 26 | import com.hvt.horizonSDK.HVTCameraListener; 27 | import com.hvt.horizonSDK.HVTVars; 28 | import com.hvt.horizonSDK.HVTVars.HVTLevelerCropMode; 29 | import com.hvt.horizonSDK.HVTView; 30 | import com.hvt.horizonSDK.Size; 31 | 32 | import java.io.File; 33 | import java.io.IOException; 34 | import java.util.ArrayList; 35 | import java.util.List; 36 | 37 | import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; 38 | 39 | @SuppressWarnings("deprecation") 40 | public class MainActivity extends AppCompatActivity { 41 | 42 | private HVTView mCameraPreview; 43 | private HVTCamera mHVTCamera; 44 | private CameraHelper mCameraHelper; 45 | 46 | private AppCompatButton mRecButton; 47 | private AppCompatButton mPhotoButton; 48 | private AppCompatButton mCropButton; 49 | private AppCompatButton mFlipCameraButton; 50 | private AppCompatButton mFlashCameraButton; 51 | 52 | private File mVideoFile; 53 | private File mPhotoFile; 54 | 55 | private final String[] PERMISSIONS; 56 | { 57 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) { 58 | PERMISSIONS = new String[]{ 59 | Manifest.permission.CAMERA, 60 | Manifest.permission.RECORD_AUDIO, 61 | WRITE_EXTERNAL_STORAGE}; 62 | } else { 63 | PERMISSIONS = new String[]{ 64 | Manifest.permission.CAMERA, 65 | Manifest.permission.RECORD_AUDIO}; 66 | } 67 | } 68 | private static final int PERMISSIONS_REQ_CODE = 1; 69 | private boolean mHasPermission; 70 | 71 | @Override 72 | protected void onCreate(Bundle savedInstanceState) { 73 | super.onCreate(savedInstanceState); 74 | setContentView(R.layout.activity_main); 75 | 76 | // Create and configure HVTCamera 77 | mHVTCamera = new HVTCamera(getApplicationContext()); 78 | mHVTCamera.setListener(new MyListener()); 79 | int activityRotation = getWindowManager().getDefaultDisplay().getRotation(); 80 | mHVTCamera.setScreenRotation(activityRotation); 81 | 82 | // Configure and attach HVTView 83 | mCameraPreview = (HVTView) findViewById(R.id.camera_preview); 84 | mHVTCamera.attachPreviewView(mCameraPreview); 85 | 86 | // alternateConfiguration(); 87 | 88 | checkPermission(); 89 | } 90 | 91 | private void onCreatePermissionGranted() { 92 | // We'll save photos and videos to the same file for simplicity. 93 | File directory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) 94 | .getAbsolutePath() + File.separator + "HorizonSDKSample"); 95 | directory.mkdirs(); 96 | mVideoFile = new File(directory.getAbsolutePath(), "video.mp4"); 97 | mPhotoFile = new File(directory.getAbsolutePath(), "photo.jpeg"); 98 | 99 | // Select camera resolution 100 | try { 101 | mCameraHelper = new CameraHelper(); 102 | } catch (IOException e) { 103 | e.printStackTrace(); 104 | Toast.makeText(getApplicationContext(), "Camera could not be opened", Toast.LENGTH_LONG).show(); 105 | finish(); 106 | return; 107 | } 108 | int facing = mCameraHelper.hasCamera(Camera.CameraInfo.CAMERA_FACING_BACK) ? 109 | Camera.CameraInfo.CAMERA_FACING_BACK : Camera.CameraInfo.CAMERA_FACING_FRONT; 110 | Size[] sizes = mCameraHelper.getDefaultVideoAndPhotoSize(facing); 111 | mHVTCamera.setCamera(facing, sizes[0], sizes[1]); 112 | 113 | // Initialize UI 114 | initializeButtons(); 115 | } 116 | 117 | private void alternateConfiguration() { 118 | mHVTCamera.setWatermarkEnabled(true); 119 | mHVTCamera.setOutputMovieSize(new Size(640, 480)); 120 | mHVTCamera.setCameraMode(HVTVars.CameraMode.VIDEO); 121 | 122 | mCameraPreview.setViewType(HVTView.ViewType.LEVELED); 123 | mCameraPreview.setFillMode(HVTView.FillMode.ASPECT_FIT); 124 | mCameraPreview.setDoubleTapToChangeFillMode(false); 125 | } 126 | 127 | private void initializeButtons() { 128 | mRecButton = (AppCompatButton) findViewById(R.id.rec_button); 129 | mPhotoButton = (AppCompatButton) findViewById(R.id.photo_button); 130 | mCropButton = (AppCompatButton) findViewById(R.id.crop_button); 131 | mFlipCameraButton = (AppCompatButton) findViewById(R.id.flip_camera_button); 132 | mFlashCameraButton = (AppCompatButton) findViewById(R.id.flash_button); 133 | 134 | View.OnClickListener listener = new View.OnClickListener() { 135 | @Override 136 | public void onClick(View v) { 137 | if (v.equals(mRecButton)) { 138 | if (mHVTCamera.isRecording() && !mHVTCamera.isStartingRecording() && !mHVTCamera.isStoppingRecording()) { 139 | stopRecording(); 140 | } 141 | else if(mHVTCamera.isRunningIdle()) { 142 | startRecording(); 143 | mRecButton.setText("Stop"); 144 | } 145 | } 146 | else if(v.equals(mPhotoButton)) { 147 | // We take either a full resolution photo or a video snapshot, depensing on the 148 | // the current state. 149 | if (mHVTCamera.isRunningIdle()) { 150 | mHVTCamera.capturePhoto(mPhotoFile); 151 | } 152 | if (mHVTCamera.isRecording() && !mHVTCamera.isStoppingRecording()) { 153 | mHVTCamera.captureSnapshot(mPhotoFile); 154 | } 155 | } 156 | else if(v.equals(mCropButton)) { 157 | changeCropMode(); 158 | } 159 | else if(v.equals(mFlipCameraButton)) { 160 | if (mHVTCamera.isRunningIdle()) { 161 | flipCamera(); 162 | } 163 | } 164 | else if (v.equals(mFlashCameraButton)) { 165 | if (mHVTCamera.isRunning()) { 166 | toggleFlash(); 167 | } 168 | } 169 | } 170 | }; 171 | 172 | mRecButton.setOnClickListener(listener); 173 | mPhotoButton.setOnClickListener(listener); 174 | mCropButton.setOnClickListener(listener); 175 | mFlipCameraButton.setOnClickListener(listener); 176 | mFlashCameraButton.setOnClickListener(listener); 177 | 178 | if (mCameraHelper.getNumberOfCameras() == 1) { 179 | mFlipCameraButton.setVisibility(View.INVISIBLE); 180 | } 181 | 182 | int facing = mHVTCamera.getCameraFacing(); 183 | if (!supportsTorchMode(mCameraHelper.getSupportedFlashModes(facing))) { 184 | mFlashCameraButton.setVisibility(View.INVISIBLE); 185 | } 186 | } 187 | 188 | private static boolean supportsTorchMode(List flashModes) { 189 | if (flashModes == null) { 190 | return false; 191 | } 192 | return flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH); 193 | } 194 | 195 | private void rotateUI(int degrees) { 196 | mRecButton.setRotation(degrees); 197 | mPhotoButton.setRotation(degrees); 198 | mCropButton.setRotation(degrees); 199 | mFlipCameraButton.setRotation(degrees); 200 | mFlashCameraButton.setRotation(degrees); 201 | } 202 | 203 | private void startRecording() { 204 | // We create a recording profile for the current camera resolution. We could also change some of 205 | // the properties, such as the bitrate and audio settings. 206 | Size size = mHVTCamera.getOutputMovieSize(); 207 | HVTCamcorderProfile recordingProfile = new HVTCamcorderProfile(size.getWidth(), size.getHeight()); 208 | mHVTCamera.startRecording(mVideoFile, recordingProfile); 209 | } 210 | 211 | private void stopRecording() { 212 | // We request to stop recording. The actual recording completion may take a while. 213 | mHVTCamera.stopRecording(); 214 | } 215 | 216 | private void flipCamera() { 217 | int newCameraFacing = (mHVTCamera.getCameraFacing() == Camera.CameraInfo.CAMERA_FACING_BACK) ? 218 | Camera.CameraInfo.CAMERA_FACING_FRONT : Camera.CameraInfo.CAMERA_FACING_BACK; 219 | Size[] sizes = mCameraHelper.getDefaultVideoAndPhotoSize(newCameraFacing); 220 | // We request the other camera. This will result in closing the current camera and opening 221 | // the other. We will notified of the time the camera actually opened, using the callback. 222 | mHVTCamera.setCamera(newCameraFacing, sizes[0], sizes[1]); 223 | } 224 | 225 | private void toggleFlash() { 226 | String flashMode = mHVTCamera.getFlashMode(); 227 | flashMode = (flashMode.equals(Camera.Parameters.FLASH_MODE_TORCH)) ? 228 | Camera.Parameters.FLASH_MODE_OFF : Camera.Parameters.FLASH_MODE_TORCH; 229 | mHVTCamera.setFlashMode(flashMode); 230 | 231 | if (flashMode.equals(Camera.Parameters.FLASH_MODE_TORCH)) { 232 | mFlashCameraButton.setText("Flash on"); 233 | } else { 234 | mFlashCameraButton.setText("Flash off"); 235 | } 236 | } 237 | 238 | private void changeCropMode() { 239 | String text; 240 | HVTLevelerCropMode mode = mHVTCamera.getLevelerCropMode(); 241 | if (mode == HVTLevelerCropMode.FLEX) { 242 | mode = HVTLevelerCropMode.ROTATE; 243 | text = "Rotate"; 244 | } else if (mode == HVTLevelerCropMode.ROTATE) { 245 | mode = HVTLevelerCropMode.LOCKED; 246 | text = "Locked"; 247 | } else { 248 | mode = HVTLevelerCropMode.FLEX; 249 | text = "Flex"; 250 | } 251 | Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 252 | mHVTCamera.setLevelerCropMode(mode); 253 | } 254 | 255 | //region Permission handling 256 | 257 | public static String[] getNotGrantedPermissions(Context context, String[] permissions) { 258 | List notGrandedpermissions = new ArrayList<>(); 259 | for (String permission: permissions) { 260 | if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { 261 | notGrandedpermissions.add(permission); 262 | } 263 | } 264 | return notGrandedpermissions.toArray(new String[notGrandedpermissions.size()]); 265 | } 266 | 267 | public static boolean shouldShowRequestPermissionRationale(Activity activity, 268 | String[] permissions) { 269 | for (String permission: permissions) { 270 | if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) { 271 | return true; 272 | } 273 | } 274 | return false; 275 | } 276 | 277 | private void checkPermission() { 278 | final String[] notGrandedPermisions = getNotGrantedPermissions(this, PERMISSIONS); 279 | if (notGrandedPermisions.length != 0) { 280 | mHasPermission = false; 281 | // Should we show an explanation? 282 | if (shouldShowRequestPermissionRationale(this, notGrandedPermisions)) { 283 | // Show an explnation to the user *asynchronously* -- don't block 284 | // this thread waiting for the user's response! After the user 285 | // sees the explanation, try again to request the permission. 286 | ActivityCompat.requestPermissions(this, 287 | notGrandedPermisions, 288 | PERMISSIONS_REQ_CODE); 289 | 290 | } else { 291 | // No explanation needed, we can request the permission. 292 | ActivityCompat.requestPermissions(this, 293 | notGrandedPermisions, 294 | PERMISSIONS_REQ_CODE); 295 | } 296 | } 297 | else { 298 | // We've already got permission 299 | mHasPermission = true; 300 | onCreatePermissionGranted(); 301 | } 302 | } 303 | 304 | @Override 305 | public void onRequestPermissionsResult(int requestCode, 306 | String permissions[], int[] grantResults) { 307 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 308 | if (requestCode == PERMISSIONS_REQ_CODE) { 309 | boolean fail = false; 310 | if (grantResults.length == permissions.length) { 311 | for (int result : grantResults) { 312 | if (result != PackageManager.PERMISSION_GRANTED) { 313 | fail = true; 314 | break; 315 | } 316 | } 317 | } else { 318 | fail = true; 319 | } 320 | if (!fail) { 321 | mHasPermission = true; 322 | onCreatePermissionGranted(); 323 | } 324 | } 325 | } 326 | 327 | //endregion 328 | 329 | //region Activity Lifecycle 330 | 331 | @Override 332 | protected void onResume() { 333 | super.onResume(); 334 | 335 | if (mHasPermission) { 336 | mHVTCamera.startRunning(); 337 | } 338 | } 339 | 340 | @Override 341 | protected void onPause() { 342 | super.onPause(); 343 | 344 | if (mHasPermission) { 345 | mHVTCamera.stopRunning(); 346 | } 347 | } 348 | 349 | @Override 350 | protected void onDestroy() { 351 | super.onDestroy(); 352 | 353 | mHVTCamera.destroy(); 354 | mHVTCamera = null; 355 | } 356 | 357 | /* If the activity can change orientation, we need to update HVTCamera so that the preview is 358 | * rendered correctly. 359 | */ 360 | //TODO: This callback will not be called when switching from landscape to reverseLandscape and 361 | // vice versa. We should poll screen rotation for changes, if we want to account for that. 362 | @Override 363 | public void onConfigurationChanged(Configuration newConfig) { 364 | super.onConfigurationChanged(newConfig); 365 | 366 | if (mHVTCamera != null) { 367 | int screenRotation = getWindowManager().getDefaultDisplay().getRotation(); 368 | mHVTCamera.setScreenRotation(screenRotation); 369 | } 370 | } 371 | 372 | //endregion 373 | 374 | //region HVTCamera Listener 375 | private class MyListener implements HVTCameraListener { 376 | 377 | @Override 378 | public void onFailedToStart() { 379 | Toast.makeText(MainActivity.this, "Camera could not open. Try again later.", Toast.LENGTH_SHORT).show(); 380 | } 381 | 382 | @Override 383 | public void onStartedRunning(Camera.Parameters parameters, int i) { 384 | 385 | } 386 | 387 | @Override 388 | public void onPreviewHasBeenRunning(Camera.Parameters parameters, int i) { 389 | if (!supportsTorchMode(CameraHelper.getSupportedFlashModes(parameters))) { 390 | mFlashCameraButton.setVisibility(View.INVISIBLE); 391 | } 392 | else { 393 | mFlashCameraButton.setVisibility(View.VISIBLE); 394 | } 395 | } 396 | 397 | @Override 398 | public void onWillStopRunning() { 399 | 400 | } 401 | 402 | @Override 403 | public void onStoppedRunning() { 404 | 405 | } 406 | 407 | @Override 408 | public void onRecordingHasStarted() { 409 | 410 | } 411 | 412 | @Override 413 | public void onRecordingWillStop() { 414 | 415 | } 416 | 417 | @Override 418 | public void onRecordingFinished(File file, boolean success) { 419 | if (success) { 420 | Toast.makeText(MainActivity.this, "Recording finished", Toast.LENGTH_SHORT).show(); 421 | // Make the media visible to other apps 422 | MediaScannerConnection.scanFile(MainActivity.this, new String[]{file.getAbsolutePath()}, null, null); 423 | } 424 | else { 425 | Toast.makeText(MainActivity.this, "Error saving video", Toast.LENGTH_SHORT).show(); 426 | } 427 | mRecButton.setText("Rec"); 428 | } 429 | 430 | @Override 431 | public void onRecordedDataIncreased(long l, long l1) { 432 | 433 | } 434 | 435 | @Override 436 | public void onPhotoCaptured(File file, boolean success) { 437 | if (success) { 438 | Toast.makeText(MainActivity.this, "Photo captured", Toast.LENGTH_SHORT).show(); 439 | // Make the media visible to other apps 440 | MediaScannerConnection.scanFile(MainActivity.this, new String[]{file.getAbsolutePath()}, null, null); 441 | } 442 | else { 443 | Toast.makeText(MainActivity.this, "Error saving photo", Toast.LENGTH_SHORT).show(); 444 | } 445 | } 446 | 447 | @Override 448 | public void onSnapshotCaptured(File file) { 449 | Toast.makeText(MainActivity.this, "Snapshot captured", Toast.LENGTH_SHORT).show(); 450 | // Make the media visible to other apps 451 | MediaScannerConnection.scanFile(MainActivity.this, new String[]{file.getAbsolutePath()}, null, null); 452 | } 453 | 454 | @Override 455 | public void onAngleUpdated(float angle, float scale) { 456 | rotateUI((int) angle); 457 | } 458 | 459 | @Override 460 | public void onSensorNotResponding() { 461 | Toast.makeText(MainActivity.this, "Motion sensor not responding. Try again later.", Toast.LENGTH_SHORT).show(); 462 | } 463 | 464 | @Override 465 | public void onSensorResponded() { 466 | 467 | } 468 | } 469 | 470 | //endregion 471 | } 472 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/java/com/hvt/petrakeas/simpleapp/SimpleApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016. Horizon Video Technologies. All rights reserved. 3 | */ 4 | 5 | package com.hvt.petrakeas.simpleapp; 6 | 7 | import android.app.Application; 8 | 9 | import com.hvt.horizonSDK.HorizonSDK; 10 | 11 | public class SimpleApp extends Application { 12 | 13 | // You need to contact us to get a development or a purchased key for your app 14 | private static final String APIKey = "m8W7J+sSoGogrwibc/TCXX/M8h9XOFozFIQ1r03zhOmpOK9Bcfde8jUrEXthYmPfHn434/WNyjfF82i0Nv5cCmNvbS5odnQucGV0cmFrZWFzLnNpbXBsZWFwcHxOT3xhbmRyb2lk"; 15 | 16 | @Override 17 | public void onCreate() { 18 | super.onCreate(); 19 | HorizonSDK.init(getApplicationContext(), APIKey); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 30 | 31 | 40 | 41 | 42 | 50 | 51 | 59 | 60 | 61 | 62 | 72 | 73 | 81 | 82 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HorizonCamera/HorizonSDK-Android/83b69ee61f6f6f6d321dde3eb2842a499b0b22e1/Examples/HorizonSDKDemo/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HorizonCamera/HorizonSDK-Android/83b69ee61f6f6f6d321dde3eb2842a499b0b22e1/Examples/HorizonSDKDemo/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HorizonCamera/HorizonSDK-Android/83b69ee61f6f6f6d321dde3eb2842a499b0b22e1/Examples/HorizonSDKDemo/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HorizonCamera/HorizonSDK-Android/83b69ee61f6f6f6d321dde3eb2842a499b0b22e1/Examples/HorizonSDKDemo/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HorizonCamera/HorizonSDK-Android/83b69ee61f6f6f6d321dde3eb2842a499b0b22e1/Examples/HorizonSDKDemo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/values/horizon_sdk_customization.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | @drawable/horizonsdk_watermark 4 | 3.0 5 | 0.75 6 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Simple Camera 3 | 4 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | google() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.4.2' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | jcenter() 19 | 20 | flatDir { 21 | dirs "${rootDir}/libs" 22 | } 23 | google() 24 | } 25 | 26 | } 27 | 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | android.enableJetifier=true 20 | android.useAndroidX=true -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HorizonCamera/HorizonSDK-Android/83b69ee61f6f6f6d321dde3eb2842a499b0b22e1/Examples/HorizonSDKDemo/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jun 26 13:14:37 EEST 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/libs/horizonsdk.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HorizonCamera/HorizonSDK-Android/83b69ee61f6f6f6d321dde3eb2842a499b0b22e1/Examples/HorizonSDKDemo/libs/horizonsdk.aar -------------------------------------------------------------------------------- /Examples/HorizonSDKDemo/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /HorizonSDK/horizonsdk.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HorizonCamera/HorizonSDK-Android/83b69ee61f6f6f6d321dde3eb2842a499b0b22e1/HorizonSDK/horizonsdk.aar -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Developer's use of the SDK is governed by the license in the applicable Horizon SDK Terms of Service at: https://horizon.camera/sdk/tos/ 2 | 3 | Open source software licenses for components of Horizon SDK released under an open source license constitute separate written agreements. 4 | 5 | To the limited extent that the open source software licenses expressly supersede these Terms, the open source licenses govern your agreement with Horizon Video Technologies for the use of the components of Horizon SDK released under an open source license. 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Horizon SDK for Android ======================= ![Horizon logo](/docs/assets/images/horizonsdk-logo.png) Horizon SDK is a state of the art real-time video recording / photo shooting Android library. Some of the features of Horizon SDK include: * Horizon real-time leveling algorithm (you can find more at [https://horizon.camera](https://horizon.camera)) * Support for multiple resolutions * Hardware accelerated * Small footprint library file: less than 300 kb In order to use Horizon SDK on your app, you have to receive your API key by [contacting us](https://horizon.camera/sdk/). The provided sample app contains its own API key. The library can be used on devices running Android 4.4 (API 19) or higher. For more information take a look at the Installation and Quick Start guides of the [documentation](https://horizoncamera.github.io/HorizonSDK-Android/). Sample app -------- There is one Android Studio project in the examples directory, which makes use of most of the SDK features: * creates a preview view * adjusts the UI elements according to the physical device orientation * starts and stop the preview * captures photos and records videos You need the latest Android Studio to build the project. -------------------------------------------------------------------------------- /docs/assets/customizations.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Roboto:400,700); 2 | 3 | body { 4 | background: none; 5 | font: 14px/24px "Roboto",sans-serif; 6 | } 7 | a, a:visited { 8 | color: #08c; 9 | } 10 | .ui-resizable-s, 11 | .ui-resizable-e { 12 | background: #f5f5f5; 13 | } 14 | #header { 15 | border-bottom: none; 16 | box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.07); 17 | } 18 | #headerRight { 19 | right: 10px; 20 | top: 8px; 21 | } 22 | #masthead-title { 23 | color: #f80; 24 | font-weight: bold; 25 | } 26 | #swapper { 27 | border-bottom: 1px solid #f5f5f5 !important; 28 | } 29 | #search { 30 | margin: 0; 31 | } 32 | #search table { 33 | border: 1px solid #ddd; 34 | } 35 | #search table.gsc-search-box { 36 | margin: 0; 37 | } 38 | #search input.gsc-input { 39 | border: none; 40 | padding: 5px 2px; 41 | } 42 | #search input.gsc-search-button { 43 | display: block; 44 | padding: 6px 2px; 45 | border: 1px solid transparent; 46 | background: #f80; 47 | cursor: pointer; 48 | text-transform: uppercase; 49 | color: #fff; 50 | } 51 | #nav-swap { 52 | color: #666; 53 | bottom: 0; 54 | } 55 | h4.jd-details-title { 56 | background-color: #f2f2f2; 57 | } 58 | #search_filtered .jd-selected { 59 | background-color: #0767a4; 60 | } 61 | #jd-header { 62 | background: transparent; 63 | } 64 | #side-nav { 65 | font-size: inherit; 66 | } 67 | #side-nav .selected { 68 | color: #fff; 69 | background-color: #f80; 70 | } 71 | #index-links a { 72 | text-decoration: none; 73 | } 74 | #index-links .selected { 75 | padding: 2px 5px; 76 | } 77 | #side-nav li h2 { 78 | font-size: 18px; 79 | } 80 | #side-nav li { 81 | padding: 5px 0; 82 | } 83 | h4.jd-details-title { 84 | background-color: 85 | } 86 | #jd-content h2 { 87 | border-top: 1px solid #ccc; 88 | } -------------------------------------------------------------------------------- /docs/assets/customizations.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HorizonCamera/HorizonSDK-Android/83b69ee61f6f6f6d321dde3eb2842a499b0b22e1/docs/assets/customizations.js -------------------------------------------------------------------------------- /docs/assets/doclava-developer-core.css: -------------------------------------------------------------------------------- 1 | /* file: doclava-developer-core.css 2 | info: core developer styles 3 | */ 4 | 5 | /* RESET STYLES */ 6 | 7 | html,body,div,h1,h2,h3,h4,h5,h6,p,img, 8 | dl,dt,dd,ol,ul,li,table,caption,tbody, 9 | tfoot,thead,tr,th,td,form,fieldset, 10 | embed,object,applet { 11 | margin: 0; 12 | padding: 0; 13 | border: 0; 14 | } 15 | 16 | /* BASICS */ 17 | 18 | html, body { 19 | overflow:hidden; /* keeps scrollbar off IE */ 20 | background-color:#fff; 21 | } 22 | 23 | body { 24 | font-family:arial,sans-serif; 25 | color:#000; 26 | font-size:13px; 27 | color:#333; 28 | background-image:url(images/bg_fade.jpg); 29 | background-repeat:repeat-x; 30 | } 31 | 32 | a, a code { 33 | color:#006699; 34 | } 35 | 36 | a:active, 37 | a:active code { 38 | color:#f00; 39 | } 40 | 41 | a:visited, 42 | a:visited code { 43 | color:#006699; 44 | } 45 | 46 | input, select, 47 | textarea, option, label { 48 | font-family:inherit; 49 | font-size:inherit; 50 | padding:0; 51 | margin:0; 52 | vertical-align:middle; 53 | } 54 | 55 | option { 56 | padding:0 4px; 57 | } 58 | 59 | p { 60 | padding:0; 61 | margin:0 0 1em; 62 | } 63 | 64 | code, pre { 65 | color:#007000; 66 | font-family:monospace; 67 | line-height:1em; 68 | } 69 | 70 | var { 71 | color:#007000; 72 | font-style:italic; 73 | } 74 | 75 | pre { 76 | border:1px solid #ccc; 77 | background-color:#fafafa; 78 | padding:10px; 79 | margin:0 0 1em 1em; 80 | overflow:auto; 81 | line-height:inherit; /* fixes vertical scrolling in webkit */ 82 | } 83 | 84 | h1,h2,h3,h4,h5 { 85 | margin:1em 0; 86 | padding:0; 87 | } 88 | 89 | p,ul,ol,dl,dd,dt,li { 90 | line-height:1.3em; 91 | } 92 | 93 | ul,ol { 94 | margin:0 0 .8em; 95 | padding:0 0 0 2em; 96 | } 97 | 98 | li { 99 | padding:0 0 .5em; 100 | } 101 | 102 | dl { 103 | margin:0 0 1em 0; 104 | padding:0; 105 | } 106 | 107 | dt { 108 | margin:0; 109 | padding:0; 110 | } 111 | 112 | dd { 113 | margin:0 0 1em; 114 | padding:0 0 0 2em; 115 | } 116 | 117 | li p { 118 | margin:.5em 0 0; 119 | } 120 | 121 | dd p { 122 | margin:1em 0 0; 123 | } 124 | 125 | li pre, li table, li img { 126 | margin:.5em 0 0 1em; 127 | } 128 | 129 | dd pre, 130 | #jd-content dd table, 131 | #jd-content dd img { 132 | margin:1em 0 0 1em; 133 | } 134 | 135 | li ul, 136 | li ol, 137 | dd ul, 138 | dd ol { 139 | margin:0; 140 | padding: 0 0 0 2em; 141 | } 142 | 143 | li li, 144 | dd li { 145 | margin:0; 146 | padding:.5em 0 0; 147 | } 148 | 149 | dl dl, 150 | ol dl, 151 | ul dl { 152 | margin:0 0 1em; 153 | padding:0; 154 | } 155 | 156 | table { 157 | font-size:1em; 158 | margin:0 0 1em; 159 | padding:0; 160 | border-collapse:collapse; 161 | border-width:0; 162 | empty-cells:show; 163 | } 164 | 165 | td,th { 166 | border:1px solid #ccc; 167 | padding:6px 12px; 168 | text-align:left; 169 | vertical-align:top; 170 | background-color:inherit; 171 | } 172 | 173 | th { 174 | background-color:#dee8f1; 175 | } 176 | 177 | td > p:last-child { 178 | margin:0; 179 | } 180 | 181 | hr.blue { 182 | background-color:#DDF0F2; 183 | border:none; 184 | height:5px; 185 | margin:20px 0 10px; 186 | } 187 | 188 | blockquote { 189 | margin: 0 0 1em 1em; 190 | padding: 0 4em 0 1em; 191 | border-left:2px solid #eee; 192 | } 193 | /* LAYOUT */ 194 | 195 | #body-content { 196 | /* "Preliminary" watermark for draft documentation. 197 | background:transparent url(images/preliminary.png) repeat scroll 0 0; */ 198 | margin:0; 199 | position:relative; 200 | width:100%; 201 | } 202 | 203 | #header { 204 | height: 44px; 205 | position:relative; 206 | z-index:100; 207 | min-width:675px; /* min width for the tabs, before they wrap */ 208 | padding:0 10px; 209 | border-bottom:3px solid #94b922; 210 | } 211 | 212 | #headerLeft{ 213 | position:absolute; 214 | padding: 10px 0 0; 215 | left:8px; 216 | bottom:3px; 217 | } 218 | 219 | #headerRight { 220 | position:absolute; 221 | right:0; 222 | bottom:3px; 223 | padding:0; 224 | text-align:right; 225 | } 226 | 227 | #masthead-title { 228 | font-size:28px; 229 | color: #2f74ae; 230 | } 231 | 232 | /* Tabs in the header */ 233 | 234 | #header ul { 235 | list-style: none; 236 | margin: 7px 0 0; 237 | padding: 0; 238 | height: 29px; 239 | } 240 | 241 | #header li { 242 | float: left; 243 | margin: 0px 2px 0px 0px; 244 | padding:0; 245 | } 246 | 247 | #header li a { 248 | text-decoration: none; 249 | display: block; 250 | background-image: url(images/bg_images_sprite.png); 251 | background-position: 0 -58px; 252 | background-repeat: no-repeat; 253 | color: #666; 254 | font-size: 13px; 255 | font-weight: bold; 256 | width: 94px; 257 | height: 29px; 258 | text-align: center; 259 | margin: 0px; 260 | } 261 | 262 | #header li a:hover { 263 | background-image: url(images/bg_images_sprite.png); 264 | background-position: 0 -29px; 265 | background-repeat: no-repeat; 266 | } 267 | 268 | #header li a span { 269 | position:relative; 270 | top:7px; 271 | } 272 | 273 | #header li a span+span { 274 | display:none; 275 | } 276 | 277 | /* tab highlighting */ 278 | 279 | .home #home-link a, 280 | .guide #guide-link a, 281 | .reference #reference-link a, 282 | .sdk #sdk-link a, 283 | .resources #resources-link a, 284 | .videos #videos-link a { 285 | background-image: url(images/bg_images_sprite.png); 286 | background-position: 0 0; 287 | background-repeat: no-repeat; 288 | color: #fff; 289 | font-weight: bold; 290 | cursor:default; 291 | } 292 | 293 | .home #home-link a:hover, 294 | .guide #guide-link a:hover, 295 | .reference #reference-link a:hover, 296 | .sdk #sdk-link a:hover, 297 | .resources #resources-link a:hover, 298 | .videos #videos-link a:hover { 299 | background-image: url(images/bg_images_sprite.png); 300 | background-position: 0 0; 301 | } 302 | 303 | #headerLinks { 304 | margin:10px 10px 0 0; 305 | height:13px; 306 | font-size: 11px; 307 | vertical-align: top; 308 | } 309 | 310 | #headerLinks a { 311 | color: #7FA9B5; 312 | } 313 | 314 | #headerLinks img { 315 | vertical-align:middle; 316 | } 317 | 318 | #language { 319 | margin:0 10px 0 4px; 320 | } 321 | 322 | #search { 323 | margin:8px 10px 0 0; 324 | } 325 | 326 | /* MAIN BODY */ 327 | 328 | #mainBodyFluid { 329 | margin: 20px 10px; 330 | color:#333; 331 | } 332 | 333 | #mainBodyFixed { 334 | margin: 20px 10px; 335 | color: #333; 336 | width:930px; 337 | position:relative; 338 | } 339 | 340 | #mainBodyFixed h3, 341 | #mainBodyFluid h3 { 342 | color:#336666; 343 | font-size:1.25em; 344 | margin: 0em 0em 0em 0em; 345 | padding-bottom:.5em; 346 | } 347 | 348 | #mainBodyFixed h2, 349 | #mainBodyFluid h2 { 350 | color:#336666; 351 | font-size:1.25em; 352 | margin: 0; 353 | padding-bottom:.5em; 354 | } 355 | 356 | #mainBodyFixed h1, 357 | #mainBodyFluid h1 { 358 | color:#435A6E; 359 | font-size:1.7em; 360 | margin: 1em 0; 361 | } 362 | 363 | #mainBodyFixed .green, 364 | #mainBodyFluid .green, 365 | #jd-content .green { 366 | color:#7BB026; 367 | background-color:none; 368 | } 369 | 370 | #mainBodyLeft { 371 | float: left; 372 | width: 600px; 373 | margin-right: 20px; 374 | color: #333; 375 | position:relative; 376 | } 377 | 378 | div.indent { 379 | margin-left: 40px; 380 | margin-right: 70px; 381 | } 382 | 383 | #mainBodyLeft p { 384 | color: #333; 385 | font-size: 13px; 386 | } 387 | 388 | #mainBodyLeft p.blue { 389 | color: #669999; 390 | } 391 | 392 | #mainBodyLeft #communityDiv { 393 | float: left; 394 | background-image:url(images/bg_community_leftDiv.jpg); 395 | background-repeat: no-repeat; 396 | width: 581px; 397 | height: 347px; 398 | padding: 20px 0px 0px 20px; 399 | } 400 | 401 | #mainBodyRight { 402 | float: left; 403 | width: 300px; 404 | color: #333; 405 | } 406 | 407 | #mainBodyRight p { 408 | padding-right: 50px; 409 | color: #333; 410 | } 411 | 412 | #mainBodyRight table { 413 | width: 100%; 414 | } 415 | 416 | #mainBodyRight td { 417 | border:0px solid #666; 418 | padding:0px 5px; 419 | text-align:left; 420 | } 421 | 422 | #mainBodyRight td p { 423 | margin:0 0 1em 0; 424 | } 425 | 426 | #mainBodyRight .blueBorderBox { 427 | border:5px solid #ddf0f2; 428 | padding:18px 18px 18px 18px; 429 | text-align:left; 430 | } 431 | 432 | #mainBodyFixed .seperator { 433 | background-image:url(images/hr_gray_side.jpg); 434 | background-repeat:no-repeat; 435 | width: 100%; 436 | float: left; 437 | clear: both; 438 | } 439 | 440 | #mainBodyBottom { 441 | float: left; 442 | width: 100%; 443 | clear:both; 444 | color: #333; 445 | } 446 | 447 | #mainBodyBottom .seperator { 448 | background-image:url(images/hr_gray_main.jpg); 449 | background-repeat:no-repeat; 450 | width: 100%; 451 | float: left; 452 | clear: both; 453 | } 454 | 455 | /* FOOTER */ 456 | 457 | #footer { 458 | float: left; 459 | width:90%; 460 | margin: 20px; 461 | color: #aaa; 462 | font-size: 11px; 463 | } 464 | 465 | #footer a { 466 | color: #aaa; 467 | font-size: 11px; 468 | } 469 | 470 | #footer a:hover { 471 | text-decoration: underline; 472 | color:#aaa; 473 | } 474 | 475 | #footerlinks { 476 | margin-top:2px; 477 | } 478 | 479 | #footerlinks a, 480 | #footerlinks a:visited { 481 | color:#006699; 482 | } 483 | 484 | /* SEARCH FILTER */ 485 | 486 | #search_autocomplete { 487 | color:#aaa; 488 | } 489 | 490 | #search-button { 491 | display:inline; 492 | } 493 | 494 | #search_filtered_div { 495 | position:absolute; 496 | margin-top:-1px; 497 | z-index:101; 498 | border:1px solid #BCCDF0; 499 | background-color:#fff; 500 | } 501 | 502 | #search_filtered { 503 | min-width:100%; 504 | } 505 | #search_filtered td{ 506 | background-color:#fff; 507 | border-bottom: 1px solid #669999; 508 | line-height:1.5em; 509 | } 510 | 511 | #search_filtered .jd-selected { 512 | background-color: #94b922; 513 | cursor:pointer; 514 | } 515 | #search_filtered .jd-selected, 516 | #search_filtered .jd-selected a { 517 | color:#fff; 518 | } 519 | 520 | .no-display { 521 | display: none; 522 | } 523 | 524 | .jd-autocomplete { 525 | font-family: Arial, sans-serif; 526 | padding-left: 6px; 527 | padding-right: 6px; 528 | padding-top: 1px; 529 | padding-bottom: 1px; 530 | font-size: 0.81em; 531 | border: none; 532 | margin: 0; 533 | line-height: 1.05em; 534 | } 535 | 536 | .show-row { 537 | display: table-row; 538 | } 539 | .hide-row { 540 | display: hidden; 541 | } 542 | 543 | /* SEARCH */ 544 | 545 | /* restrict global search form width */ 546 | #searchForm { 547 | width:350px; 548 | } 549 | 550 | #searchTxt { 551 | width:200px; 552 | } 553 | 554 | /* disable twiddle and size selectors for left column */ 555 | #leftSearchControl div { 556 | width: 100%; 557 | } 558 | 559 | #leftSearchControl .gsc-twiddle { 560 | background-image : none; 561 | } 562 | 563 | #leftSearchControl td, #searchForm td { 564 | border: 0px solid #000; 565 | } 566 | 567 | #leftSearchControl .gsc-resultsHeader .gsc-title { 568 | padding-left : 0px; 569 | font-weight : bold; 570 | font-size : 13px; 571 | color:#006699; 572 | display : none; 573 | } 574 | 575 | #leftSearchControl .gsc-resultsHeader div.gsc-results-selector { 576 | display : none; 577 | } 578 | 579 | #leftSearchControl .gsc-resultsRoot { 580 | padding-top : 6px; 581 | } 582 | 583 | #leftSearchControl div.gs-visibleUrl-long { 584 | display : block; 585 | color:#006699; 586 | } 587 | 588 | .gsc-webResult div.gs-visibleUrl-short, 589 | table.gsc-branding, 590 | .gsc-clear-button { 591 | display : none; 592 | } 593 | 594 | .gsc-cursor-box .gsc-cursor div.gsc-cursor-page, 595 | .gsc-cursor-box .gsc-trailing-more-results a.gsc-trailing-more-results, 596 | #leftSearchControl a, 597 | #leftSearchControl a b { 598 | color:#006699; 599 | } 600 | 601 | .gsc-resultsHeader { 602 | display: none; 603 | } 604 | 605 | /* Disable built in search forms */ 606 | .gsc-control form.gsc-search-box { 607 | display : none; 608 | } 609 | table.gsc-search-box { 610 | margin:6px 0 0 0; 611 | border-collapse:collapse; 612 | } 613 | 614 | td.gsc-input { 615 | padding:0 2px; 616 | width:100%; 617 | vertical-align:middle; 618 | } 619 | 620 | input.gsc-input { 621 | border:1px solid #BCCDF0; 622 | width:99%; 623 | padding-left:2px; 624 | font-size:.95em; 625 | } 626 | 627 | td.gsc-search-button { 628 | text-align: right; 629 | padding:0; 630 | vertical-align:top; 631 | } 632 | 633 | #search-button { 634 | margin:0 0 0 2px; 635 | font-size:11px; 636 | } 637 | 638 | /* search result tabs */ 639 | 640 | #doc-content .gsc-control { 641 | position:relative; 642 | } 643 | 644 | #doc-content .gsc-tabsArea { 645 | position:relative; 646 | white-space:nowrap; 647 | } 648 | 649 | #doc-content .gsc-tabHeader { 650 | padding: 3px 6px; 651 | position:relative; 652 | } 653 | 654 | #doc-content .gsc-tabHeader.gsc-tabhActive { 655 | border-top: 2px solid #94B922; 656 | } 657 | 658 | #doc-content h2#searchTitle { 659 | padding:0; 660 | } 661 | 662 | #doc-content .gsc-resultsbox-visible { 663 | padding:1em 0 0 6px; 664 | } 665 | 666 | /* Pretty printing styles. Used with prettify.js. */ 667 | 668 | .str { color: #080; } 669 | .kwd { color: #008; } 670 | .com { color: #800; } 671 | .typ { color: #606; } 672 | .lit { color: #066; } 673 | .pun { color: #660; } 674 | .pln { color: #000; } 675 | dl.tag-list dt code, 676 | .tag { color: #008; } 677 | dl.atn-list dt code, 678 | .atn { color: #828; } 679 | .atv { color: #080; } 680 | .dec { color: #606; } 681 | 682 | @media print { 683 | .str { color: #060; } 684 | .kwd { color: #006; font-weight: bold; } 685 | .com { color: #600; font-style: italic; } 686 | .typ { color: #404; font-weight: bold; } 687 | .lit { color: #044; } 688 | .pun { color: #440; } 689 | .pln { color: #000; } 690 | .tag { color: #006; font-weight: bold; } 691 | .atn { color: #404; } 692 | .atv { color: #060; } 693 | } -------------------------------------------------------------------------------- /docs/assets/doclava-developer-docs.js: -------------------------------------------------------------------------------- 1 | var resizePackagesNav; 2 | var classesNav; 3 | var devdocNav; 4 | var sidenav; 5 | var content; 6 | var HEADER_HEIGHT = -1; 7 | var cookie_namespace = 'doclava_developer'; 8 | var NAV_PREF_TREE = "tree"; 9 | var NAV_PREF_PANELS = "panels"; 10 | var nav_pref; 11 | var toRoot; 12 | var toAssets; 13 | var isMobile = false; // true if mobile, so we can adjust some layout 14 | var isIE6 = false; // true if IE6 15 | 16 | // TODO: use $(document).ready instead 17 | function addLoadEvent(newfun) { 18 | var current = window.onload; 19 | if (typeof window.onload != 'function') { 20 | window.onload = newfun; 21 | } else { 22 | window.onload = function() { 23 | current(); 24 | newfun(); 25 | } 26 | } 27 | } 28 | 29 | var agent = navigator['userAgent'].toLowerCase(); 30 | // If a mobile phone, set flag and do mobile setup 31 | if ((agent.indexOf("mobile") != -1) || // android, iphone, ipod 32 | (agent.indexOf("blackberry") != -1) || 33 | (agent.indexOf("webos") != -1) || 34 | (agent.indexOf("mini") != -1)) { // opera mini browsers 35 | isMobile = true; 36 | addLoadEvent(mobileSetup); 37 | // If not a mobile browser, set the onresize event for IE6, and others 38 | } else if (agent.indexOf("msie 6") != -1) { 39 | isIE6 = true; 40 | addLoadEvent(function() { 41 | window.onresize = resizeAll; 42 | }); 43 | } else { 44 | addLoadEvent(function() { 45 | window.onresize = resizeHeight; 46 | }); 47 | } 48 | 49 | function mobileSetup() { 50 | $("body").css({'overflow':'auto'}); 51 | $("html").css({'overflow':'auto'}); 52 | $("#body-content").css({'position':'relative', 'top':'0'}); 53 | $("#doc-content").css({'overflow':'visible', 'border-left':'3px solid #DDD'}); 54 | $("#side-nav").css({'padding':'0'}); 55 | $("#nav-tree").css({'overflow-y': 'auto'}); 56 | } 57 | 58 | /* loads the lists.js file to the page. 59 | Loading this in the head was slowing page load time */ 60 | addLoadEvent( function() { 61 | var lists = document.createElement("script"); 62 | lists.setAttribute("type","text/javascript"); 63 | lists.setAttribute("src", toRoot+"lists.js"); 64 | document.getElementsByTagName("head")[0].appendChild(lists); 65 | } ); 66 | 67 | addLoadEvent( function() { 68 | $("pre:not(.no-pretty-print)").addClass("prettyprint"); 69 | prettyPrint(); 70 | } ); 71 | 72 | function setToRoot(root, assets) { 73 | toRoot = root; 74 | toAssets = assets; 75 | // note: toRoot also used by carousel.js 76 | } 77 | 78 | function restoreWidth(navWidth) { 79 | var windowWidth = $(window).width() + "px"; 80 | content.css({marginLeft:parseInt(navWidth) + 6 + "px"}); //account for 6px-wide handle-bar 81 | 82 | if (isIE6) { 83 | content.css({width:parseInt(windowWidth) - parseInt(navWidth) - 6 + "px"}); // necessary in order for scrollbars to be visible 84 | } 85 | 86 | sidenav.css({width:navWidth}); 87 | resizePackagesNav.css({width:navWidth}); 88 | classesNav.css({width:navWidth}); 89 | $("#packages-nav").css({width:navWidth}); 90 | } 91 | 92 | function restoreHeight(packageHeight) { 93 | var windowHeight = ($(window).height() - HEADER_HEIGHT); 94 | var swapperHeight = windowHeight - 13; 95 | $("#swapper").css({height:swapperHeight + "px"}); 96 | sidenav.css({height:windowHeight + "px"}); 97 | content.css({height:windowHeight + "px"}); 98 | resizePackagesNav.css({maxHeight:swapperHeight + "px", height:packageHeight}); 99 | classesNav.css({height:swapperHeight - parseInt(packageHeight) + "px"}); 100 | $("#packages-nav").css({height:parseInt(packageHeight) - 6 + "px"}); //move 6px to give space for the resize handle 101 | devdocNav.css({height:sidenav.css("height")}); 102 | $("#nav-tree").css({height:swapperHeight + "px"}); 103 | } 104 | 105 | function readCookie(cookie) { 106 | var myCookie = cookie_namespace+"_"+cookie+"="; 107 | if (document.cookie) { 108 | var index = document.cookie.indexOf(myCookie); 109 | if (index != -1) { 110 | var valStart = index + myCookie.length; 111 | var valEnd = document.cookie.indexOf(";", valStart); 112 | if (valEnd == -1) { 113 | valEnd = document.cookie.length; 114 | } 115 | var val = document.cookie.substring(valStart, valEnd); 116 | return val; 117 | } 118 | } 119 | return 0; 120 | } 121 | 122 | function writeCookie(cookie, val, section, expiration) { 123 | if (val==undefined) return; 124 | section = section == null ? "_" : "_"+section+"_"; 125 | if (expiration == null) { 126 | var date = new Date(); 127 | date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week 128 | expiration = date.toGMTString(); 129 | } 130 | document.cookie = cookie_namespace + section + cookie + "=" + val + "; expires=" + expiration+"; path=/"; 131 | } 132 | 133 | function getSection() { 134 | if (location.href.indexOf("/reference/") != -1) { 135 | return "reference"; 136 | } else if (location.href.indexOf("/guide/") != -1) { 137 | return "guide"; 138 | } else if (location.href.indexOf("/resources/") != -1) { 139 | return "resources"; 140 | } 141 | var basePath = getBaseUri(location.pathname); 142 | return basePath.substring(1,basePath.indexOf("/",1)); 143 | } 144 | 145 | function init() { 146 | HEADER_HEIGHT = $("#header").height()+3; 147 | $("#side-nav").css({position:"absolute",left:0}); 148 | content = $("#doc-content"); 149 | resizePackagesNav = $("#resize-packages-nav"); 150 | classesNav = $("#classes-nav"); 151 | sidenav = $("#side-nav"); 152 | devdocNav = $("#devdoc-nav"); 153 | 154 | var cookiePath = getSection() + "_"; 155 | 156 | if (!isMobile) { 157 | $("#resize-packages-nav").resizable({handles: "s", resize: function(e, ui) { resizePackagesHeight(); } }); 158 | $(".side-nav-resizable").resizable({handles: "e", resize: function(e, ui) { resizeWidth(); } }); 159 | var cookieWidth = readCookie(cookiePath+'width'); 160 | var cookieHeight = readCookie(cookiePath+'height'); 161 | if (cookieWidth) { 162 | restoreWidth(cookieWidth); 163 | } else if ($(".side-nav-resizable").length) { 164 | resizeWidth(); 165 | } 166 | if (cookieHeight) { 167 | restoreHeight(cookieHeight); 168 | } else { 169 | resizeHeight(); 170 | } 171 | } 172 | 173 | if (devdocNav.length) { // only dev guide, resources, and sdk 174 | tryPopulateResourcesNav(); 175 | highlightNav(location.href); 176 | } 177 | } 178 | 179 | function highlightNav(fullPageName) { 180 | var lastSlashPos = fullPageName.lastIndexOf("/"); 181 | var firstSlashPos; 182 | if (fullPageName.indexOf("/guide/") != -1) { 183 | firstSlashPos = fullPageName.indexOf("/guide/"); 184 | } else if (fullPageName.indexOf("/sdk/") != -1) { 185 | firstSlashPos = fullPageName.indexOf("/sdk/"); 186 | } else { 187 | firstSlashPos = fullPageName.indexOf("/resources/"); 188 | } 189 | if (lastSlashPos == (fullPageName.length - 1)) { // if the url ends in slash (add 'index.html') 190 | fullPageName = fullPageName + "index.html"; 191 | } 192 | // First check if the exact URL, with query string and all, is in the navigation menu 193 | var pathPageName = fullPageName.substr(firstSlashPos); 194 | var link = $("#devdoc-nav a[href$='"+ pathPageName+"']"); 195 | if (link.length == 0) { 196 | var htmlPos = fullPageName.lastIndexOf(".html", fullPageName.length); 197 | pathPageName = fullPageName.slice(firstSlashPos, htmlPos + 5); // +5 advances past ".html" 198 | link = $("#devdoc-nav a[href$='"+ pathPageName+"']"); 199 | if ((link.length == 0) && ((fullPageName.indexOf("/guide/") != -1) || (fullPageName.indexOf("/resources/") != -1))) { 200 | // if there's no match, then let's backstep through the directory until we find an index.html page 201 | // that matches our ancestor directories (only for dev guide and resources) 202 | lastBackstep = pathPageName.lastIndexOf("/"); 203 | while (link.length == 0) { 204 | backstepDirectory = pathPageName.lastIndexOf("/", lastBackstep); 205 | link = $("#devdoc-nav a[href$='"+ pathPageName.slice(0, backstepDirectory + 1)+"index.html']"); 206 | lastBackstep = pathPageName.lastIndexOf("/", lastBackstep - 1); 207 | if (lastBackstep == 0) break; 208 | } 209 | } 210 | } 211 | 212 | // add 'selected' to the
  • or
    that wraps this 213 | link.parent().addClass('selected'); 214 | 215 | // if we're in a toggleable root link (
  • ) 216 | if (link.parent().parent().hasClass('toggle-list')) { 217 | toggle(link.parent().parent(), false); // open our own list 218 | // then also check if we're in a third-level nested list that's toggleable 219 | if (link.parent().parent().parent().is(':hidden')) { 220 | toggle(link.parent().parent().parent().parent(), false); // open the super parent list 221 | } 222 | } 223 | // if we're in a normal nav link (
  • ) and the parent
      is hidden 224 | else if (link.parent().parent().is(':hidden')) { 225 | toggle(link.parent().parent().parent(), false); // open the parent list 226 | // then also check if the parent list is also nested in a hidden list 227 | if (link.parent().parent().parent().parent().is(':hidden')) { 228 | toggle(link.parent().parent().parent().parent().parent(), false); // open the super parent list 229 | } 230 | } 231 | } 232 | 233 | /* Resize the height of the nav panels in the reference, 234 | * and save the new size to a cookie */ 235 | function resizePackagesHeight() { 236 | var windowHeight = ($(window).height() - HEADER_HEIGHT); 237 | var swapperHeight = windowHeight - 13; // move 13px for swapper link at the bottom 238 | resizePackagesNav.css({maxHeight:swapperHeight + "px"}); 239 | classesNav.css({height:swapperHeight - parseInt(resizePackagesNav.css("height")) + "px"}); 240 | 241 | $("#swapper").css({height:swapperHeight + "px"}); 242 | $("#packages-nav").css({height:parseInt(resizePackagesNav.css("height")) - 6 + "px"}); //move 6px for handle 243 | 244 | var section = getSection(); 245 | writeCookie("height", resizePackagesNav.css("height"), section, null); 246 | } 247 | 248 | /* Resize the height of the side-nav and doc-content divs, 249 | * which creates the frame effect */ 250 | function resizeHeight() { 251 | var docContent = $("#doc-content"); 252 | 253 | // Get the window height and always resize the doc-content and side-nav divs 254 | var windowHeight = ($(window).height() - HEADER_HEIGHT); 255 | docContent.css({height:windowHeight + "px"}); 256 | $("#side-nav").css({height:windowHeight + "px"}); 257 | 258 | var href = location.href; 259 | // If in the reference docs, also resize the "swapper", "classes-nav", and "nav-tree" divs 260 | if (href.indexOf("/reference/") != -1) { 261 | var swapperHeight = windowHeight - 13; 262 | $("#swapper").css({height:swapperHeight + "px"}); 263 | $("#classes-nav").css({height:swapperHeight - parseInt(resizePackagesNav.css("height")) + "px"}); 264 | $("#nav-tree").css({height:swapperHeight + "px"}); 265 | 266 | // If in the dev guide docs, also resize the "devdoc-nav" div 267 | } else if (href.indexOf("/guide/") != -1) { 268 | $("#devdoc-nav").css({height:sidenav.css("height")}); 269 | } else if (href.indexOf("/resources/") != -1) { 270 | $("#devdoc-nav").css({height:sidenav.css("height")}); 271 | } 272 | 273 | // Hide the "Go to top" link if there's no vertical scroll 274 | if ( parseInt($("#jd-content").css("height")) <= parseInt(docContent.css("height")) ) { 275 | $("a[href='#top']").css({'display':'none'}); 276 | } else { 277 | $("a[href='#top']").css({'display':'inline'}); 278 | } 279 | } 280 | 281 | /* Resize the width of the "side-nav" and the left margin of the "doc-content" div, 282 | * which creates the resizable side bar */ 283 | function resizeWidth() { 284 | var windowWidth = $(window).width() + "px"; 285 | if (sidenav.length) { 286 | var sidenavWidth = sidenav.css("width"); 287 | } else { 288 | var sidenavWidth = 0; 289 | } 290 | content.css({marginLeft:parseInt(sidenavWidth) + 6 + "px"}); //account for 6px-wide handle-bar 291 | 292 | if (isIE6) { 293 | content.css({width:parseInt(windowWidth) - parseInt(sidenavWidth) - 6 + "px"}); // necessary in order to for scrollbars to be visible 294 | } 295 | 296 | resizePackagesNav.css({width:sidenavWidth}); 297 | classesNav.css({width:sidenavWidth}); 298 | $("#packages-nav").css({width:sidenavWidth}); 299 | 300 | if ($(".side-nav-resizable").length) { // Must check if the nav is resizable because IE6 calls resizeWidth() from resizeAll() for all pages 301 | var section = getSection(); 302 | writeCookie("width", sidenavWidth, section, null); 303 | } 304 | } 305 | 306 | /* For IE6 only, 307 | * because it can't properly perform auto width for "doc-content" div, 308 | * avoiding this for all browsers provides better performance */ 309 | function resizeAll() { 310 | resizeHeight(); 311 | resizeWidth(); 312 | } 313 | 314 | function getBaseUri(uri) { 315 | var intlUrl = (uri.substring(0,6) == "/intl/"); 316 | if (intlUrl) { 317 | base = uri.substring(uri.indexOf('intl/')+5,uri.length); 318 | base = base.substring(base.indexOf('/')+1, base.length); 319 | //alert("intl, returning base url: /" + base); 320 | return ("/" + base); 321 | } else { 322 | //alert("not intl, returning uri as found."); 323 | return uri; 324 | } 325 | } 326 | 327 | function requestAppendHL(uri) { 328 | //append "?hl= to an outgoing request (such as to blog) 329 | var lang = getLangPref(); 330 | if (lang) { 331 | var q = 'hl=' + lang; 332 | uri += '?' + q; 333 | window.location = uri; 334 | return false; 335 | } else { 336 | return true; 337 | } 338 | } 339 | 340 | function loadLast(cookiePath) { 341 | var location = window.location.href; 342 | if (location.indexOf("/"+cookiePath+"/") != -1) { 343 | return true; 344 | } 345 | var lastPage = readCookie(cookiePath + "_lastpage"); 346 | if (lastPage) { 347 | window.location = lastPage; 348 | return false; 349 | } 350 | return true; 351 | } 352 | 353 | $(window).unload(function(){ 354 | var path = getBaseUri(location.pathname); 355 | if (path.indexOf("/reference/") != -1) { 356 | writeCookie("lastpage", path, "reference", null); 357 | } else if (path.indexOf("/guide/") != -1) { 358 | writeCookie("lastpage", path, "guide", null); 359 | } else if (path.indexOf("/resources/") != -1) { 360 | writeCookie("lastpage", path, "resources", null); 361 | } 362 | }); 363 | 364 | function toggle(obj, slide) { 365 | var ul = $("ul:first", obj); 366 | var li = ul.parent(); 367 | if (li.hasClass("closed")) { 368 | if (slide) { 369 | ul.slideDown("fast"); 370 | } else { 371 | ul.show(); 372 | } 373 | li.removeClass("closed"); 374 | li.addClass("open"); 375 | $(".toggle-img", li).attr("title", "hide pages"); 376 | } else { 377 | ul.slideUp("fast"); 378 | li.removeClass("open"); 379 | li.addClass("closed"); 380 | $(".toggle-img", li).attr("title", "show pages"); 381 | } 382 | } 383 | 384 | function buildToggleLists() { 385 | $(".toggle-list").each( 386 | function(i) { 387 | $("div:first", this).append(""); 388 | $(this).addClass("closed"); 389 | }); 390 | } 391 | 392 | function getNavPref() { 393 | var v = readCookie('reference_nav'); 394 | if (v != NAV_PREF_TREE) { 395 | v = NAV_PREF_PANELS; 396 | } 397 | return v; 398 | } 399 | 400 | function chooseDefaultNav() { 401 | nav_pref = getNavPref(); 402 | if (nav_pref == NAV_PREF_TREE) { 403 | $("#nav-panels").toggle(); 404 | $("#panel-link").toggle(); 405 | $("#nav-tree").toggle(); 406 | $("#tree-link").toggle(); 407 | } 408 | } 409 | 410 | function swapNav() { 411 | if (nav_pref == NAV_PREF_TREE) { 412 | nav_pref = NAV_PREF_PANELS; 413 | } else { 414 | nav_pref = NAV_PREF_TREE; 415 | init_default_navtree(toRoot); 416 | } 417 | var date = new Date(); 418 | date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years 419 | writeCookie("nav", nav_pref, "reference", date.toGMTString()); 420 | 421 | $("#nav-panels").toggle(); 422 | $("#panel-link").toggle(); 423 | $("#nav-tree").toggle(); 424 | $("#tree-link").toggle(); 425 | 426 | if ($("#nav-tree").is(':visible')) scrollIntoView("nav-tree"); 427 | else { 428 | scrollIntoView("packages-nav"); 429 | scrollIntoView("classes-nav"); 430 | } 431 | } 432 | 433 | function scrollIntoView(nav) { 434 | var navObj = $("#"+nav); 435 | if (navObj.is(':visible')) { 436 | var selected = $(".selected", navObj); 437 | if (selected.length == 0) return; 438 | if (selected.is("div")) selected = selected.parent(); 439 | 440 | var scrolling = document.getElementById(nav); 441 | var navHeight = navObj.height(); 442 | var offsetTop = selected.position().top; 443 | if (selected.parent().parent().is(".toggle-list")) offsetTop += selected.parent().parent().position().top; 444 | if(offsetTop > navHeight - 92) { 445 | scrolling.scrollTop = offsetTop - navHeight + 92; 446 | } 447 | } 448 | } 449 | 450 | function changeTabLang(lang) { 451 | var nodes = $("#header-tabs").find("."+lang); 452 | for (i=0; i < nodes.length; i++) { // for each node in this language 453 | var node = $(nodes[i]); 454 | node.siblings().css("display","none"); // hide all siblings 455 | if (node.not(":empty").length != 0) { //if this languages node has a translation, show it 456 | node.css("display","inline"); 457 | } else { //otherwise, show English instead 458 | node.css("display","none"); 459 | node.siblings().filter(".en").css("display","inline"); 460 | } 461 | } 462 | } 463 | 464 | function changeNavLang(lang) { 465 | var nodes = $("#side-nav").find("."+lang); 466 | for (i=0; i < nodes.length; i++) { // for each node in this language 467 | var node = $(nodes[i]); 468 | node.siblings().css("display","none"); // hide all siblings 469 | if (node.not(":empty").length != 0) { // if this languages node has a translation, show it 470 | node.css("display","inline"); 471 | } else { // otherwise, show English instead 472 | node.css("display","none"); 473 | node.siblings().filter(".en").css("display","inline"); 474 | } 475 | } 476 | } 477 | 478 | function changeDocLang(lang) { 479 | changeTabLang(lang); 480 | changeNavLang(lang); 481 | } 482 | 483 | function changeLangPref(lang, refresh) { 484 | var date = new Date(); 485 | expires = date.toGMTString(date.setTime(date.getTime()+(10*365*24*60*60*1000))); // keep this for 50 years 486 | //alert("expires: " + expires) 487 | writeCookie("pref_lang", lang, null, expires); 488 | //changeDocLang(lang); 489 | if (refresh) { 490 | l = getBaseUri(location.pathname); 491 | window.location = l; 492 | } 493 | } 494 | 495 | function loadLangPref() { 496 | var lang = readCookie("pref_lang"); 497 | if (lang != 0) { 498 | $("#language").find("option[value='"+lang+"']").attr("selected",true); 499 | } 500 | } 501 | 502 | function getLangPref() { 503 | var lang = $("#language").find(":selected").attr("value"); 504 | if (!lang) { 505 | lang = readCookie("pref_lang"); 506 | } 507 | return (lang != 0) ? lang : 'en'; 508 | } 509 | 510 | 511 | function toggleContent(obj) { 512 | var button = $(obj); 513 | var div = $(obj.parentNode); 514 | var toggleMe = $(".toggle-content-toggleme",div); 515 | if (button.hasClass("show")) { 516 | toggleMe.slideDown(); 517 | button.removeClass("show").addClass("hide"); 518 | } else { 519 | toggleMe.slideUp(); 520 | button.removeClass("hide").addClass("show"); 521 | } 522 | $("span", button).toggle(); 523 | } -------------------------------------------------------------------------------- /docs/assets/doclava-developer-reference.js: -------------------------------------------------------------------------------- 1 | var API_LEVEL_ENABLED_COOKIE = "api_level_enabled"; 2 | var API_LEVEL_INDEX_COOKIE = "api_level_index"; 3 | var minLevelIndex = 0; 4 | 5 | function toggleApiLevelSelector(checkbox) { 6 | var date = new Date(); 7 | date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years 8 | var expiration = date.toGMTString(); 9 | if (checkbox.checked) { 10 | $("#apiLevelSelector").removeAttr("disabled"); 11 | $("#api-level-toggle label").removeClass("disabled"); 12 | writeCookie(API_LEVEL_ENABLED_COOKIE, 1, null, expiration); 13 | } else { 14 | $("#apiLevelSelector").attr("disabled","disabled"); 15 | $("#api-level-toggle label").addClass("disabled"); 16 | writeCookie(API_LEVEL_ENABLED_COOKIE, 0, null, expiration); 17 | } 18 | changeApiLevel(); 19 | } 20 | 21 | function buildApiLevelSelector() { 22 | var userApiLevelEnabled = readCookie(API_LEVEL_ENABLED_COOKIE); 23 | var userApiLevelIndex = readCookie(API_LEVEL_INDEX_COOKIE); // No cookie (zero) is the same as maxLevel. 24 | 25 | if (userApiLevelEnabled == 0) { 26 | $("#apiLevelSelector").attr("disabled","disabled"); 27 | } else { 28 | $("#apiLevelCheckbox").attr("checked","checked"); 29 | $("#api-level-toggle label").removeClass("disabled"); 30 | } 31 | 32 | minLevelValue = $("body").attr("class"); 33 | minLevelIndex = apiKeyToIndex(minLevelValue); 34 | var select = $("#apiLevelSelector").html("").change(changeApiLevel); 35 | for (var i = SINCE_DATA.length-1; i >= 0; i--) { 36 | var option = $("