I've created a basic Android app that is intended to have a map with a hamburger drawer on-top of that. Each hamburger menu option will run object methods on the GoogleMap object.
The issue is that while the hamburger drawer is created and works, the map's fragment is placed in the correct place, the onCreate and subsequently onMapReady functions in MainActivity are not running meaning the GoogleMap object is never made. I added some print statements to these functions to make sure and they are never printed.
I've got two classes, HamburgerDrawer.java and MainActivity.java.
HamburgerDrawer.java:
package com.vanleusen.brighthelp;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.google.android.gms.common.api.GoogleApiClient;
public class HamburgerDrawer extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
//testing
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hamburger_drawer);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
/*FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.frame_container, new MyFragment());
transaction.commit();*/
//MainActivity map = new MainActivity();
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.hamburger_drawer, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_roadmap) {
System.out.println("Roadmap");
//mapData.mapTypeInterface(1);
} else if (id == R.id.nav_satellite) {
System.out.println("Satellite");
//mapData.mapTypeInterface(2);
} else if (id == R.id.nav_hybrid) {
System.out.println("Hybrid");
//mapData.mapTypeInterface(3);
} else if (id == R.id.nav_terrain) {
System.out.println("Terrain");
//mapData.mapTypeInterface(4);
} else if (id == R.id.nav_problems) {
System.out.println("Report Problems");
} else if (id == R.id.nav_contact) {
System.out.println("Contact Us");
} else if (id == R.id.nav_about) {
System.out.println("About");
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
MainActivity.java:
package com.vanleusen.brighthelp;
/**
* Created by Oscar on 22/10/2016.
*/
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MainActivity extends Activity implements OnMapReadyCallback {
private GoogleMap mMap;
public static MapFragment mapFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_hamburger_drawer);
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
System.out.println("Ran onCreate method");
}
#Override
public void onMapReady(GoogleMap googleMap) {
System.out.println("Ran onMapReady method");
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
I have multiple layout xml files to implement the hamburger menu, although the relevant one which contains the content for the drawer is here:
content_hamburger_drawer.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/content_hamburger_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.vanleusen.brighthelp.HamburgerDrawer"
tools:showIn="#layout/app_bar_hamburger_drawer">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment" />
<view
android:id="#+id/myview"
android:layout_width="match_parent"
android:layout_height="fill_parent"
class="android.view.View" />
</FrameLayout>
</RelativeLayout>
And finally I've heard this may be connected to my AndroidManifest although I tried some corrections nothing seemed to work for me, I included this below:
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.vanleusen.brighthelp">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
Google Maps Android API v2, but you must specify either coarse or fine
location permissions for the 'MyLocation' functionality.
-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".HamburgerDrawer"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
launchMode ensures intents don't create multiple instances of it
<activity
android:name=".MainActivity"
android:label="Map"
android:theme="#style/AppTheme.NoActionBar"
android:launchMode="singleTask" >
</activity>
<!--
The API key for Google Maps-based APIs is defined as a string resource.
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/google_maps_key" />
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
I'd highly appreciate it if someone could help me work out why my map's onCreate and onMapReady functions are not being executed.
I think you are not calling MainActivity class from anywhere that's why this problem is coming.Please call it from HamburgerDrawer class in onCreate method or any clicklistener.
Intent a=new Intent(getApplicationContext,MainActivity.class);
startActivity(a);
Related
I am new to coding in Android Studio and have been trying to make an application for school and i'm trying to make a youtube streaming application using navigation drawer. But, everytime i run it, I get the message:
My Application keeps stopping
What can i do to solve this?
Here is the main activity:
package com.example.myapplication;
import android.content.Intent;
import android.os.Bundle;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.example.myapplication.Adapter.MyCustomAdapter;
import com.example.myapplication.Model.VideoDetails;
import androidx.core.view.GravityCompat;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.example.myapplication.ui.gallery.GalleryFragment;
import com.google.android.material.navigation.NavigationView;
import com.google.android.youtube.player.YouTubePlayerView;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.RecyclerView;
import android.provider.MediaStore;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
YouTubePlayerView playerView;
private RecyclerView rvVideo;
String API_KEY = "xxxxxx";
String url = "https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=25&type=video&q=larva&key=xxxxxxxxx";
ListView listView;
MyCustomAdapter myCustomAdapter;
ArrayList<VideoDetails> videoDetailsArrayList;
private AppBarConfiguration mAppBarConfiguration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
videoDetailsArrayList = new ArrayList<>();
myCustomAdapter = new MyCustomAdapter(MainActivity.this, videoDetailsArrayList);
rvVideo= findViewById(R.id.rv_video);
rvVideo.setHasFixedSize(true);
displayVideos();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_about)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
private boolean displayVideos() {
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("items");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
JSONObject jsonVideoID = jsonObject1.getJSONObject("id");
JSONObject jsonObjectSnippet = jsonObject1.getJSONObject("snippet");
JSONObject jsonObjectDefault = jsonObjectSnippet.getJSONObject("thumbnails").getJSONObject("medium");
String video_id = jsonVideoID.getString("videoId");
VideoDetails vd = new VideoDetails();
vd.setVideoId(video_id);
vd.setTitle(jsonObjectSnippet.getString("title"));
vd.setDescription(jsonObjectSnippet.getString("description"));
vd.setUrl(jsonObjectDefault.getString("url"));
videoDetailsArrayList.add(vd);
}
listView.setAdapter(myCustomAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
},new Response.ErrorListener(){
#Override
public void onErrorResponse (VolleyError error){
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
}
}
);
requestQueue.add(stringRequest);
return false;
}
#Override
public boolean onSupportNavigateUp () {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if(drawer.isDrawerOpen(GravityCompat.START)){
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_gallery) {
Intent intentku= new Intent(MainActivity.this, GalleryFragment.class);
startActivity(intentku);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
here is the manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".VideoPlayActivity"></activity>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
here is the logcat error:
Process: com.example.myapplication, PID: 25434
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setHasFixedSize(boolean)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setHasFixedSize(boolean)' on a null object reference
at com.example.myapplication.MainActivity.onCreate(MainActivity.java:66)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
here my activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
here is the HomeFragment:
package com.example.myapplication.ui.home;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import com.example.myapplication.R;
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
final TextView textView = root.findViewById(R.id.text_home);
homeViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
return root;
}
}
here is the fragment home.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="#+id/text_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_video"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="#layout/item_video" />
</RelativeLayout>
You are trying to access recyclerview from activity where you have recyclerview in fragment not in activity.
so in fragment's oncreateview method add your code related to fragment not in activity.
I have created a simple app by adding action bar to it. And android studio didn't show any issue in the code, but my app keeps crashing when I run it.
I have two activities, in MainActivity I have one button and when you click it it supposed to take you to SecondActivity. And on SecondActivity there should be back arrow in action bar to get back to MainActivity.
Btw I'm using API 16. My activity extends Activity.
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.actionbar3.MainActivity">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="96dp"
android:text="Next Activity"
android:onClick="onClickButton"/>
</RelativeLayout>
MainActivity:
package com.actionbar3;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.action, menu);
return onCreateOptionsMenu(menu);
}
public void onClickButton(View view){
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
}
}
res/menu/action.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/main_action"
android:title="#string/settings"
android:showAsAction="ifRoom"
android:icon="#drawable/settings"
/>
<item
android:id="#+id/info_action"
android:title="Info"/>
</menu>
ActivitySecond:
package com.actionbar3;
import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
public class SecondActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle("Second Activity");
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.actionbar3">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity" android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
</application>
</manifest>
You are creating a recursion by calling return onCreateOptionsMenu(menu);
so it should be simply return true;
#Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.action, menu);
return true;
// return onCreateOptionsMenu(menu);
// call to itself , mean infinite recursion
}
The onCreateOptionMenu method recurses infinitely, so change it as below
#Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.action, menu);
return true;
}
Extend your activity with AppCompatActivity and use get getSupportActionBar() for backward compatibility
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
public class SecondActivity extends AppCompatActivity {
and create actionbar using getSupportActionBar
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle("Second Activity");
I' have a problem with the app toolbar UP button which never passes the R.id.home on the onOptionsItemSelected method when pressed in a child activity.
The main activity
package com.foocorp.firstapp;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class InstrumentListActivity extends AppCompatActivity
implements IUdpNotificationListener
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_my, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
if (id == R.id.home) {
Toast.makeText(getApplicationContext(), "Clicked Menu back from Main", Toast.LENGTH_SHORT).show();
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
Toast.makeText(getApplicationContext(), "Clicked Hard back from Main", Toast.LENGTH_SHORT).show();
finish();
}
}
The child activity where I set the setDisplayHomeAsUpEnabled(true);
package com.foocorp.firstapp;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class InstrumentViewDetailsActivity extends AppCompatActivity implements IUdpNotificationListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_instrument_view_details);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
//whatever here
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_instrument_view_details, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
//=> never get called because passed ID is never R.id.home
if (id == R.id.home) {
Toast.makeText(getApplicationContext(), "Clicked Menu back from Details", Toast.LENGTH_SHORT).show();
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
Toast.makeText(getApplicationContext(), "Clicked Hard back from Details", Toast.LENGTH_SHORT).show(); // this works fine
finish();
}
}
The manifest file where the parent child relation is defined
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.foocorp.firstapp">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_tap_and_play_white_24dp"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name="com.foocorp.firstapp.InstrumentListActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".InstrumentViewDetailsActivity"
android:label="#string/instrum_details"
android:parentActivityName="com.foocorp.firstapp.InstrumentListActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.foocorp.firstapp.InstrumentListActivity" />
</activity>
</application>
</manifest>
The menu layout file of the child activity (by the way, is it normal that the UP button is not defined here although it appears when the application is running ?)
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.foocorp.firstapp.InstrumentViewDetailsActivity">
<item
android:id="#+id/action_settings"
android:orderInCategory="100"
android:title="#string/action_settings"
app:showAsAction="never" />
</menu>
While searching the internet for this solution, I have found the tips about the parent/child relation in the manifest file and the getSupportActionBar().setHomeButtonEnabled(true); but despite theses hints, I can't get this UP toolbar button to work properly : it DOES return to the parent activity BUT not in the proper way like when I press the back button wich calls the onBackPressed() method and which works fine.
Any clue about what I'm missing here ?
Change id of back button from
R.id.home to android.R.id.home in your onOptionsItemSelected() Method.
you can also use NavUtils.navigateUpFromSameTask(this); instead of finish(); as you have mentioned parentActivityName in AndroidManifest.xml.
Even after defining com.facebook.LoginActivity in my AndroidManifest.xml file the logcat gives the same error and asks to define com.facebook.LoginActivity as activity. I have followed this https://developers.facebook.com/docs/android/login-with-facebook/v2.2#step2 tutorial.
Here is my androidmanifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.log"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.log.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id" />
<activity
android:name="com.facebook.loginActivity"
android:label="#string/app_name" >
</activity>
</application>
</manifest>
MainActivity.java
package com.example.log;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends FragmentActivity {
private MainFragment mainFragment;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.fragment_main);
if (savedInstanceState == null) {
// Add the fragment on initial activity setup
mainFragment = new MainFragment();
getSupportFragmentManager()
.beginTransaction()
.add(android.R.id.content, mainFragment)
.commit();
} else {
// Or set the fragment from restored state info
mainFragment = (MainFragment) getSupportFragmentManager()
.findFragmentById(android.R.id.content);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class MainFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
return view;
}
}
}
fragment_main.xml file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.facebook.widget.LoginButton
android:id="#+id/authButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
/>
</LinearLayout>
The facebook login activity is com.facebook.LoginActivity with a capital 'L'. You're using a lower case l.
I am a new developer of Android App and learning all tips from Getting Started. I'm now on the second stage phase 2 "Adding Action Button" and stuck with adding the actions to the action bar. Here is my current situation.
MyfirstApp Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myfirstapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme.Holo.Light" >
<activity
android:name="com.example.myfirstapp.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- A child of the main activity -->
<activity
android:name="com.example.myfirstapp.DisplayMessageActivity"
android:label="#string/title_activity_display_message"
android:parentActivityName="com.example.myfirstapp.MainActivity" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myfirstapp.MainActivity" />
</activity>
</application>
</manifest>
2.main(menu).xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
<!-- Search, should appear as action button -->
<item android:id="#+id/action_search"
android:icon="#drawable/ic_action_search"
android:title="#string/action_search"
yourapp:showAsAction="ifRoom" />
<!-- Settings, should always be in the overflow -->
<item android:id="#+id/action_settings"
android:title="#string/action_settings"
android:showAsAction="never" />
</menu>
3.MainActivity.java
package com.example.myfirstapp;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
#SuppressLint("ValidFragment")
public class MainActivity extends ActionBarActivity {
public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_displaymessage);
getActionBar().setDisplayHomeAsUpEnabled(true);
// If your minSdkVersion is 11 or higher, instead use:
// getActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case R.id.action_search:
openSearch();
return true;
case R.id.action_settings:
openSettings();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void openSettings() {
}
private void openSearch() {
}
/**
* A placeholder fragment containing a simple view.
*/
public class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
I see two errors from MainActivity.java
1.
inflater.inflate(R.menu.main_activity_actions, menu);
The method inflate(int, Menu) in the type MenuInflater is not applicable for the arguments (Object, Menu)
2.
case R.id.action_search:
case expressions must be constant expressions
I tried to figure out those 2 errors for couple days but I couldn't. Please help.