I did everything by following a tutorial, the map gets displayed in the tutorial but it doesn't get displayed in mine even when I did the exact same thing.
MainActivity.Java
package com.example.ankit.mrestro;
import android.app.Dialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final int GPS_ERRORDIALOGUE_REQUEST = 9001;
GoogleMap mMap;
MapView mMapView;
Button bLogout;
EditText etFName, etLName, etAge, etEmail, etUserName;
UserLocalStorage userLocalStorage;
/**
* 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) {
super.onCreate(savedInstanceState);
if (servicesOK()){
Toast.makeText(this, "Ready to map", Toast.LENGTH_SHORT).show();
setContentView(R.layout.activity_mapview);
mMapView = (MapView) findViewById(R.id.map);
mMapView.onCreate(savedInstanceState);
}
setContentView(R.layout.activity_main);
etFName = (EditText) findViewById(R.id.etFName);
etLName = (EditText) findViewById(R.id.etLName);
etAge = (EditText) findViewById(R.id.etAge);
etEmail = (EditText) findViewById(R.id.etEmail);
etUserName = (EditText) findViewById(R.id.etUserName);
bLogout = (Button) findViewById(R.id.bLogout);
bLogout.setOnClickListener(this);
userLocalStorage = new UserLocalStorage(this);
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
#Override
protected void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
if (authenticate() == true) {
DisplaysUserDetails();
}
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.example.ankit.mrestro/http/host/path")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
private boolean authenticate() {
return userLocalStorage.getUserLoggedIn();
}
private void DisplaysUserDetails() {
User user = userLocalStorage.GetLoggedInUser();
etUserName.setText(user.UserName);
etFName.setText(user.FirstName);
etLName.setText(user.LastName);
etAge.setText(user.Age + "");
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bLogout:
userLocalStorage.ClearUserData();
userLocalStorage.SetUserLoggedIn(false);
startActivity(new Intent(this, Login.class));
break;
}
}
public boolean servicesOK() {
int isAvailable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (isAvailable == ConnectionResult.SUCCESS) {
return true;
} else if (GooglePlayServicesUtil.isUserRecoverableError(isAvailable)) {
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(isAvailable, this, GPS_ERRORDIALOGUE_REQUEST);
dialog.show();
}
else {
Toast.makeText(this, "Can't connect to google play services", Toast.LENGTH_SHORT).show();
}
return false;
}
#Override
protected void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
#Override
protected void onPause() {
super.onPause();
mMapView.onPause();
}
#Override
protected void onResume() {
super.onResume();
mMapView.onResume();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mMapView.onSaveInstanceState(outState);
}
#Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction2 = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.example.ankit.mrestro/http/host/path")
);
AppIndex.AppIndexApi.end(client, viewAction2);
client.disconnect();
}
}
AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.ankit.mrestro">
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="23"/>
<permission android:name="com.example.ankit.mrestro.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsg.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:replace="android:icon, android:theme, android:label">
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="<<APIKEY>>"/>
<activity
android:name=".Login"
android:label="#string/title_activity_login"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".Register"
android:label="#string/title_activity_register"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".Main2Activity"
android:label="#string/title_activity_main2"
android:theme="#style/AppTheme.NoActionBar"></activity>
<!-- ATTENTION: This was auto-generated to add Google Play services to your project for
App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information. -->
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
activity_mapview
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.gms.maps.MapView
android:id="#+id/map"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>
I've noticed that I've not created a separate button for displaying the map. Could this be the problem? If so, how do I assign a button to Google maps? I know how to create a button and assign an activity to it but how do I do that for Maps? Please help.
Where are you getting your map?
You should implement OnMapReadyCallback in your Activity and then in onCreate do the following:
if (/* play services are OK */) {
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(this);
}
And then override an onMapReady call (something like that):
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
UiSettings uiSettings = mGoogleMap.getUiSettings();
uiSettings.setZoomControlsEnabled(true);
if (mCameraPosition != null) {
mGoogleMap.moveCamera(CameraUpdateFactory.newCameraPosition(mCameraPosition));
}
addMarkers();
}
You can check out my code:
https://github.com/dmytroKarataiev/EarthquakeSurvival/blob/master/app/src/main/java/com/adkdevelopment/earthquakesurvival/MapviewFragment.java
Also very important: NEVER show anyone your API key. It's against the Google rules and also not safe for you.
Related
I would like to figure out the cause of not registering a listener for a step counter sensor and how to overcome it.
MainActivity.java
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager sensorManager;
private TextView count;
boolean activityRunning;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
count = (TextView) findViewById(R.id.counter);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
#Override
protected void onResume() {
super.onResume();
activityRunning = true;
Sensor countSensor = sensorManager
.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (countSensor != null) {
if (sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI)) {
Toast.makeText(this, "registered", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "NOT registered", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(this, "Count sensor not available", Toast.LENGTH_LONG).show();
}
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_STEP_DETECTOR)) {
Toast.makeText(getApplicationContext(), "STEP DETECTOR -> SUPPORTED", Toast.LENGTH_LONG).show();
Log.i("onResume", "step detector is supported");
} else {
Toast toast = Toast.makeText(getApplicationContext(), "STEP DETECTOR -> NO", Toast.LENGTH_LONG).show();
Log.i("onResume", "step detector is NOT supported");
}
}
#Override
protected void onPause() {
super.onPause();
activityRunning = false;
}
#Override
public void onSensorChanged(SensorEvent event) {
if (activityRunning) {
count.setText(String.valueOf(event.values[0]));
Toast.makeText(this, "onSensorChanged", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "changed, else branch", Toast.LENGTH_LONG).show();
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<uses-feature android:name="android.hardware.sensor.stepcounter" android:required="true"/>
<uses-feature android:name="android.hardware.SensorManager"/>
<uses-feature android:name="android.hardware.Sensor"/>
<uses-feature android:name="android.hardware.SensorEvent"/>
<uses-feature android:name="android.hardware.SensorEventListener"/>
<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>
</application>
</manifest>
It shows a Toast with NOT registered and this error in Logcat
E/SensorManager: registerListenerImpl sensorName:Step Counter,isWakeUpSensor:false
P.S. It pops up the STEP DETECTOR -> SUPPORTED toast for the check of the presence of this sensor. Is there something else that must be added to the manifest? Or probably, it is a wrong way of registering a listener?
Try adding the activity recognition permission to your manifest:
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
If you app targets Android 10+ (API 29 or later), you may need to request the permission at runtime as well:
https://developer.android.com/about/versions/10/privacy/changes#physical-activity-recognition
I have an App where a background service running . When a phone call is detected I want that app to open and show me a particular Intent. How should I do this.
My code is
MainActivity.java
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.lang.reflect.Method;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view){
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener phoneStateListener = new PhoneStateListener(){
#Override
public void onCallStateChanged(int state, String incomingNumber) {
String number = incomingNumber;
Log.d("gaandu", number);
if(state == TelephonyManager.CALL_STATE_RINGING){
Toast.makeText(MainActivity.this, "incoming call from" + incomingNumber, Toast.LENGTH_SHORT).show();
}
if(state == TelephonyManager.CALL_STATE_OFFHOOK){
Toast.makeText(MainActivity.this, "Phone is currently in a call", Toast.LENGTH_SHORT).show();
}
if(state == TelephonyManager.CALL_STATE_IDLE){
Toast.makeText(MainActivity.this, "Phone is neither Ringing nor in a Call", Toast.LENGTH_SHORT).show();
}
}
};
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
public void stopService(View view){
Intent i = new Intent(MainActivity.this, MyService.class);
stopService(i);
}
}
MyService.java
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.admin.abab">
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<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>
<service android:name=".MyService"
android:exported="false"
/>
</application>
</manifest>
In MainActivity.java, after a phone call has been detected, I want to launch my app running in background to open to its first Activity.
You might want to look into the Android cookbook:
You want to act on an incoming phone call and do something with the incoming number.
Solution:
This can be achieved by implementing a Broadcast receiver and listening for a TelephonyManager.ACTION_PHONE_STATE_CHANGED action.
You probably need to do some more research; depending the version of Android you are targeting!
Try this link. hope this will help you. Transparent your activity will help you some what.
Go through this link also
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
I keep getting this error while trying to build the apk.
ERROR
Error:Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed with multiple errors, see logs
And in the Event Logs, it simply says "2:58:21 PM Build APK: Errors while building APK. You can find the errors in the 'Messages'"
AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.ankit.mrestro">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17"/>
<permission android:name="com.example.ankit.mrestro.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsg.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<meta-data
android:name="com.google.android.gms.version"
tools:replace="android:value"/>
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIzaSyAfg6F4I6Ee-E6xxxxxxxxxxxxxxxxxx"/>
<activity
android:name=".Login"
android:label="#string/title_activity_login"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".Register"
android:label="#string/title_activity_register"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".Main2Activity"
android:label="#string/title_activity_main2"
android:theme="#style/AppTheme.NoActionBar"></activity>
</application>
</manifest>
MainActivity
package com.example.ankit.mrestro;
import android.app.Dialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.maps.GoogleMap;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final int GPS_ERRORDIALOGUE_REQUEST = 9001;
GoogleMap mMap;
Button bLogout;
EditText etFName, etLName, etAge, etEmail, etUserName;
UserLocalStorage userLocalStorage;
/**
* 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) {
super.onCreate(savedInstanceState);
if (servicesOK()){
Toast.makeText(this, "Ready to map", Toast.LENGTH_SHORT).show();
}
setContentView(R.layout.activity_main);
etFName = (EditText) findViewById(R.id.etFName);
etLName = (EditText) findViewById(R.id.etLName);
etAge = (EditText) findViewById(R.id.etAge);
etEmail = (EditText) findViewById(R.id.etEmail);
etUserName = (EditText) findViewById(R.id.etUserName);
bLogout = (Button) findViewById(R.id.bLogout);
bLogout.setOnClickListener(this);
userLocalStorage = new UserLocalStorage(this);
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
#Override
protected void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
if (authenticate() == true) {
DisplaysUserDetails();
}
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.example.ankit.mrestro/http/host/path")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
private boolean authenticate() {
return userLocalStorage.getUserLoggedIn();
}
private void DisplaysUserDetails() {
User user = userLocalStorage.GetLoggedInUser();
etUserName.setText(user.UserName);
etFName.setText(user.FirstName);
etLName.setText(user.LastName);
etAge.setText(user.Age + "");
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bLogout:
userLocalStorage.ClearUserData();
userLocalStorage.SetUserLoggedIn(false);
startActivity(new Intent(this, Login.class));
break;
}
}
public boolean servicesOK() {
int isAvailable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (isAvailable == ConnectionResult.SUCCESS) {
return true;
} else if (GooglePlayServicesUtil.isUserRecoverableError(isAvailable)) {
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(isAvailable, this, GPS_ERRORDIALOGUE_REQUEST);
dialog.show();
}
else {
Toast.makeText(this, "Can't connect to google play services", Toast.LENGTH_SHORT).show();
}
return false;
}
}
I want to display the "Ready to Map" toast while running the app on my device. What should I do to fix the error?
GRADLE
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.example.ankit.mrestro"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.google.android.gms:play-services:8.4.0'
}
I'm completely new to Android development, but I have worked with Java (and other programming languages) before.
I'm using Android Studio to develop my application and I've become stuck when following the developer tutorial on accessing Location information (http://developer.android.com/training/location/index.html). I understand that the Location services require the android.permission.ACCESS_COARSE_LOCATION and/or android.permission.ACCESS_FINE_LOCATION permissions but upon adding them to my ApplicationManifest my application still crashes with a SecurityException
java.lang.SecurityException: Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to perform any location operations.
I've come across several other instances of people having trouble, but these have generally been the result of mis-placing (java.lang.SecurityException: Requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission), mis-spelling (ACCESS_FINE_LOCATION AndroidManifest Permissions Not Being Granted) or incorrect capitalization of the permission string.
Here is my ApplicationManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="scd.tt" >
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="23" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher_tt_v2"
android:label="#string/app_name"
android:theme="#style/TT_Theme">
<activity
android:name=".MainActivity"
android:theme="#style/TT_Theme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".LoginActivity" android:theme="#style/TT_Theme.NoActionBar" />
<activity android:name=".IndexActivity" />
</application>
</manifest>
I've even tried to remove ACCESS_NETWORK_STATE and INTERNET to see if this would cause other SecurityExceptions as the application is required to communicate with an HTTP server (which it performs successfully) before it gets attempts to get Location information.
It seems as though modifications I make to the permissions on the AndroidManifest aren't being updated when I run the program. I've also tried to Clean and Rebuild the application using the Build menu.
UPDATE:
Here is the core of the Activity; I've removed some of the unrelated methods (such as onCreateOptionsMenu() and onBackPressed() as they have nothing to do with the Location)
package scd.tt;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import java.util.Map;
/**
* Created by Liam on 08/09/2015
*/
public class IndexActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location mLastLocation;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index);
if(debug) Log.d(TAG, "onCreate() called: savedInstanceState is " + (savedInstanceState == null ? "null" : "not null"));
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
buildGoogleApiClient();
if (findViewById(R.id.index_fragment_container) != null) {
if (savedInstanceState != null) return;
Fragment index = new IndexFragment();
index.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(R.id.index_fragment_container, index).commit();
}
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
#Override
public void onConnected(Bundle bundle) {
if(debug) Log.d(TAG, "onConnected");
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
if(debug) Log.d(TAG, "Connection Suspended");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if(debug) Log.d(TAG, "Connection Failed");
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
if(debug) Log.d(TAG, "buildGoogleAPIClient()");
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
Check these 3 links. They might help -
Android - Unable to get the gps location on the emulator
ACCESS_FINE_LOCATION permission error emulator only
http://www.gitshah.com/2011/02/android-fixing-no-internet-connection.html
As quoted by you in comments -
Permissions with a protection level of dangerous must be granted at runtime by prompting the user as of SDK 23 and can not be defined solely in the Manifest any more.
I have an app with 2 classes, I need my app to open the second class CardActivity when the NFC tag tapped/swiped. The app opens fine, but MainActivity is run, instead of CardActivity.
I would hazard a guess that this is an issue with my manifest, but it looks correct. Here it is regardless:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.spotsofmagic.spotsofmagic"
android:versionCode="1"
android:versionName="1.0" android:installLocation="auto">
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".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>
<activity
android:name=".CardActivity"
android:label="#string/app_name" >
<!-- Handle a collectable card NDEF record -->
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<data android:mimeType="application/vnd.spotsofmagic.spotsofmagic"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
I'm confident the tag itself is correct, as I have opened it in another app to view it's contents.
Below are the two classes.
CardActivity:
package com.spotsofmagic.spotsofmagic;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.bluetooth.*;
public class CardActivity extends Activity implements OnClickListener {
private static final String TAG = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.card_activity);
// see if app was started from a tag and show game console
Intent intent = getIntent();
Log.e(TAG, "Hello world. Intent Type: "+ intent.getType());
if(intent.getType() != null && intent.getType().equals(MimeType.NFC_DEMO)) {
Parcelable[] rawMsgs = getIntent().getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage msg = (NdefMessage) rawMsgs[0];
NdefRecord cardRecord = msg.getRecords()[0];
String payload = new String(cardRecord.getPayload());
turnBluetoothOn(payload);
}
}
private void turnBluetoothOn(String payload) {
final AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("Alert Dialog");
builder.setMessage(payload);
builder.setIcon(android.R.drawable.ic_dialog_alert);
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
android.os.Process.killProcess(android.os.Process.myPid());
}
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
}
MainActivity:
package com.spotsofmagic.spotsofmagic;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "Activity...";
private NfcAdapter mAdapter;
private TextView mTextView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
// grab our NFC Adapter
mAdapter = NfcAdapter.getDefaultAdapter(this);
// TextView that we'll use to output messages to screen
mTextView = (TextView)findViewById(R.id.text_view);
displayMessage("Loading payload...");
}
private void displayMessage(String message) {
mTextView.setText(message);
}
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
}
}
Here is the code I used to write the tag. This is done on a different app incidentally:
NdefRecord appRecord = NdefRecord.createApplicationRecord("com.spotsofmagic.spotsofmagic");
// record that contains our custom "retro console" game data, using custom MIME_TYPE
byte[] payload = getPayload().getBytes();
byte[] mimeBytes = MimeType.NFC_DEMO.getBytes(Charset.forName("US-ASCII"));
NdefRecord cardRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeBytes,
new byte[0], payload);
NdefMessage message = new NdefMessage(new NdefRecord[] { cardRecord, appRecord});
// Some code here removed for readability
Ndef ndef = Ndef.get(tag);
if (ndef != null) {
ndef.connect();
ndef.writeNdefMessage(message);
Does the NDEF message on the tag contain an Android Application Record? That could explain how MainActivity is launched. However, that can only be the cause if the AAR is the first record of the NDEF message on the tag or if the first record does not match the intent filter.