Mobile Programming Final Exam (PDF)

Document Details

Uploaded by Deleted User

The University of Jordan

Tags

mobile programming android programming UI design mobile development

Summary

This document is lecture notes for a mobile programming course, and covers general topics such as building a UI with CardView and ScrollView, Creating the content of cards, adding CardView, and the Localization of apps.

Full Transcript

Building a UI with CardView and ScrollView In this chapter, will learn how to create several CardViews. Once creating a new project, the created layout will be ConstraintLayout. Firstly, create a new layout with Root element ScrollView. This layout type appears to work just like LinearLayou...

Building a UI with CardView and ScrollView In this chapter, will learn how to create several CardViews. Once creating a new project, the created layout will be ConstraintLayout. Firstly, create a new layout with Root element ScrollView. This layout type appears to work just like LinearLayout; the difference is that when there is too much content to display onscreen, it will allow the user to scroll through the content by swiping with their finger. The University of Jordan Creating the contents for the cards The thing we need to do is create the contents for our cards. It makes sense to separate the content from the layout. Assume that we want to create three cards. So, we will create three separate layouts, called card_contents_1, card_contents_2, and card_contents_3. They will each contain a LinearLayout, which itself will contain an image and some text. Add the images you want to present in the cards to the drawable folder. The University of Jordan Creating the contents for the cards Now, select the card_contents_1.xml tab and make sure you are in the design view. We will drag and drop some elements to the layout to get the basic structure. 1. Drag a TextView onto the top of the layout. 2. Drag an ImageView onto the layout below the TextView. 3. In the Resources pop-up window, select Project | image_1, then click OK. 4. Drag another two TextView below the image. The University of Jordan Creating the contents for the cards In the first TextView, set the text attribute to Learning Java by Building Android Games (or whatever title suits your image). In the second TextView, set the text attribute to Learn Java and Android from scratch by building 6 playable games (or something that describes your image). In the second TextView, set the text attribute to BUY NOW. Make the text color and size as you like. Now lay out the other two files (card_contents_2 and card_contents_3) with the exact same dimensions and colors. The University of Jordan Creating the contents for the cards The University of Jordan Adding CardView to our layout Switch to the main_layout.xml tab and make sure you are in the design view. You probably recall that we are now working with a ScrollView that will scroll the contents of our app. ScrollView has a limitation – it can only have one direct child layout. We want it to contain three CardView widgets. To overcome this problem, drag a LinearLayout layout from the Layouts category of the palette. Be sure to pick LinearLayout (vertical), as represented by this icon in the palette: The University of Jordan Adding CardView to our layout We will add our three CardView. The CardView widget can be found in the Containers category of the palette, so switch to that and locate CardView inside LinearLayout (vertical). Now, to include to content of the card_contents_1, Change the code of the XML of the first CardView to be: The University of Jordan Adding CardView to our layout Now, we will change the design of the CardView by adding a margin and making its corner rounded. Find the layout_margin and cardCornerRadius in the attribute and make them as follows: The University of Jordan Adding CardView to our layout Try to change the width size and make the gravity to the center, to have a better design. Now, do the same for other two CardViews. The University of Jordan The University of Jordan The University of Jordan Chapter 8: Localization Dr. Sharif Makhadmeh Making the Note to Self app accessible for Spanish and German speakers First, we need to add some folders to our project – one for each new language. The text is classed as a resource and consequently needs to go in the res folder. Follow the steps in the next slide to add Spanish and German support to the project. The University of Jordan Adding Spanish language support Follow the next steps to add Spanish language support: 1. Right-click on the res folder, and then select New | Android resource directory. In the Directory name field, type values-es. 2. Left-click OK. 3. Now we need to add a file in which we can place all our Spanish translations. Right-click on res, and then select New | Android resource file and type strings.xml in the File name field. Type values-es in the Directory name field. 4. Left-click OK. At this stage, we have a new folder for Spanish translations with a strings.xml file inside for the string resources. The University of Jordan Adding German language support Follow these steps to add German language support: 1. Right-click on the res folder, and then select New | Android resource directory. In the Directory name field, type values-de. 2. Left-click OK. 3. Now we need to add a file in which we can place all our German translations. Rightclick on res, and then select New | Android resource file and type strings.xm in the File name field. Type values-de in the Directory name field. 4. Left-click OK. The University of Jordan Resource The files will be added as shown in the figure. The strings.xml file contains the words that the app will display – words such as "important," "to do," "idea," and more. By having a strings.xml file for each language we want to support, we can then leave Android to choose the appropriate text depending on the language settings of the user. The University of Jordan Translating Let's provide the translations: Assume you have an interface containing TextView and Button as follows. We want to translate the text in TextView and Button to Spanish and German. 1. Open the strings.xml file by double-clicking it. Be sure to choose the one next to the (es) postfix. Add the following code: Hola Mundo! Prensa The first line is to translate the text in TextView and the second for the button. In (name=) we add and name we want to refer to the text. Then, the text in the preferred language (Spanish). The University of Jordan Translating 2. Open the strings.xml file by double-clicking it. Be sure to choose the one next to the (de) postfix. Will do the same for German. Hallo Welt! Drücken 3. Open the strings.xml file by double-clicking it. Be sure to choose the original one (without postfix). This file is for the main language (English). Will do the same in English. Hello World! Press The University of Jordan Activate the translation In the MainActivity.java, will set the text in the TextView and Button by referring to the string.xml for each language. TextView TV = findViewById(R.id.tv); TV.setText(R.string.Text_View); Button BT = findViewById(R.id.button); BT.setText(R.string.Text_Button); The University of Jordan Activate the translation Will notice that the emulator presents the text in English. This is because the language of the emulator is English. Now, we will change the device’s language to the preferred language. Choose Settings | System | Languages and input | Add a language. Next, select Español Now, the text will be presented in Spanish. Do the same for German. The University of Jordan The University of Jordan Chapter 9: Activity Life Cycle Dr. Sharif Makhadmeh Activity Life Cycle Activities are a fundamental building block of Android applications and they can exist in a number of different states. The activity lifecycle begins with instantiation and ends with destruction, and includes many states in between. When an activity changes state, the appropriate lifecycle event method is called, notifying the activity of the impending state change and allowing it to execute code to adapt to that change. The University of Jordan Activity Life Cycle The Android activity lifecycle comprises a collection of methods exposed within the Activity class that provide the developer with a resource management framework. This framework allows developers to meet the unique state management requirements of each activity within an application and properly handle resource management. The University of Jordan States These states can be broken into 4 main groups as follows: Active or Running – Activities are considered active or running if they are in the foreground, also known as the top of the activity stack. This is considered the highest priority activity in Android. Paused – When the device goes to sleep, or an activity is still visible but partially hidden by a new, non-full-sized or transparent activity, the activity is considered paused. Paused activities are still alive, that is, they maintain all state and member information, and remain attached to the window manager. This is considered to be the second highest priority activity in Android. The University of Jordan States Stopped/Backgrounded - Activities that are completely hidden by another activity are considered stopped or in the background. Stopped activities still try to retain their state and member information for as long as possible, but stopped activities are considered to be the lowest priority of the three states. Restarted - It is possible for an activity that is anywhere from paused to stopped in the lifecycle to be removed from memory by Android. If the user navigates back to the activity it must be restarted, restored to its previously saved state, and then displayed to the user. The University of Jordan Activity Lifecycle Methods Android framework provide a powerful model for managing the state of activities within an application. When an activity's state is changing, the activity is notified by the OS, which calls specific methods on that activity. The following diagram illustrates these methods in relationship to the Activity Lifecycle: The onCreate() and onDestroy() methods are called only once throughout lifecycle. The University of Jordan Activity Lifecycle Methods 1. OnCreate: This is called when activity is first created. 2. OnStart: This is called when the activity becomes visible to the user. 3. OnResume: This is called when the activity starts to interact with the user. 4. OnPause: This is called when activity is not visible to the user. 5. OnStop: This is called when activity is no longer visible. 6. OnRestart: This is called when activity is stopped, and restarted again. 7. OnDestroy: This is called when activity is to be closed or destroyed. The University of Jordan Activity Lifecycle Methods OnCreate OnCreate is the first method to be called when an activity is created. OnCreate is always overridden to perform any startup initializations that may be required by an Activity such as: Creating views Initializing variables Binding static data to lists The University of Jordan Activity Lifecycle Methods onStart() Method When activity start getting visible to user then onStart() will be called. This calls just after the onCreate() at first time launch of activity. When activity launch, first onCreate() method call then onStart() and then onResume(). If the activity is in onPause() condition i.e. not visible to user. And if user again launch the activity then onStart() method will be called. Example: Try to use onStart method with Toast as follows: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); Toast.makeText(this, "OnCreate MEthod", Toast.LENGTH_SHORT).show(); } @Override protected void onStart(){ super.onStart(); Toast.makeText(this, "OnStart Method", Toast.LENGTH_SHORT).show(); } The University of Jordan Activity Lifecycle Methods onPause() When onPause() method is in background then onPause() method will execute. Activity is not visible to user and goes in background when onPause() method is executed. onResume() Called when the activity will start interacting with the user. At this point your activity is at the top of the activity stack, with user input going to it. Always followed by onPause(). onStop(): Called when you are no longer visible to the user. You will next receive either onRestart(), onDestroy(), or nothing, depending on later user activity. Note that this method may never be called, in low memory situations where the system does not have enough memory to keep your activity's process running after its onPause() method is called. The University of Jordan Activity Lifecycle Methods When the Activity first time loads the events are called as below onCreate() onStart() onResume() When you click on Phone button the Activity goes to the background and the below events are called: onPause() onStop() Exit the phone dialer and the below events will be called: onRestart() onStart() onResume() When you click the back button OR try to finish() the activity the events are called as below: onPause() onStop() onDestroy() The University of Jordan Activity Lifecycle Methods @Override protected void onStart() { super.onStart(); Log.d("lifecycle","onStart invoked"); } @Override protected void onResume() { super.onResume(); Log.d("lifecycle","onResume invoked"); } @Override protected void onPause() { super.onPause(); Log.d("lifecycle","onPause invoked"); } @Override protected void onStop() { super.onStop(); Log.d("lifecycle","onStop invoked"); } @Override protected void onRestart() { super.onRestart(); Log.d("lifecycle","onRestart invoked"); } @Override protected void onDestroy() { super.onDestroy(); Log.d("lifecycle","onDestroy invoked"); } The University of Jordan The University of Jordan Chapter 10: Design Patterns, Multiple Layouts, and Fragments Dr. Sharif Makhadmeh Introducing the model-view-controller pattern The model-view-controller pattern involves the separation of different aspects of our app into distinct parts called layers. A pattern is simply a recognized way to structure our code and other application resources such as layout files, images, databases, and so on. There are many patterns in computer science but an understanding of model-view controller (MVC) will be enough to create some professionally built Android apps. The University of Jordan Model-view-controller We have been partly using MVC already, so let's look at each of the three layers in turn: Model: Model refers to the data that drives our app and any logic/code that specifically manages it and makes it available to the other layers. View: The view of the app is all the widgets in all the different layouts. Anything the user can see or interact with on the screen is typically part of the view. And you probably remember that the widgets came from the View class hierarchy of the Android API. Controller: The controller is the bit in between the view and the model. It interacts with both and keeps them separate. It contains what is known in geek speak as the application logic. If a user taps a button, the application layer decides what to do about it. When the user clicks OK to add a new note, the application layer listens for the interaction on the view layer. It captures the data contained in the view and passes it to the model layer. The University of Jordan Real-world apps Look at this screenshot of the BBC weather app running on an Android phone in portrait orientation. Look at the basic layout but also study the information shown as we will compare it to the tablet app in a moment. For now, the purpose of the first screenshot is not so much to show you the specific UI features but to allow you to compare it with the next screenshot. Look at the exact same app running on a tablet in landscape orientation. The University of Jordan Real-world apps Notice that the tablet UI has an extra panel of information compared to the phone app. This extra panel is highlighted in the preceding screenshot. Android allows us to design real-world apps like this where not only is the layout different for varying device types/orientations/sizes but also (and this is important) the behavior is different. The Android secret weapon that makes this possible is Fragments. We can design multiple different layouts in different XML files. We can also detect things such as device orientation and screen resolution in our Java code, so we can then make decisions about layout, dynamically. The University of Jordan Device detection mini-app The best way to learn about detecting and responding to devices and their varying attributes (screens, orientations, and so on) is to make a simple app: 1. Create a new Empty Activity project and call it Device Detection. Leave all the other settings as their defaults. 2. Open the activity_main.xml file in the design tab and delete the default Hello world! TextView. 3. Drag a Button onto the top of the screen and set its onClick property to detectDevice. We will code this method in a minute. 4. Drag two TextView widgets onto the layout, one below the other, and set their id properties to txtOrientation and txtResolution. 5. Click the Infer Constraints button to secure the positions of the UI elements. The University of Jordan Device detection mini-app In Android Studio, make sure the activity_main.xml file is selected in the editor and locate the Orientation for preview button as shown next. In other versions, will find it in the activity_main.xml tab as shown in the next screenshot. Click it and then select Create Landscape Variation. You now have a new layout XML file with the same name but orientated in landscape mode. The University of Jordan Device detection mini-app It would appear that the layout already contains all our widgets – we just cannot see them in the design view. The reason for this anomaly is that when we created the landscape layout, Android Studio copied the portrait layout, including all the constraints. The portrait constraints rarely match the landscape constraints. To solve the problem, click the Remove all constraints button; it's the button to the left of the Infer constraints button. The UI is now unconstrained. All the UI widgets will appear jumbled up in the top-left corner. One at a time, rearrange them to look like this next screenshot. The University of Jordan Coding the MainActivity class To activate the TextViews added to the design, add the following member variables just after the MainActivity class declaration, as learned before: private TextView txtOrientation; private TextView txtResolution; Now, in the onCreate method of the MainActivity class, just after the call to setContentView, add this code, as learned before: // Get a reference to our TextView widgets txtOrientation = findViewById(R.id.txtOrientation); txtResolution = findViewById(R.id.txtResolution); The University of Jordan Configuration qualifiers We can begin to remove reliance on the controller layer to influence app layout by using configuration qualifiers. There are configuration qualifiers for size, orientation, and pixel density. To take advantage of a configuration qualifier, we simply design a layout in the usual way, optimized for our preferred configuration, and then place that layout in a folder with a name that Android recognizes as being for that particular configuration. For example, in the previous app, putting a layout in the land folder tells Android to use the layout when the device is in the landscape orientation. If you select the Project Files option from the drop-down list at the top of the Project Explorer window and then examine the project contents, you will indeed see that there is a layout and layout-land folder as shown next: The University of Jordan Configuration qualifiers If we are designing for different sizes of screen, we place layouts into folders with the following names: layout-small layout-normal layout-large layout-xlarge If we are designing for screens with different pixel densities, we can place XML layouts into folders with names like these: layout-ldpi for low-DPI devices layout-mdpi for medium-DPI devices layout-hdpi for high-DPI devices layout-xhdpi for extra-high DPI devices layout-xxhdpi for extra-extra-high DPI devices layout-xxxhdpi for extra-extra-extra-high DPI devices layout-nodpi for devices with a DPI you have not otherwise catered for layout-tvdpi for TVs The University of Jordan The limitation of configuration qualifiers Configuration qualifiers and detecting attributes in code only solves the problem in the view layer of our MVC pattern. Our apps sometimes need to have different behavior as well as layout. This perhaps implies multiple branches of our Java code in the controller layer (MainActivity in most of our previous apps) and perhaps summons nightmarish visions of having huge great if or switch blocks with different code for each different scenario. Fortunately, this is not how it's done. For such situations, in fact for most apps, Android has fragments. The University of Jordan Fragments Fragments will likely become a staple of almost every app you make. They are so useful, there are so many reasons to use them. Fragments are reusable elements of an app just like any class, but as mentioned previously, they have special features, such as the ability to load their own view/layout as well as their very own lifecycle methods, which make them perfect for achieving the goals we discussed in the Real- world apps section and having different layouts and code for different devices (like the weather app we looked at). The University of Jordan Fragments have a lifecycle too We can set up and control fragments very much like we do Activities, by overriding the appropriate lifecycle methods: onCreate: In the onCreate method, we can initialize variables and do almost all the things we would typically have done in the Activity onCreate method. The big exception to this is initializing our UI. onCreateView: In this method, we will, as the name suggests, get a reference to any of our UI widgets, set up anonymous classes to listen for clicks, and more besides, as we will soon see. onAttach and onDetach: These methods are called just before Fragment is put into use/taken out of use. onResume, onStart, onPause, and onStop: In these methods, we can take certain actions, such as creating or deleting objects or saving data, just like we have done with their Activity based counterparts. The University of Jordan Managing Fragments with FragmentManager The FragmentManager class is part of the Activity. We use it to initialize a Fragment, add Fragments to the Activities layout, and to end a Fragment. FragmentManager is a key component that manages the fragments associated with an activity or another fragment. It provides a range of operations to dynamically add, remove, replace, or interact with fragments at runtime. What is important here is that Activity only has one FragmentManager, but it can take care of many fragments. FragmentManager also calls the various lifecycle methods of the fragments it is responsible for. This is distinct from the Activity lifecycle methods that are called by Android, yet closely related because FragmentManager calls many of the Fragment lifecycle methods in response to the Activity lifecycle methods being called. The University of Jordan Fragment app Let's build Fragment in its simplest possible form so we can understand what is going on: 1. Create a new project called Simple Fragment using the Empty Activity template and leaving the rest of the settings at their defaults. 2. Now make sure the root ConstraintLayout is selected by left-clicking it in the Component tree window, then change its id property to fragmentHolder. 3. Now we will create a layout that will define our fragment's appearance. Right-click the layout folder and choose New | Layout resource file. In the File name field, ty fragment_layout, in the RootElement field, type LinearLayout, and left-click OK. 4. Add a single Button widget anywhere on the new layout and make its id property button. 5. In the Project Explorer, right-click the folder that contains the MainActivity file. From the context menu, choose New | Java class and call it SimpleFragment. The University of Jordan Fragment app 6. In our new SimpleFragment class, change the code to extend Fragment. As you type the code, you will be asked to choose the specific Fragment class to import, as shown in the next screenshot. 7. Now add a single String variable called myString and a Button variable called myButton as members. String myString; Button myButton; 8. Now override the onCreate method. Inside the onCreate method, initialize myString to Hello from SimpleFragment. public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); myString = "Hello from SimpleFragment";} The University of Jordan Fragment app In the previous code, we created a member variable called myString, then in the onCreate method, we initialized it. This is very much like what we did for our previous apps when only using Activity. The difference, however, is that we did not set the view or attempt to get a reference to our Button member variable, myButton. When using Fragment, we need to do this in the onCreateView method. Let’s override that now and see how we set the view and get a reference to our Button widget. @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_layout, container, false); myButton = view.findViewById(R.id.button); return view; } The University of Jordan Fragment app (Code Description) First, notice the start of the method states that it must return an object of type View: public View onCreateView... Next, we have three arguments. (LayoutInflater inflater, ViewGroup container,... We need a LayoutInflater reference as we cannot call the setContentView method because the Fragment class provides no such method. In the body of onCreateView, we use the inflate method of inflater to inflate our layout contained in fragment_layout.xml and initialize view (an object of type View) with the result. The ViewGroup container argument allows any Activity with any layout to be the container for our fragment. The third argument we pass in to inflate is false, which means that we don't want our layout immediately added to the containing layout. We will do this ourselves soon from another part of the code. The third argument of onCreateView is Bundle savedInstanceState, which is there to help us maintain the data that our fragments hold. The University of Jordan Fragment app Now we can add an anonymous class to listen for clicks on our button in the usual manner. In the onClick method, we display a pop-up Toast message to demonstrate that everything is working as expected. @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_layout,container, false); myButton = view.findViewById(R.id.button); myButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getActivity(),myString ,Toast.LENGTH_SHORT).show(); } }); return view; } The University of Jordan Fragment app We need to create an instance of our SimpleFragment class and initialize it appropriately. This is where the FragmentManager class will get introduced. This next code creates a new FragmentManager by calling getSupportFragmentManager. The code then creates a new Fragment, based on our SimpleFragment class using the FragmentManager and passing in the ID of the layout (within the Activity) that will hold it. Add this code in the onCreate method of MainActivity.java, just after the call to the setContentView method: FragmentManager fManager = getSupportFragmentManager(); // Create a new fragment using the manager Fragment frag = new SimpleFragment(); fManager.beginTransaction().add(R.id.fragmentHolder, frag).commit(); The University of Jordan The University of Jordan Chapter 11: Android Dialog Windows Dr. Sharif Makhadmeh Dialog windows If we will to show the user some information or even ask for confirmation of an action in a pop-up window. This is known as a dialog window. Dialogs in Android are more advanced than a simple widget or even a whole layout. They are classes that can have layouts and other User Interface (UI) elements of their own. The University of Jordan Creating the Dialog Demo project A lot of methods can be used to create a dialog. Here we want to use the simplest one. Previosly, we learn how to create a login page. In this project, will learn how to create a logout page. Create a new project in Android Studio using the Empty Activity template and call it Dialog Demo. The University of Jordan Creating the Dialog Demo project Create the following layout. Create a new layout and call it layout_dialog. Now will design the dialog. Make it as presented in the following screenshot. Note, after designing the layout, we will make the height of the layout as content and make some margins if needed. The University of Jordan Creating the Dialog Demo project Now, will activate the dialog. As the buttons declare as Button and text as TextView, dialogs will declare also as Dialog. Define the three buttons and dialog as follow: private Button logout; private Button confirm; private Button cancel; private Dialog dialog; The University of Jordan Creating the Dialog Demo project Create a new method for the logout button and call it onClicklogout. Make the logout button clickable for it. Inside it Will declare the dialog and call the setViewContent for the layout_dialog. public void onClicklogout(View v){ dialog = new Dialog(MainActivity.this); dialog.setContentView(R.layout.logout_dialog); dialog.show(); } The University of Jordan Creating the Dialog Demo project Create a new method for the logout button and call it onClickCancle. Make the cancel button clickable for it. Inside it: public void onClickCancel(View v){ dialog.cancel(); // to cancel the dialog } The University of Jordan Creating the Dialog Demo project Notice that, once you click outside the dialog, the dialog will be cancelled. To stop this, set the dialog.setCancelable to false inside onClicklogout as follows: public void onClicklogout(View v){ dialog = new Dialog(MainActivity.this); dialog.setContentView(R.layout.logout_dialog); dialog.show(); dialog.setCancelable(false); } The University of Jordan Creating the Dialog Demo project Create a new project in Android Studio using the Empty Activity template and call it Dialog Demo. Create a new class in Android Studio by selecting New | Java class and name it MyDialog. The first thing to do is to change the class declaration to extend DialogFragment. public class MyDialog extends DialogFragment { The package import androidx.fragment.app.DialogFragment; should be imported. Just like so many classes in the Android API, DialogFragment provides us with methods that we can override in order to interact with the different events that will occur with the class. override the onCreateDialog method from DialogFragment, as follows: public class MyDialog extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return builder.create(); }} The University of Jordan Creating the Dialog Demo project Then, inside the onCreateDialog method, we get our hands on a new class. We declare and initialize an object of the AlertDialog.Builder type, which needs a reference to MainActivity passed into its constructor. This is why we use the getActivity() method as the argument. The getActivity method is part of the Fragment class (and, therefore, DialogFragment too), and it returns a reference to Activity, which will create DialogFragment. AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); The University of Jordan Creating the Dialog Demo project Now we can use our builder object to do the remainder of the work. Inside the onCreateDialog method, will add a code to create the dialog, title, and two buttons “ok” and “cancel”. builder.setMessage("Make a selection") // Dialog will have "Make a selection" as the title.setPositiveButton("OK", new DialogInterface.OnClickListener() // An OK button that does nothing { public void onClick(DialogInterface dialog, int id) {// Nothing happening here } }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {// A "Cancel" button that does nothing public void onClick(DialogInterface dialog, int id) {// Nothing happening here either } }); The University of Jordan Creating the Dialog Demo project The final output will be: The University of Jordan The University of Jordan Chapter 12: Sound Effect Dr. Sharif Makhadmeh What Are Sound Effects? Short audio clips used in apps to provide feedback or enhance interactivity. Purpose: Create immersive experiences. Improve user engagement. Offer feedback for user actions. Examples: Button clicks. Notifications. Game sounds. Visual: Icons representing different sound effects (e.g., bell, click, music). The University of Jordan Why Use Sound Effects? Sound effects transform a mundane app experience into something engaging and memorable. They serve as an essential form of feedback, confirming user actions like button presses or gestures. For instance, a soft click when navigating menus provides reassurance that the action was registered. Moreover, sound effects are an excellent branding tool—unique sound cues can help establish a distinct identity for an app, making it stand out in a crowded marketplace. Visual: A scene showing a user interacting with an app on their phone, with icons or waveforms indicating sound output. The University of Jordan Key Android Tools for Sound Effects SoundPool: Optimized for short, quick sounds with low latency. MediaPlayer: Ideal for longer audio, like background music. AudioManager: Manages audio streams, volume, and audio focus. The University of Jordan Demo Project 1 Create a new project called FirstSoundEffect. Add a new button to the layout. Make the text “Click to Hear”. Right-click on res and select new directory. Name it raw. Copy/Paste a sound file into the raw directory. The University of Jordan Demo Project 1 Declare the button and media player, as follows: private Button btn; private MediaPlayer media; Then initilize the button media player: btn = findViewById(R.id.button); media = MediaPlayer.create(this, R.raw.ring); Create a method or setOnClickListener to activate the button. btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { media.start(); } }); The University of Jordan Demo Project 2 Here, we will present another way of using audio. After creating a project and adding the sound file to raw, we want to initialize the SoundPool. SoundPool soundPool = new SoundPool.Builder().setMaxStreams(5) // Maximum number of simultaneous sounds.build(); int soundId = soundPool.load(this, R.raw.ring, 1); int soundId: This variable stores the identifier (ID) of the loaded sound. soundPool.load():This method loads a sound resource into the SoundPool for playback. 1: Indicates the priority of this sound. Typically, you can use 1 as a default value. The University of Jordan Demo Project 2 Create a method or setOnClickListener to activate the button. btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { soundPool.play(soundId, 1, 1, 0, 0, 1); // (soundId, leftVolume, rightVolume, priority, loop, rate) } }); The University of Jordan The University of Jordan Chapter 13: Android Databases Dr. Sharif Makhadmeh What is a database? A database is both a place of storage and a means to retrieve, store, and manipulate data. The actual structure of the internals of a database varies greatly depending upon the database in question. SQLite actually stores all its data in a single file. Think about a database with names and exam scores. Take a look at this visual representation of such data and imagine what it would look like in a database: Notice, however, that there is an extra column of data: an _ID column. This single spreadsheet-like structure is called a table. There might be multiple tables in a database. Each column of the table will have a name that can be referred to when speaking to the database. The University of Jordan What is SQL and SQLite?? SQL stands for Structured Query Language. It is the syntax that is used to get things done with a database. SQLite is the name of the database system that is favored by Android, and it has its own version of SQL. The reason the SQLite version of SQL needs to be slightly different to some other versions is that the database has different features. The SQL syntax primer that follows will be focused on SQLite. The University of Jordan SQL syntax primer Let's look at some example SQL code that could be used on a SQLite database directly, without any Java or Android classes; then we can more easily understand what our Java code is doing later on. SQLite example code SQL has keywords, much like Java, that cause things to happen. Here is a flavor of some of the SQL keywords we will soon be using: INSERT: Allows us to add data to the database DELETE: Allows us to remove data from the database SELECT: Allows us to read data from the database WHERE: Allows us to specify parts of the database, matching specific criteria, that we want to use INSERT, DELETE, or SELECT on FROM: Used to specify a table or column name in a database The University of Jordan SQL syntax primer In addition to keywords, SQL has types. Some examples of SQL types are as follows: integer: Just what we need for storing whole numbers text: Perfect for storing a simple name or address real: For large floating-point numbers The University of Jordan Creating a table Creating a table: Here is the statement we would use to create a table within a database. I have highlighted a few parts to make the statement clearer: create table StudentsAndGrades _ID integer primary key autoincrement not null, name text not null, score int; The previous code creates a table called StudentsAndGrades with an integer row ID that will be automatically increased (incremented) each time a row of data is added. The table will also have a name column that will be of type text and cannot be blank (not null). It will also have a score column that will be of type int. Also, notice that the statement is completed by a semicolon. The University of Jordan Inserting data into the database Here is how we might insert a new row of data into that database: INSERT INTO StudentsAndGrades (name, score) VALUES ("Bart", 23); The previous code added a row to the database. After the preceding statement, the database will have one entry with the values (1, Bart, 23) for the columns (_ID, name, score). Here is how we might insert another new row of data into that database: INSERT INTO StudentsAndGrades (name, score) VALUES ("Lisa", 100); The University of Jordan Retrieving & Updating data from the database Here is how we would access all the rows and columns from our database: SELECT * FROM StudentsAndGrades; The previous code asks for every row and column. The * symbol can be read as "all." We can also be a little more selective, as this code demonstrates: SELECT score FROM StudentsAndGrades where name = "Lisa"; The previous code would only return 100, which of course is the score associated with the name Lisa. The next statement adds a new column called age that is of type int: ALTER TABLE StudentsAndGrades ADD age int; The University of Jordan SQLiteOpenHelper and SQLiteDatabase There are a number of different ways that the Android API makes it fairly easy to use our app's database. The first class we need to get familiar with is SQLiteOpenHelper. The SQLiteDatabase class is the class that represents the actual database. The SQLiteOpenHelper class, however, is where most of the action takes place. This class will enable us to get access to a database and initialize an instance of SQLiteDatabase. In addition, SQLiteOpenHelper has two methods to override. First, it has an onCreate method, which is called the first time a database is used; therefore, it makes sense that we would put our SQL to create our table structure in. The other method we must override is onUpgrade, which, as you can probably guess, is called when we upgrade our database (use ALTER to change its structure). The University of Jordan Building and executing queries final strings to represent things such as table and column names should be used to not get in a muddle with them. For example, we could declare the following members, which would represent the table name and column names from the fictitious example from earlier. Note that we will also give the database itself a name and have a string for that too: public static final String DB_NAME = "MyCollegeDB"; public static final String TABLE_S_AND_G = "StudentsAndGrades"; public static final String TABLE_ROW_ID = "_id"; public static final String TABLE_ROW_NAME = "name"; public static final String TABLE_ROW_SCORE = "score"; Notice in the preceding code how we will benefit from accessing the strings outside the class, as we declare them public. The University of Jordan Building and executing queries We could then build a query like in this next example. The example adds a new entry to our hypothetical database and incorporates Java variables into the SQL statement: String name = "Onkar"; int score = 95; // Add all the details to the table String query = "INSERT INTO " + TABLE_S_AND_G + " (" + TABLE_ROW_NAME + ", " + TABLE_ROW_SCORE + ") " + "VALUES (" + "'" + name + "'" + ", " + score + ");"; The previous string called query is now the SQL statement, exactly equivalent to this: INSERT INTO StudentsAndGrades ( name, score) VALUES ('Onkar',95); The University of Jordan Coding the database class We will create a class that manages our database by using the SQLiteOpenHelper class. It will also define some final strings to represent the names of the table and its columns. Create a new class called DataManager and extend it from SQLiteOpenHelper and add the following member variables: public class DataManager extends SQLiteOpenHelper { public static final String DATABASE_NAME = "Grading.db"; // public static final string for each row/table that we need to refer to both inside and outside this class public static final int DATABASE_VERSION = 1; public static final String TABLE_NAME = "StudentsAndGrades"; public static final String TABLE_ROW_ID = "_id"; public static final String TABLE_ROW_NAME = "name"; public static final String TABLE_ROW_SCORE = "score"; The University of Jordan Coding the database class An error will appear due to not creating constructor, onCreate, onUpdate, and the package. public MyDatabase(@Nullable Context context) { // constructor super(context, DATABASE_NAME, null, DATABASE_VERSION); // fill the database name and version, and make the factory as null} @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } The University of Jordan Coding the database class In onCreate, will create the tables using queries. Assume will add the following query: CREATE TABLE StudentsAndGrades _ID INTEGER primary key autoincrement, NAME TEXT, SCORE INTEGER; The query will be written as follows: String query = "CREATE TABLE " + TABLE_S_AND_G + "(" + TABLE_ROW_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + TABLE_ROW_NAME + " TEXT, " + TABLE_ROW_SCORE + " INTEGER);"; db.execSQL(query); // To execute it The University of Jordan Coding the database class Now, we will create a new method to insert the data into the database. public void insertData(String name, int score){ SQLiteDatabase db = this.getWritableDatabase(); ContentValues cv = new ContentValues(); cv.put(TABLE_ROW_NAME, name); cv.put(TABLE_ROW_SCORE, score); long results = db.insert(TABLE_S_AND_G, null, cv); // insert the data and save the tag into resutls if(results == -1){ \\ check if added Log.i("info1", "Fail"); }else{ Log.i("info2", "Data Added"); } } The University of Jordan Coding the database class In the main class, first, we design the UI to allow the user to enter the values into the database. Assume you have this interface. The University of Jordan Coding the database class private EditText NameED; private EditText ScoreED; private Button InsertBt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); NameED = findViewById(R.id.name); ScoreED = findViewById(R.id.score); Now, we will declare the UI components and call the insertData InsertBt = findViewById(R.id.insert); method once we click on the button, as learned before. InsertBt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MyDatabase Mydb = new MyDatabase(MainActivity.this); Mydb.insertData(NameED.getText().toString().trim(), Integer.valueOf(ScoreED.getText().toString().trim())); } }); } The University of Jordan Database Browser To check how the data stored and present it, follow these steps: 1- open Database Browser using https://sqlitebrowser.org/ 2- go to the download tab to download the suitable version. 3- unzip the folder and open DB Browser for SQLite The University of Jordan Database Browser To open your database, follow these steps: 1- click on View -> Tool Windows -> Device Explorer. 2- click on data -> data -> com.example.project name 3- click on databases then will find your database name.db 4- select the files with the database name -> right click -> save as. 5- open database browser -> click on open database -> select the database. 6- you can see your database structure now. 7- click on browse Data to see the data in the database. The University of Jordan The University of Jordan Chapter 14: Publishing Dr. Sharif Makhadmeh GitHub GitHub allows you to search and browse code that other people have written and see how they have solved problems. Also, GitHub allows you to sync your code, store it, and share it with other developers. This is useful because seeing the file structure of classes and then dipping into them often shows how to plan your apps from the start and prevents you from starting off on the wrong path. You can even get a GitHub app that allows you to do this from the comfort of your phone or tablet. You can also configure Android Studio to save and share your projects with GitHub. For example, search for Android fragment on the home page, www.github.com, and you will see more than 1,000 related projects that you can snoop through: The University of Jordan GitHub To connect your Android studio with GitHub, several simple steps will be followed: 1- Open GitHub and create an account. 2- Create a new repository by clicking on New -> put the Repository name -> make it public or private -> Create repository. 3- copy the repository link. 4- Now, in Android Studio, click on VCS in the toolbar -> Enable Version Control Integration -> Select Git -> Ok. 5- in the toolbar -> click on Git -> Commit -> Select the project file -> click on Commit -> set the user and email -> Set and Commit. 6- Once finished, Click on Git in the Toolbar -> Push -> Define Remote -> Paste the repository link - > push. 7- Go to your GitHub -> the created repository. Then you will find all files. The University of Jordan Publishing To publish your app, follow these steps: 1- Open Google Play Developer using https://play.google.com/console/signup 2- create an account or link it to your account. 3- In Yourself section click on Get Started -> Continue -> put your username -> select your payment address -> enter your developer email -> verify it -> Select the category of you app and how many app you will upload -> enter contact name, email, and number. 4- Click on Create App -> select if it is an app or game -> free or paid. 5- Click on Set up your app -> finish the nine tasks, starting with App access and ending with Set up your store listing, based on your interest. The University of Jordan Publishing 6- Once finished, click on Production. It shows an upload button. 7- now we need to export out project from Android Studio. Click on Build from Toolbar -> Generate Singed Bundle APK -> Create the key store path -> Choose password -> fill your information -> next -> release -> finish. 8- in the right hand side will display the following message -> click on locate -> then upload the file to Production webpage. 9- click on Create production release -> release. The University of Jordan The University of Jordan

Use Quizgecko on...
Browser
Browser