This is the final video in my Samsung Mobile SDK Tutorial. It has been a ton of fun exploring a new SDK literally days after it was introduced to the public. I did my best to also cover a bunch of general Android topics as well.
Here I’ll specifically finish up the paint application we started back in part 7 of this series. We’ll create all of the event handlers we need to make sure our app runs like a professional tool. All of the code follows the video and it is heavily commented so it can be translated.
If you like videos like this it helps to tell Google+ with a click here [googleplusone]
Donβt forget to check out the Samsung Smart App Challenge which has extended the submission deadline from Nov 30th to Dec 31st!
This challenge will judge and select the 12 winning apps that best incorporate the Pen package or Look package in Samsung Mobile SDK.
The winning entries will receive a total of $1.1 million in prizes and the opportunity for investment evaluation from Samsung Venture Investment
as well as a host of marketing support for app promotion.
Code and Transcript from the Video
package com.samsung.android.sdk.pen.pg.example1_5; import java.io.IOException; import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.Color; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.view.Display; import android.view.View; import android.view.View.OnClickListener; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.Toast; //Used to make sure the device supports the Samsung Mobile SDK import com.samsung.android.sdk.SsdkUnsupportedException; //Initializes and verifies that the S Pen is available import com.samsung.android.sdk.pen.Spen; // Allows you to manage SPD (S Pen Data Files) // Loads and saves SPD files // Adds and removes PageDocs from NoteDocs and attaches external files import com.samsung.android.sdk.pen.document.SpenNoteDoc; // Contains all the data and objects in a page // Adds, deletes, retrieves and changes layers, objects and general // settings for the page document. import com.samsung.android.sdk.pen.document.SpenPageDoc; // Receives history events like undo and redo import com.samsung.android.sdk.pen.document.SpenPageDoc.HistoryListener; // Forwards history information in regards to undo and redo import com.samsung.android.sdk.pen.document.SpenPageDoc.HistoryUpdateInfo; // Handles changes to the color for the S Pen stroke import com.samsung.android.sdk.pen.engine.SpenColorPickerListener; // Allows for editing of the drawing surface with both a finger or the SPen import com.samsung.android.sdk.pen.engine.SpenSurfaceView; // Stores Eraser settings stroke, Thickness, Eraser type import com.samsung.android.sdk.pen.SpenSettingEraserInfo; // Stores Pen settings like color, Pen class name, thickness import com.samsung.android.sdk.pen.SpenSettingPenInfo; // Reference to the class that handles all alert dialogs associated // with making sure the user has the right device and the S Pen import com.samsung.android.sdk.pen.pg.tool.SDKUtils; // Provides methods for working with the Eraser pop up dialog import com.samsung.android.sdk.pen.settingui.SpenSettingEraserLayout; // Handles Eraser events import com.samsung.android.sdk.pen.settingui.SpenSettingEraserLayout.EventListener; //Provides methods for working with the Pen pop up dialog import com.samsung.android.sdk.pen.settingui.SpenSettingPenLayout; import com.samsung.spensdk3.example.R; public class PenSample1_5_Background extends Activity { // startActivityForResult will be used to call an intent // by passing this code when the activity finishes this // code is returned to onActivityResult (Used for Tracking) private final int REQUEST_CODE_SELECT_IMAGE_BACKGROUND = 100; // A Context provides access to application resources private Context mContext; private SpenNoteDoc mSpenNoteDoc; private SpenPageDoc mSpenPageDoc; private SpenSurfaceView mSpenSurfaceView; private SpenSettingPenLayout mPenSettingView; private SpenSettingEraserLayout mEraserSettingView; // Initializes all the images used on buttons in the tool bar private ImageView mPenBtn; private ImageView mEraserBtn; private ImageView mUndoBtn; private ImageView mRedoBtn; private ImageView mBgImgBtn; // Stores the tool type used being the S Pen private int mToolType = SpenSurfaceView.TOOL_SPEN; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_background); mContext = this; // Sets the S Pen usage as false by default boolean isSpenFeatureEnabled = false; // Create an S Pen object Spen spenPackage = new Spen(); // Try to initialize the Spen and if it doesn't exist // trigger an exception that is handled below try { spenPackage.initialize(this); isSpenFeatureEnabled = spenPackage.isFeatureEnabled(Spen.DEVICE_PEN); } // Have SDKUtils create the right alert dialogs for this exception catch (SsdkUnsupportedException e) { if( SDKUtils.processUnsupportedException(this, e) == true) { return; } } // Generate a Toast to warn the user of an error catch (Exception e1) { Toast.makeText(mContext, "Cannot initialize Spen.", Toast.LENGTH_SHORT).show(); e1.printStackTrace(); // Drop the Activity from memory finish(); } // The FrameLayout will hold the Relative Layout that will be drawn on FrameLayout spenViewContainer = (FrameLayout) findViewById(R.id.spenViewContainer); RelativeLayout spenViewLayout = (RelativeLayout) findViewById(R.id.spenViewLayout); // To create the SpenSettingPenLayout that will allow // us to work with the Pen settings layout, pass it the // Context, an image file path if any and the RelativeLayout mPenSettingView = new SpenSettingPenLayout(mContext, new String(), spenViewLayout); // Notify the user of an error and kill the app if (mPenSettingView == null) { Toast.makeText(mContext, "Cannot create new PenSettingView.", Toast.LENGTH_SHORT).show(); finish(); } // Set up the settings window for the Eraser tool mEraserSettingView = new SpenSettingEraserLayout(mContext, new String(), spenViewLayout); if (mEraserSettingView == null) { Toast.makeText(mContext, "Cannot create new EraserSettingView.", Toast.LENGTH_SHORT).show(); finish(); } // Add the settings windows for the Pen and Eraser spenViewContainer.addView(mPenSettingView); spenViewContainer.addView(mEraserSettingView); // Create the drawing surface on the device or trigger an error mSpenSurfaceView = new SpenSurfaceView(mContext); if (mSpenSurfaceView == null) { Toast.makeText(mContext, "Cannot create new SpenSurfaceView.", Toast.LENGTH_SHORT).show(); finish(); } // Add the drawing surface to Relative Layout spenViewLayout.addView(mSpenSurfaceView); // Sets the canvas view mPenSettingView.setCanvasView(mSpenSurfaceView); mEraserSettingView.setCanvasView(mSpenSurfaceView); // Display provides information on the display Display display = getWindowManager().getDefaultDisplay(); // Holds 4 integer coordinates for a rectangle being the display Rect rect = new Rect(); // Get the size of the display as a Rect in pixels display.getRectSize(rect); // Create a SpenNoteDoc by passing the Context and the // width and height or handle errors try { mSpenNoteDoc = new SpenNoteDoc(mContext, rect.width(), rect.height()); } catch (IOException e) { Toast.makeText(mContext, "Cannot create new NoteDoc", Toast.LENGTH_SHORT).show(); e.printStackTrace(); finish(); } catch (Exception e) { e.printStackTrace(); finish(); } // Adds a page to the document mSpenPageDoc = mSpenNoteDoc.appendPage(); // Changes the background color mSpenPageDoc.setBackgroundColor(0xFFD6E6F5); // Clear undo / redo history mSpenPageDoc.clearHistory(); // Put the Spen document in the current view // and pass true to update the screen mSpenSurfaceView.setPageDoc(mSpenPageDoc, true); // Call to method below which sets default settings for // the Pen and Eraser initSettingInfo(); // Set the method that will handle color changes mSpenSurfaceView.setColorPickerListener(mColorPickerListener); // Set the method that will handle history changes (Undo / Redo) mSpenPageDoc.setHistoryListener(mHistoryListener); // Set the method that will handle Eraser setting changes mEraserSettingView.setEraserListener(mEraserListener); // initialize all the icon images and add listeners for them mPenBtn = (ImageView) findViewById(R.id.penBtn); mPenBtn.setOnClickListener(mPenBtnClickListener); mEraserBtn = (ImageView) findViewById(R.id.eraserBtn); mEraserBtn.setOnClickListener(mEraserBtnClickListener); mUndoBtn = (ImageView) findViewById(R.id.undoBtn); mUndoBtn.setOnClickListener(undoNredoBtnClickListener); mUndoBtn.setEnabled(mSpenPageDoc.isUndoable()); mRedoBtn = (ImageView) findViewById(R.id.redoBtn); mRedoBtn.setOnClickListener(undoNredoBtnClickListener); mRedoBtn.setEnabled(mSpenPageDoc.isRedoable()); mBgImgBtn = (ImageView) findViewById(R.id.bgImgBtn); mBgImgBtn.setOnClickListener(mBgImgBtnClickListener); // Set the Pen button in the tool bar to be set by default selectButton(mPenBtn); // Check if the Spen is available or not if(isSpenFeatureEnabled == false) { // Set the tool type to the finger if not mToolType = SpenSurfaceView.TOOL_FINGER; mSpenSurfaceView.setToolTypeAction(mToolType, SpenSurfaceView.ACTION_STROKE); Toast.makeText(mContext, "Device does not support Spen. \n You can draw stroke by finger", Toast.LENGTH_SHORT).show(); } } // Sets the default settings for the Pen and Eraser private void initSettingInfo() { SpenSettingPenInfo penInfo = new SpenSettingPenInfo(); penInfo.color = Color.BLUE; penInfo.size = 10; mSpenSurfaceView.setPenSettingInfo(penInfo); mPenSettingView.setInfo(penInfo); SpenSettingEraserInfo eraserInfo = new SpenSettingEraserInfo(); eraserInfo.size = 30; mSpenSurfaceView.setEraserSettingInfo(eraserInfo); mEraserSettingView.setInfo(eraserInfo); } // Handle what happens if the Pen icon is clicked on in the tool bar private final OnClickListener mPenBtnClickListener = new OnClickListener() { @Override public void onClick(View v) { // Check if the current tool is the stroke or pen tool if (mSpenSurfaceView.getToolTypeAction(mToolType) == SpenSurfaceView.ACTION_STROKE) { // Check if the Pen settings window is open // if it is close it and if not open it if (mPenSettingView.isShown()) { mPenSettingView.setVisibility(View.GONE); } else { mPenSettingView .setViewMode(SpenSettingPenLayout.VIEW_MODE_EXTENSION); mPenSettingView.setVisibility(View.VISIBLE); } } else { // If the Pen tool wasn't in use when the Pen icon // was clicked change to the Pen tool rather then // opening the Pen settings window selectButton(mPenBtn); mSpenSurfaceView.setToolTypeAction(mToolType, SpenSurfaceView.ACTION_STROKE); } } }; // Handle what happens if the Eraser icon is clicked on in the tool bar private final OnClickListener mEraserBtnClickListener = new OnClickListener() { @Override public void onClick(View v) { // Check if the current tool is the Eraser tool // and do the same as we did with Pen if (mSpenSurfaceView.getToolTypeAction(mToolType) == SpenSurfaceView.ACTION_ERASER) { if (mEraserSettingView.isShown()) { mEraserSettingView.setVisibility(View.GONE); } else { mEraserSettingView .setViewMode(SpenSettingEraserLayout.VIEW_MODE_NORMAL); mEraserSettingView.setVisibility(View.VISIBLE); } } else { selectButton(mEraserBtn); mSpenSurfaceView.setToolTypeAction(mToolType, SpenSurfaceView.ACTION_ERASER); } } }; // If the background image button is clicked private final OnClickListener mBgImgBtnClickListener = new OnClickListener() { @Override public void onClick(View v) { // Method below that closes the Pen and Eraser // setting views closeSettingView(); // Call a method below that opens up the picture gallery callGalleryForInputImage(REQUEST_CODE_SELECT_IMAGE_BACKGROUND); } }; // If the Undo / Redo button is clicked private final OnClickListener undoNredoBtnClickListener = new OnClickListener() { @Override public void onClick(View v) { // Check if the SpenPageDoc is valid if (mSpenPageDoc == null) { return; } // undo button click if (v.equals(mUndoBtn)) { // Check if it is possible to Undo if (mSpenPageDoc.isUndoable()) { // Return the previous state history for the page HistoryUpdateInfo[] userData = mSpenPageDoc.undo(); // Update the undo state in the stack mSpenSurfaceView.updateUndo(userData); } // redo button click } else if (v.equals(mRedoBtn)) { // Check if it is possible to Redo if (mSpenPageDoc.isRedoable()) { // Return the previous state history for the page HistoryUpdateInfo[] userData = mSpenPageDoc.redo(); // Update the redo state in the stack mSpenSurfaceView.updateRedo(userData); } } } }; // Called if the color or other settings for Pen have changed private SpenColorPickerListener mColorPickerListener = new SpenColorPickerListener() { @Override public void onChanged(int color, int x, int y) { // Get the settings changes set in the settings View // and save them to the Pen object if (mPenSettingView != null) { SpenSettingPenInfo penInfo = mPenSettingView.getInfo(); penInfo.color = color; mPenSettingView.setInfo(penInfo); } } }; // Catch when the eraser icon is clicked on private EventListener mEraserListener = new EventListener() { @Override public void onClearAll() { // Remove all objects from the current layer mSpenPageDoc.removeAllObject(); mSpenSurfaceView.update(); } }; // Handle changing the state of Undo / Redo buttons based on // if there is an option to do so in the history stack private HistoryListener mHistoryListener = new HistoryListener() { @Override public void onCommit(SpenPageDoc page) { } // If there is nothing left to Undo in the history then // disable the Undo button @Override public void onUndoable(SpenPageDoc page, boolean undoable) { // undo mUndoBtn.setEnabled(undoable); } // If there is nothing left to Redo in the history then // disable the Undo button @Override public void onRedoable(SpenPageDoc page, boolean redoable) { // redo mRedoBtn.setEnabled(redoable); } }; // Called to set the button sent as active on the tool bar // while making the others inactive private void selectButton(View v) { mPenBtn.setSelected(false); mEraserBtn.setSelected(false); v.setSelected(true); // Close the Eraser and Pen settings Views closeSettingView(); } // Close the Eraser and Pen settings Views private void closeSettingView() { mEraserSettingView.setVisibility(SpenSurfaceView.GONE); mPenSettingView.setVisibility(SpenSurfaceView.GONE); } private void callGalleryForInputImage(int nRequestCode) { try { // Create an Intent that will display the gallery, // allow the user to pick a picture and then return // it to this app Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT); // Set the data type returned galleryIntent.setType("image/*"); // Trigger the activity and then return the item selected // to onActivityResult (RequestCode signifies the intent // that triggered this action) startActivityForResult(galleryIntent, nRequestCode); } // If gallery wasn't found catch (ActivityNotFoundException e) { Toast.makeText(mContext, "Cannot find gallery.", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } // After the Intent triggered by startActivityForResult is finished // this method is sent data to process @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Check if everything went all right when the Intent was called if (resultCode == RESULT_OK) { // Check if the image is available if (data == null) { Toast.makeText(mContext, "Cannot find the image", Toast.LENGTH_SHORT).show(); return; } // Check that the Intent that was meant to return an // image from the gallery called onActivityResult if (requestCode == REQUEST_CODE_SELECT_IMAGE_BACKGROUND) { // Get the path to the image Uri imageFileUri = data.getData(); // A ContentResolver is returned by getContentResolver // A ContentResolver is used to access data in this case // the image // query returns a Cursor given the URI for the data // The Cursor allows you to read the image data Cursor cursor = getContentResolver().query( Uri.parse(imageFileUri.toString()), null, null, null, null); // Cursor moves through the results cursor.moveToNext(); // MediaStore has an index of all files in storage // DATA is the actual data stream for the file String imagePath = cursor.getString(cursor .getColumnIndex(MediaStore.MediaColumns.DATA)); // Sets the background for the Doc to the image mSpenPageDoc.setBackgroundImage(imagePath); mSpenSurfaceView.update(); } } } // The app is being shutdown so free memory @Override protected void onDestroy() { super.onDestroy(); if (mPenSettingView != null) { mPenSettingView.close(); } if (mEraserSettingView != null) { mEraserSettingView.close(); } if(mSpenSurfaceView != null) { mSpenSurfaceView.close(); mSpenSurfaceView = null; } if(mSpenNoteDoc != null) { try { mSpenNoteDoc.close(); } catch (Exception e) { e.printStackTrace(); } mSpenNoteDoc = null; } }; }
hello admin u have problm while installing eclipse .
eclipse failed to load the jni shared library jvm.dll it pop up this.
(m using 64bit win8) pls hlp as quick as pssbl .
Fixed it ohh yeahhh π
You need to use a 64 bit version of Eclipse and Java to solve this problem.
i have instald eclipse also android plugin for it wat if now i also install android studio will it misconfigure or harm anything??
and why u didnt use android studio ??
You can use Eclipse and Android Studio without conflicts. I don’t use Android Studio in these tutorials because the install fails on to many machines.
derek thanks for all the awesome videos you make but can you also make videos on using the facebook android sdk and twitter api…….
You’re very welcome π I’ll be taking a look at both Facebook and Twitter. I’m sure I can make a Twitter app, but I’m not sure about Facebook because it changes constantly.
for begining with php do we have to install anything??
do you have tutorial on it .i am new to php.
Yes you need to install a web server. I use Apache. If you’re on a Mac or Linux machine chances are it is already installed or it is very easy to install. If you are on Windows I’d install WUBI, which is like Linux installed as an application, or WAMP.
Here is my PHP video tutorial