= Android Mobile Development = == Resources == Downloads: * [[https://developer.android.com/index.html|Android Development Resources]] * [[https://developer.android.com/studio/index.html|Android Studio (IDE)]] * [[https://flutter.io/get-started/codelab/|Flutter (IDE)]] * [[https://www.visualstudio.com|Visual Studio (IDE) + Xamarin]] - Select //Community Edition// Videos: * [[https://www.youtube.com/watch?v=ZLNO2c7nqjw|Edureka: Android Studio Tutorial For Beginners - 1]] * [[https://www.youtube.com/watch?v=D-iqMlLOrec|Edureka: Android Studio Tutorial For Beginners - 2]] * [[https://www.youtube.com/watch?v=dFlPARW5IX8|Butterfield: Studio For Beginners Part 1]] * [[https://www.youtube.com/watch?v=6ow3L39Wxmg|Butterfield: Studio For Beginners Part 2]] * [[https://www.youtube.com/watch?v=rdGpT1pIJlw|Butterfield: Studio For Beginners Part 3]] * [[https://www.youtube.com/watch?v=bu5Y3uZ6LLM|Butterfield: Studio For Beginners Part 4]] How To: * [[http://envyandroid.com/android-studio-extract-strings-resources|How to extract strings into strings.xml resource files in Android Studio]] == App Lifecycle == * onCreate() * onStart()/onRestart() * onResume() * onPause() * onStop() * onDestroy() See: [[https://developer.android.com/guide/components/activities/activity-lifecycle.html|Android Activity Lifecycle]] == Activities == Activities are equivalent to forms, and can be call directly by any other activity or app. ''findViewById()'' is a way to locate resources within Activity. == Event Listeners == * onClick() * onFocusChange() * onLongClick() * onKey() * onTouch() Example 1: public class MainActivity extends AppCompatActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Button btnAdd = (Button) findViewById(R.id.btnAdd); btnAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Do something, such as add to values EditText txtVal1 = (EditText) findViewById(R.id.txtVal1); EditText txtVal2 = (EditText) findViewById(R.id.txtVal2); int val1 = (int) Integer.parseInt(txtVal1.getText().toString()); int val2 = (int) Integer.parseInt(txtVal2.getText().toString()); int result = val1 + val2; final TextView lblResult = (TextView) findViewById(R.id.lblResult); lblResult.SetText(result + ""); // append empty string to convert operation to string Log.d("MyApp", "We clicked a button!"); Toast.makeText(this, "We clicked a button!", Toast.LENGTH_SHORT).show(); } }); } } Example 2: Sharing onClickListener with multiple buttons in same Activity: public class MainActivity extends AppCompatActivity implements View.OnClickListener { // Resources private TextView txt; private Button btn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); txt = (TextView) findViewById(R.id.txtTest); btn = (Button) findViewById(R.id.btnTest); btn.setOnClickListener(this); } @Override public void onClick(View view) { // do something switch(view.getId()) { case R.id.btnTest: Log.d("MyApp", "We clicked a button!"); txt.SetText("We clicked a button!"); Toast.makeText(this, "YEs!!", Toast.LENGTH_SHORT).show(); break; // case ... } } } == Intents == Call for an activity into action (your own or other apps), which can carry a data payload. Eg: Calling dialer from your app, or calling email client when sending an email, or calling a new activity from within your app. To deliver an intent: * context.startActivity() * context.startService() * context.sendBroadcast() To handle an intent: * IntentService * BroadcastReceiver === Implicit Intent === Intents that do not define which activity will handle the request, but rather seek a registered app to handle the provided data payload. // Call dialer app to handle phone number Intent intentDialNumber = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:4071233500")); if (intentDialNumber.resolveActivity(getPackageManager()) != null) { startActivity(intentDialNumber); } // Call contacts to handle contact selection Intent intentSelectContact = new Intent(Intent.ACTION_DIAL, new Uri("content://contacts")); if (intentSelectContact.resolveActivity(getPackageManager()) != null) { startActivity(intentSelectContact); } // Call web browser to handle URL Intent intentViewWebsite = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.acme.com")); if (intentViewWebsite.resolveActivity(getPackageManager()) != null) { startActivity(intentViewWebsite); } // Call a mapping app to handle geolocation (lat,long,zoom) Intent intentShowLocation = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:28.6027902,-81.4232732,14z")); if (intentShowLocation.resolveActivity(getPackageManager()) != null) { startActivity(intentShowLocation); } // Display all activities supporting Action View that can handle intent Intent intentShowAllActivities = new Intent(Intent.ACTION_VIEW); if (intentShowAllActivities.resolveActivity(getPackageManager()) != null) { startActivity(intentShowAllActivities); } === Explicit Intent === Intents that fully define the required activity that should handle the action and its data payload. For example, in the ''MainActivity'', you can define an intent: //... public class MainActivity extends AppCompatActivity { @Override public void onClick(View view) { switch(view.getId()) { case R.id.btnShowIntent: Intent intentDataHandler = new Intent(this, TargetActivity.class); intentDataHandler.putExtra("Key1", "Value1"); // data payload (optional) intentDataHandler.putExtra("Key2", "Value2"); // data payload (optional) intentDataHandler.putExtra("com.acme.myapp.Key3", "Value3"); // use full path with key (recommended) intentDataHandler.putExtra("Key4.TEAM_OBJ", aTeamObj); // parcelable object (eg. object of type Team) startActivity(intentDataHandler); break; } } } In your target activity, retrieve the intent as follows: //... public class TargetActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(saveInstanceState); setContentView(R.layout.activity_target); //----------------------------------- // Get data payload (if available) //----------------------------------- // Method 1 Bundle bundle = getIntent().getExtras(); String str = bundle.getString("Key1"); Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); // Method 2 Intent intent = getIntent(); if (intent.hasExtra("Key2")) { str = intent.getExtras().getString("Key2"); Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); } // Method 3 if (getIntent().hasExtra("Key3")) { str = getIntent().getExtras().getString("Key3"); Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); } // Parcelable data Team objTeam; if (intent.hasExtra("Key4.TEAM_OBJ")) { Log.d("MyApp", "Retrieving intent extras..."); objTeam = intent.getParcelableExtra("Key4.TEAM_OBJ"); Toast.makeText(this, "Team Name: "+ objTeam.name, Toast.LENGTH_SHORT).show(); } } } A parcelable extra must be of a type supporting parcelable. For example: package com.acme.myapp; import android.os.Parcel; import android.os.Parcelable; public class Team implements Parcelable { public long id = 0; public String name = ""; public String number = ""; public int ranking = 0; // Default constructor Team() { } // In constructor, read variables from Parcel. // Important: Read them in the same sequence in which they were written in Parcel. public Team(Parcel in) { id = in.readLong(); name = in.readString(); number = in.readString(); ranking = in.readInt(); } @Override public int describeContents() { return 0; } // Write member variables in Parcel. // Write in any order. Not required to write all members in Parcel. @Override public void writeToParcel(Parcel dest, int flags) { // Write data in any order dest.writeLong(id); dest.writeString(name); dest.writeString(number); dest.writeInt(ranking); } // De-serialize the object public static final Parcelable.Creator CREATOR = new Parcelable.Creator(){ public Team createFromParcel(Parcel in) { return new Team(in); } public Team[] newArray(int size) { return new Team[size]; } }; } === Intent Examples === For example, in the ''MainActivity'', you can define an intent: //... public class MainActivity extends AppCompatActivity implements View.OnClickListener { // Resources private TextView txtHello; private Button btnDialNumber; private Button btnViewWebsite; //... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); txtHello = (TextView) findViewById(R.id.txtHello); btnDialNumber = (Button) findViewById(R.id.btnDialNumber); btnDialNumber.setOnClickListener(this); btnViewWebsite= (Button) findViewById(R.id.btnViewWebsite); btnViewWebsite.setOnClickListener(this); //... } @Override public void onClick(View view) { switch(view.getId()) { case R.id.btnDialNumber: Intent intentDialNumber = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:4071233500")); if (intentDialNumber.resolveActivity(getPackageManager()) != null) { startActivity(intentDialNumber); } break; case R.id.btnViewWebsite: Intent intentViewWebsite = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.acme.com")); if (intentViewWebsite.resolveActivity(getPackageManager()) != null) { startActivity(intentViewWebsite); } break; case R.id.btnShowLocation: Intent intentShowLocation = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:28.6027902,-81.4232732,14z" // lat,long,zoom )); if (intentShowLocation.resolveActivity(getPackageManager()) != null) { startActivity(intentShowLocation); } break; case R.id.btnShowAllActivities: // Display all activities supporting Action View that can handle intent Intent intentShowAllActivities = new Intent(Intent.ACTION_VIEW); if (intentShowAllActivities.resolveActivity(getPackageManager()) != null) { startActivity(intentShowAllActivities); } break; case R.id.btnShowToast: Intent intentShowToast = new Intent(MainActivity.this, SampleActivity.class // target activity ); if (intentShowToast.resolveActivity(getPackageManager()) != null) { startActivity(intentShowToast); } break; case R.id.btnShowSampleActivity: Intent intentShowSampleActivity = new Intent("com.acme.myapp.SampleActivity"); if (intentShowSampleActivity.resolveActivity(getPackageManager()) != null) { startActivity(intentShowSampleActivity); } break; } } } ''activity_main.xml'':