I want to auto-launch my activity when a beacon comes within 1 meter. This question has been posed before, but I am unable to get mine to work using/modifying his code.
Just like that post, I followed the same steps with the android beacon library through the altbeacon github but still have been unsuccessful.
I also have "compile 'org.altbeacon:android-beacon-library:2.7+'" in build.gradle file.
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.communionchapelefca.ccsatx" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
"android.hardware.bluetooth_le" android:required="false"/>
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name="org.communionchapelefca.ccsatx.SplashScreen" android:label="#string/app_name"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name="org.communionchapelefca.ccsatx.MainActivity" android:label="#string/app_name"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="org.communionchapelefca.ccsatx.MAINACTIVITY"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Application;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.BootstrapNotifier;
import org.altbeacon.beacon.startup.RegionBootstrap;
import java.util.Collection;
public class MainActivity extends Activity implements BootstrapNotifier, RangeNotifier {
public static final String TAG = "MainActivityCCSATX";
private WebView mWebView;
ProgressBar progressBar;
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.activity_main_webview);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.loadUrl("http://communionchapelefca.org/edy-home");
mWebView.setWebViewClient(new HelloWebViewClient());
// begin code for bluetooth permission for android 6
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Android M Permission check

if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access to find Communion Chapel beacons");
builder.setMessage("Please grant location access so this app can detect Communion Chapel beacons.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
}
mAllBeaconsRegion = new Region("all beacons", null, null, null);
mBeaconManager = BeaconManager.getInstanceForApplication(this);
mBackgroundPowerSaver = new BackgroundPowerSaver(this);
mRegionBootstrap = new RegionBootstrap(this, mAllBeaconsRegion);
// By default the AndroidBeaconLibrary will only find AltBeacons. If you wish to make it
// find a different type of beacon, you must specify the byte layout for that beacon's
// advertisement with a line like below. The example shows how to find a beacon with the
// same byte layout as AltBeacon but with a beaconTypeCode of 0xaabb
//
Log.d(TAG, " region. starting ranging");
mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
mBeaconManager.setBackgroundScanPeriod(11000l);
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "coarse location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
// end code for bluetooth permission for android 6
private class HelloWebViewClient extends WebViewClient{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url)
{
webView.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.setVisibility(view.GONE);
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{ //if back key is pressed
if((keyCode == KeyEvent.KEYCODE_BACK)&& mWebView.canGoBack())
{
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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);
}
public void onBackPressed() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
MainActivity.this);
// set title
alertDialogBuilder.setTitle("Exit");
// set dialog message
alertDialogBuilder
.setMessage("Do you really want to exit?")
.setCancelable(false)
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, close
// current activity
MainActivity.this.finish();
}
})
.setNegativeButton("No",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
private RegionBootstrap regionBootstrap;
private BeaconManager mBeaconManager;
private Region region;
private Region mAllBeaconsRegion;
private BackgroundPowerSaver mBackgroundPowerSaver;
private RegionBootstrap mRegionBootstrap;
#Override
public void didDetermineStateForRegion(int arg0, Region arg1) {
// Don't care
}
#Override
public void didEnterRegion(Region arg0) {
mRegionBootstrap.disable();
// This call to disable will make it so the activity below only gets launched the first time a beacon is seen (until the next time the app is launched)
// if you want the Activity to launch every single time beacons come into view, remove this call.
try {
mBeaconManager.startRangingBeaconsInRegion(new Region("all beacons", null, null, null));
mBeaconManager.setRangeNotifier(this);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d(TAG, "Got a didEnterRegion call");
}
#Override
public void didExitRegion(Region arg0) {
// Don't care
}
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
// TODO Auto-generated method stub
if (beacons.size() > 0) {
for (Beacon beacon: beacons) {
Log.d(TAG, "Found a beacon, getting distance");
if(beacon.getDistance()<1)
{
Log.d(TAG, "within 1 minute call");
Intent intent = new Intent(this, MainActivity.class);
// IMPORTANT: in the AndroidManifest.xml definition of this activity, you must set android:launchMode="singleInstance" or you will get two instances
// created when a user launches the activity manually and it gets launched from here.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
}
}
}
}
LogCat from fatal error:
01-28 17:23:38.819 6549 6724 D MainActivityCCSATX: Got a didEnterRegion call
01-28 17:23:38.824 6549 6549 D BluetoothAdapter: STATE_ON
01-28 17:23:38.824 6549 6549 D BluetoothLeScanner: could not find callback wrapper
01-28 17:23:38.824 6549 6549 D BluetoothAdapter: STATE_ON
01-28 17:23:38.824 6549 6549 D BluetoothLeScanner: could not find callback wrapper
01-28 17:23:39.444 6549 6549 W cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 6549
01-28 17:23:40.023 6549 6549 W cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 6549
A few tips:
Try adding a debug line Log.d("Distance:"+beacon.get Distance()); before you check for Distance < 1. Then run the app while watching LogCat output looking for that log line.
Understand that if you have Android 4.x, it may take up to five minutes to detect in the background.
It is always easier to get apps working in the foreground first, and then add background capability. Make sure you can write code to detect your beacon in the foreground.
With help from davidgyoung's code posted on github, I was able to solve the problem.
Related
I have a requirement to show a customised screen over/on the lock screen in android. logically I want to show a screen (an activity) when phone is locked.
[]
I have tried multiple ways to achieve this functionality but no luck yet.
some links which I have followed are :
https://github.com/ShakeebM/Android-LockScreen
Create custom lockscreen for android 4.0 or above?
show web site on Android lock screen
Creating custom LockScreen in android
https://github.com/Kirk-Str/LockScreenApp
As of now I am able to show a custom screen over the lock screen when app is in foreground state but when app is in background/killed state not able to show the custom screen over the lock screen. Please suggest me what I am missing in my code snippet.
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.lockscreen">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round">
<activity
android:name=".sample2.screen.LockScreenActivity"
android:excludeFromRecents="true"
android:label="#string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
android:showOnLockScreen="true"
android:turnScreenOn="false"
android:noHistory="true"
android:exported="true">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".sample2.utils.LockscreenService" >
</service>
<receiver
android:name=".sample2.utils.LockscreenIntentReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
LockscreenService Class:
package com.example.lockscreen.sample2.utils;
import android.app.Notification;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import com.example.lockscreen.R;
public class LockscreenService extends Service {
private BroadcastReceiver mReceiver;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
// Register for Lockscreen event intents
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("LockScreen ::: ","onStartCommand");
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
mReceiver = new LockscreenIntentReceiver();
registerReceiver(mReceiver, filter);
startForeground();
return START_STICKY;
}
// Run service in foreground so it is less likely to be killed by system
private void startForeground() {
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(getResources().getString(R.string.app_name))
.setTicker(getResources().getString(R.string.app_name))
.setContentText("Running")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentIntent(null)
.setOngoing(true)
.build();
startForeground(9999,notification);
}
// Unregister receiver
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}
LockscreenIntentReceiver Class:
package com.example.lockscreen.sample2.utils;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.example.lockscreen.sample2.screen.LockScreenActivity;
public class LockscreenIntentReceiver extends BroadcastReceiver {
// Handle actions and display Lockscreen
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)
|| intent.getAction().equals(Intent.ACTION_SCREEN_ON)
|| intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
start_lockscreen(context);
}
}
// Display lock screen
private void start_lockscreen(Context context) {
Intent mIntent = new Intent(context, LockScreenActivity.class);
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
}
}
LockScreenActivity Class:
package com.example.lockscreen.sample2.screen;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;
import com.example.lockscreen.R;
import com.example.lockscreen.sample2.utils.LockscreenService;
import com.example.lockscreen.sample2.utils.LockscreenUtils;
public class LockScreenActivity extends Activity implements
LockscreenUtils.OnLockStatusChangedListener {
// User-interface
private Button btnUnlock;
// Member variables
private LockscreenUtils mLockscreenUtils;
// Set appropriate flags to make the screen appear over the keyguard
#Override
public void onAttachedToWindow() {
this.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
);
super.onAttachedToWindow();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
);
setContentView(R.layout.activity_lockscreen);
init();
// unlock screen in case of app get killed by system
if (getIntent() != null && getIntent().hasExtra("kill")
&& getIntent().getExtras().getInt("kill") == 1) {
enableKeyguard();
unlockHomeButton();
}
try {
// disable keyguard
disableKeyguard();
// lock home button
lockHomeButton();
Toast.makeText(getApplicationContext(),"lockHomeButton startService", Toast.LENGTH_LONG).show();
// start service for observing intents
startService(new Intent(this, LockscreenService.class));
// listen the events get fired during the call
StateListener phoneStateListener = new StateListener();
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
}
}
private void init() {
mLockscreenUtils = new LockscreenUtils();
btnUnlock = (Button) findViewById(R.id.btnUnlock);
btnUnlock.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// unlock home button and then screen on button press
unlockHomeButton();
}
});
}
// Handle events of calls and unlock screen if necessary
private class StateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
unlockHomeButton();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
case TelephonyManager.CALL_STATE_IDLE:
break;
}
}
};
// Don't finish Activity on Back press
#Override
public void onBackPressed() {
return;
}
// Handle button clicks
#Override
public boolean onKeyDown(int keyCode, android.view.KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
|| (keyCode == KeyEvent.KEYCODE_POWER)
|| (keyCode == KeyEvent.KEYCODE_VOLUME_UP)
|| (keyCode == KeyEvent.KEYCODE_CAMERA)) {
return true;
}
if ((keyCode == KeyEvent.KEYCODE_HOME)) {
return true;
}
return false;
}
// handle the key press events here itself
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP
|| (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN)
|| (event.getKeyCode() == KeyEvent.KEYCODE_POWER)) {
return false;
}
if ((event.getKeyCode() == KeyEvent.KEYCODE_HOME)) {
return true;
}
return false;
}
// Lock home button
public void lockHomeButton() {
mLockscreenUtils.lock(LockScreenActivity.this);
}
// Unlock home button and wait for its callback
public void unlockHomeButton() {
mLockscreenUtils.unlock();
}
// Simply unlock device when home button is successfully unlocked
#Override
public void onLockStatusChanged(boolean isLocked) {
if (!isLocked) {
unlockDevice();
}
}
#Override
protected void onStop() {
super.onStop();
unlockHomeButton();
}
#SuppressWarnings("deprecation")
private void disableKeyguard() {
KeyguardManager mKM = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
KeyguardManager.KeyguardLock mKL = mKM.newKeyguardLock("IN");
mKL.disableKeyguard();
}
#SuppressWarnings("deprecation")
private void enableKeyguard() {
KeyguardManager mKM = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
KeyguardManager.KeyguardLock mKL = mKM.newKeyguardLock("IN");
mKL.reenableKeyguard();
}
//Simply unlock device by finishing the activity
private void unlockDevice()
{
finish();
}
}
Please help me how can I achieve this?
Below code does not work on Android 10 until you manually enable the location from settings. When I go through the Android 10 documentation, it says if you are fetching location from the visible activity, if that was the case you don't need any foreground service, that's the reason I haven't used any service here.
And also as per Android 10 guidelines, after permission getting granted I am calling getLastLocation function.
Implementation is like, on main activity I am fetching location coordinates.
Please help, where in the code am I going wrong?
MainActivity.java
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import androidx.annotation.NonNull;
import com.google.android.material.snackbar.Snackbar;
import androidx.core.app.ActivityCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34;
private FusedLocationProviderClient mFusedLocationClient;
protected Location mLastLocation;
private String mLatitudeLabel;
private String mLongitudeLabel;
private TextView mLatitudeText;
private TextView mLongitudeText;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
mLatitudeLabel = getResources().getString(R.string.latitude_label);
mLongitudeLabel = getResources().getString(R.string.longitude_label);
mLatitudeText = (TextView) findViewById((R.id.latitude_text));
mLongitudeText = (TextView) findViewById((R.id.longitude_text));
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
#Override
public void onStart() {
super.onStart();
if (!checkPermissions()) {
requestPermissions();
} else {
getLastLocation();
}
}
#SuppressWarnings("MissingPermission")
private void getLastLocation() {
mFusedLocationClient.getLastLocation()
.addOnCompleteListener(this, new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
if (task.isSuccessful() && task.getResult() != null) {
mLastLocation = task.getResult();
Log.d("raviraj", "lat is " +mLastLocation.getLatitude());
Log.d("raviraj", "long is " +mLastLocation.getLongitude());
mLatitudeText.setText(String.format(Locale.ENGLISH, "%s: %f",
mLatitudeLabel,
mLastLocation.getLatitude()));
mLongitudeText.setText(String.format(Locale.ENGLISH, "%s: %f",
mLongitudeLabel,
mLastLocation.getLongitude()));
} else {
Log.w("RAVIRAJ", "getLastLocation:exception" +task.getException());
showSnackbar(getString(R.string.no_location_detected));
}
}
});
}
private void showSnackbar(final String text) {
View container = findViewById(R.id.main_activity_container);
if (container != null) {
Snackbar.make(container, text, Snackbar.LENGTH_LONG).show();
}
}
private void showSnackbar(final int mainTextStringId, final int actionStringId,
View.OnClickListener listener) {
Snackbar.make(findViewById(android.R.id.content),
getString(mainTextStringId),
Snackbar.LENGTH_INDEFINITE)
.setAction(getString(actionStringId), listener).show();
}
private boolean checkPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
return permissionState == PackageManager.PERMISSION_GRANTED;
}
private void startLocationPermissionRequest() {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSIONS_REQUEST_CODE);
}
private void requestPermissions() {
boolean shouldProvideRationale =
ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (shouldProvideRationale) {
Log.i(TAG, "Displaying permission rationale to provide additional context.");
showSnackbar(R.string.permission_rationale, android.R.string.ok,
new View.OnClickListener() {
#Override
public void onClick(View view) {
// Request permission
startLocationPermissionRequest();
}
});
} else {
Log.i(TAG, "Requesting permission");
startLocationPermissionRequest();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
Log.i(TAG, "onRequestPermissionResult");
if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) {
if (grantResults.length <= 0) {
// If user interaction was interrupted, the permission request is cancelled and you
// receive empty arrays.
Log.i(TAG, "User interaction was cancelled.");
} else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted.
getLastLocation();
} else {
showSnackbar(R.string.permission_denied_explanation, R.string.settings,
new View.OnClickListener() {
#Override
public void onClick(View view) {
// Build intent that displays the App settings screen.
Intent intent = new Intent();
intent.setAction(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",
BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
}
}
}
}
Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.gms.location.sample.basiclocationsample" >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.Base" >
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/google_maps_key" />
<activity
android:name=".NewMain"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Well there is a problem. Official documentation states that it can be null in some cases
https://developer.android.com/training/location/retrieve-current
Location is turned off in the device settings. The result could be null even if the last location was previously retrieved because disabling location also clears the cache.
The device never recorded its location, which could be the case of a new device or a device that has been restored to factory settings.
Google Play services on the device has restarted, and there is no active Fused Location Provider client that has requested location after the services restarted. To avoid this situation you can create a new client and request location updates yourself. For more information, see Receiving Location Updates.
In your case you can get location only if GPS is ON. Even for last known location.
https://developer.android.com/training/location/retrieve-current#last-known
Please add this permission in AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
and add this to application tag
android:usesCleartextTraffic="true"
I'm developing an app which can read data from a Bluetooth RFID Reader, but everytime i start the BluetoothActivity (it's a tabbed activity), it always shows a ClassCastException, below is my code..
BluetoothActivity class:
package com.siscaproject.sisca.Activity;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.siscaproject.sisca.Fragment.RegisterFragment;
import com.siscaproject.sisca.Fragment.SearchFragment;
import com.siscaproject.sisca.R;
import com.siscaproject.sisca.Utilities.FamsModel;
import com.siscaproject.sisca.Utilities.TSLBluetoothDeviceActivity;
import com.siscaproject.sisca.Utilities.TSLBluetoothDeviceApplication;
import com.uk.tsl.rfid.asciiprotocol.AsciiCommander;
import com.uk.tsl.rfid.asciiprotocol.responders.LoggerResponder;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
public class BluetoothActivity extends TSLBluetoothDeviceActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
#BindView(R.id.viewpager_bluetooth) ViewPager mViewPager;
#BindView(R.id.toolbar_bluetooth) Toolbar mToolbar;
#BindView(R.id.tab_bluetooth) TabLayout mTabLayout;
private FamsModel mModel;
public AsciiCommander getCommander(){
return ((TSLBluetoothDeviceApplication) getApplication()).getCommander();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
ButterKnife.bind(this);
setSupportActionBar(mToolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
setupViewPager(mViewPager);
mTabLayout.setupWithViewPager(mViewPager);
AsciiCommander commander = getCommander();
// Add the LoggerResponder - this simply echoes all lines received from the reader to the log
// and passes the line onto the next responder
// This is added first so that no other responder can consume received lines before they are logged.
commander.addResponder(new LoggerResponder());
// Add a synchronous responder to handle synchronous commands
commander.addSynchronousResponder();
}
private void setupViewPager(ViewPager viewPager){
SectionsPagerAdapter adapter = new SectionsPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new RegisterFragment(), "REGISTER");
adapter.addFragment(new SearchFragment(), "SEARCH");
viewPager.setAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_bluetooth, 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.menu_item_reconnect_reader) {
return true;
}
return super.onOptionsItemSelected(item);
}
public static class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_bluetooth, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragmentList = new ArrayList<>();
private ArrayList<String> fragmentTitleList = new ArrayList<>();
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
#Override
public int getCount() {
// Show 3 total pages.
return fragmentList.size();
}
public void addFragment(Fragment fragment, String title ){
fragmentList.add(fragment);
fragmentTitleList.add(title);
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
}
}
TSLBluetoothDeviceActivity class:
package com.siscaproject.sisca.Utilities;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;
import com.siscaproject.sisca.BuildConfig;
import com.uk.tsl.rfid.DeviceListActivity;
import com.uk.tsl.rfid.asciiprotocol.AsciiCommander;
import java.util.Timer;
import java.util.TimerTask;
public class TSLBluetoothDeviceActivity extends AppCompatActivity {
// Debugging
private static final String TAG = "TSLBTDeviceActivity";
private static final boolean D = BuildConfig.DEBUG;
// Intent request codes
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
private static final int REQUEST_ENABLE_BT = 3;
// Local Bluetooth adapter
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothDevice mDevice = null;
protected AsciiCommander getCommander() {
return ((TSLBluetoothDeviceApplication) getApplication()).getCommander();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// Create the AsciiCommander to talk to the reader (if it doesn't already exist)
if (getCommander() == null) {
try {
TSLBluetoothDeviceApplication app = (TSLBluetoothDeviceApplication) getApplication();
AsciiCommander commander = new AsciiCommander(getApplicationContext());
app.setCommander(commander);
} catch (Exception e) {
fatalError("Unable to create AsciiCommander!");
}
}
}
// Terminate the app with the given message
private void fatalError(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
finish();
}
}, 1800);
}
protected void bluetoothNotAvailableError(String message) {
fatalError(message);
}
#Override
public void onStart() {
super.onStart();
// If no other attempt to connect is ongoing try to connect to last used reader
// Note: When returning from the Device List activity
if (mBluetoothAdapter.isEnabled()) {
if (mDevice == null) {
// Attempt to reconnect to the last reader used
Toast.makeText(this, "Reconnecting to last used reader...", Toast.LENGTH_SHORT).show();
getCommander().connect(null);
}
} else {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
#Override
public void onStop() {
super.onStop();
getCommander().disconnect();
mDevice = null;
}
protected void connectToDevice(Intent deviceData, boolean secure) {
Toast.makeText(this.getApplicationContext(), "Connecting...", Toast.LENGTH_LONG).show();
// Get the device MAC address
String address = deviceData.getExtras()
.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BluetoothDevice object
mDevice = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
if (mDevice != null) {
getCommander().connect(mDevice);
} else {
if (D) Log.e(TAG, "Unable to obtain BluetoothDevice!");
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (D)
Log.d(TAG, "selectDevice() onActivityResult: " + resultCode + " for request: " + requestCode);
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectToDevice(data, true);
}
break;
case REQUEST_CONNECT_DEVICE_INSECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectToDevice(data, false);
}
break;
case REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode != Activity.RESULT_OK) {
// User did not enable Bluetooth or an error occurred
Log.d(TAG, "BT not enabled");
bluetoothNotAvailableError("Bluetooth was not enabled\nApplication Quitting...");
}
}
}
public void selectDevice() {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
}
public void disconnectDevice() {
mDevice = null;
getCommander().disconnect();
}
public void reconnectDevice() {
getCommander().connect(null);
}
}
The error log:
11-21 14:47:54.836 18956-18956/com.siscaproject.sisca E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.siscaproject.sisca, PID: 18956
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.siscaproject.sisca/com.siscaproject.sisca.Activity.BluetoothActivity}: java.lang.ClassCastException: android.app.Application cannot be cast to com.siscaproject.sisca.Utilities.TSLBluetoothDeviceApplication
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2318)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2396)
at android.app.ActivityThread.access$800(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1293)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.siscaproject.sisca.Utilities.TSLBluetoothDeviceApplication
at com.siscaproject.sisca.Activity.BluetoothActivity.getCommander(BluetoothActivity.java:51)
at com.siscaproject.sisca.Utilities.TSLBluetoothDeviceActivity.onCreate(TSLBluetoothDeviceActivity.java:45)
at com.siscaproject.sisca.Activity.BluetoothActivity.onCreate(BluetoothActivity.java:57)
at android.app.Activity.performCreate(Activity.java:5411)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2396)
at android.app.ActivityThread.access$800(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1293)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)
I've followed this code from an app that works fine, but when I implemented it in my project it always shows this error, I'm not sure what I'm doing wrong.
---EDIT---
TSLBluetoothDeviceApplication class:
package com.siscaproject.sisca.Utilities;
import android.app.Application;
import com.uk.tsl.rfid.asciiprotocol.AsciiCommander;
public class TSLBluetoothDeviceApplication extends Application {
private static AsciiCommander commander = null;
/// Returns the current AsciiCommander
public AsciiCommander getCommander() {
return commander;
}
/// Sets the current AsciiCommander
public void setCommander(AsciiCommander _commander) {
commander = _commander;
}
}
Android Manifest:
<?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.siscaproject.sisca">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<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"
tools:replace="android:icon">
<activity
android:name=".Activity.LoginActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Activity.BluetoothTestActivity"
android:theme="#style/StandardTheme" />
<activity
android:name=".Activity.HomeActivity"
android:label="#string/title_activity_home"
android:theme="#style/AppTheme" />
<meta-data
android:name="com.google.android.gms.vision.DEPENDENCIES"
android:value="barcode" />
<activity android:name=".Activity.QRActivity" />
<activity
android:name=".Activity.BluetoothActivity"
android:label="#string/title_activity_bluetooth"
android:theme="#style/AppTheme"></activity>
</application>
</manifest>
getApplication() inside an activity returns an object of type Application. In your case you are trying to cast this object into TSLBluetoothDeviceApplication which, as defined by you, is an Activity type class.
As I see, you are trying to call getCommander() which is defined already in your TSL activity class. I assume you want getCommander() method from another class.. Make sure which one is.
public AsciiCommander getCommander(){
return ((TSLBluetoothDeviceApplication) getApplication()).getCommander();
}
This method is already inside TSLBluetoothDeviceApplication class.. I don't know what are you trying to achieve by trying to call same method which is already in your current class.
EDIT:
After the edited post, we noticed that the class was properly implemented, just forgot to add
android:name="com.path.to.ApplicationClass" into the Manifestfile under <application/> tag.
I will let the above answer also, because it may help others
Happy coding <3
It's clear that your application class is not used. You need to add it to your xml Application tag like this:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:name="com.siscaproject.sisca.Utilities. TSLBluetoothDeviceApplication"
android:theme="#style/AppTheme"
tools:replace="android:icon">
and the only change is adding android:name="com.siscaproject.sisca.Utilities. TSLBluetoothDeviceApplication" to the Application tag as your customized class.
Im currently working at an app for controlling an arduino via bluetooth. I added some Activitys for menus and so on. Yesterday I added a new Activity for connecting my device to the bluetooth module.
Is it even possible to connect to the device in one activity and actually controlling (sending letters) it in another Activity?
With that said the app crashes every time I try to open the activity with the bluetooth code in it. Every other Activity works without any problem.
I hope somebody can help.
Here is my Code:
MainActivity.java (the activity which will control the module):
package com.car.bluetooth.bluetoothcar;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CheckBox;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.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();
//MENÜPUNKTE
if (id == R.id.action_settings) {
Intent settingsintent = new Intent(MainActivity.this,
settingsactivity.class);
startActivity(settingsintent);
return false;
}
if (id == R.id.action_connect) {
Intent connectintent = new Intent(MainActivity.this,
connectactivity.class);
startActivity(connectintent);
return false;
}
return super.onOptionsItemSelected(item);
}
//SeekBars
private SeekBar seekBarGas;
private TextView textViewGas;
private SeekBar seekBarSteering;
private TextView textViewSteering;
private CheckBox backwards_checkBox;
boolean rückwärts_var = false;
boolean safeMode;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
seekBarGas = (SeekBar) findViewById(R.id.seekBarGas);
textViewGas = (TextView) findViewById(R.id.textViewGas);
seekBarGas.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
textViewGas.setText(progress + " / " + seekBarGas.getMax());
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
seekBarGas.setProgress(0);
}
});
seekBarSteering = (SeekBar) findViewById(R.id.seekBarSteering);
textViewSteering = (TextView) findViewById(R.id.textViewSteering);
seekBarSteering.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
textViewSteering.setText(progress + " / " + seekBarSteering.getMax());
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
seekBarSteering.setProgress(3);
}
});
//GET DATA Settings
Intent safeMode_Intent = getIntent();
safeMode = safeMode_Intent.getBooleanExtra("safeMode", false);
//Rückwärts
CheckBox backwards_checkBox=(CheckBox)findViewById(R.id.backwards_checkBox);
backwards_checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (((CheckBox)v).isChecked()) {
Toast.makeText(getApplicationContext(), "Rückwärts", Toast.LENGTH_SHORT).show();
rückwärts_var = true;
if (safeMode == true) {
seekBarGas.setMax(2);
}
}
else{
Toast.makeText(getApplicationContext(), "Vorwärts", Toast.LENGTH_SHORT).show();
rückwärts_var = false;
if (safeMode == true){
seekBarGas.setMax(5);
}
}
}
});
//Bluetooth
if (btAdapter == null){
Toast.makeText(getApplicationContext(), "Bluetooth wird auf diesem Gerät nicht unterstützt", Toast.LENGTH_LONG).show();
}
}
}
BT_Classic.java (the activity which connects to the module) :
package com.car.bluetooth.bluetoothcar;
import androidx.appcompat.app.AppCompatActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Set;
public class BT_Classic extends AppCompatActivity {
private Button pairedButton;
private Button discoveredButton;
private Button btonButton;
private Button btoffButton;
ListView list;
private static final int REQUEST_ENABLED = 0;
private static final int REQUEST_DISCOVERABLE = 0;
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bt__classic);
pairedButton = (Button) findViewById(R.id.pairedButton);
discoveredButton = (Button) findViewById(R.id.discoveredButton);
list = (ListView) findViewById(R.id.list) ;
//Pairing Button
pairedButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
ArrayList<String> devices = new ArrayList<String>();
for (BluetoothDevice bt : pairedDevices){
devices.add(bt.getName());
}
ArrayAdapter arrayAdapter = new ArrayAdapter(BT_Classic.this, android.R.layout.simple_list_item_1, devices);
list.setAdapter(arrayAdapter);
}
});
discoveredButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!btAdapter.isDiscovering()){
Intent bton = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(bton, REQUEST_DISCOVERABLE);
}
}
});
btonButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent bton = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(bton, REQUEST_ENABLED);
}
});
btoffButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
btAdapter.disable();
}
});
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.car.bluetooth.bluetoothcar">
<uses-feature android:name="android.hardware.bluetooth" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<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"
android:label="Bluetooth Car"
android:screenOrientation="landscape"
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=".connectactivity"
android:label="Connect"
android:screenOrientation="landscape" />
<activity
android:name=".settingsactivity"
android:label="Settings"
android:screenOrientation="landscape" />
<activity
android:name=".BT_LE"
android:label="Connect Bluetooth Low Energy"
android:screenOrientation="landscape"/>
<activity
android:name=".BT_Classic"
android:label="Connect Bluetooth Classic"
android:screenOrientation="landscape"
></activity>
</application>
build.gradle (Module:app) :
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.car.bluetooth.bluetoothcar"
minSdkVersion '16'
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
implementation 'android.arch.navigation:navigation-fragment:1.0.0-alpha05'
implementation 'android.arch.navigation:navigation-ui:1.0.0-alpha05'
implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
implementation 'com.google.android.material:material:1.0.0-beta01'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
}
Crashlog:
2018-09-12 17:25:36.957 10178-10178/com.car.bluetooth.bluetoothcar
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.car.bluetooth.bluetoothcar, PID: 10178
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.car.bluetooth.bluetoothcar/com.car.bluetooth.bluetoothcar.BT_Classic}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2830)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2909)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1606)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6592)
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:769)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at com.car.bluetooth.bluetoothcar.BT_Classic.onCreate(BT_Classic.java:78)
at android.app.Activity.performCreate(Activity.java:6984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1235)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2783)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2909)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1606)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6592)
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:769)
btonButton and btoffButton are not initialized and equals null.
You should initialize them with findViewById() like you do with pairedButton
btonButton = (Button) findViewById(R.id.put_here_btn_on_id);
btoffButton = (Button) findViewById(R.id.put_here_btn_off_id);
btonButton and btoffButton have not been initialised yet and then you are calling setonClickListener this causes NPE
Inside onCreate initialise like this:
btonButton = (Button) findViewById(R.id.btonButton);
btoffButton = (Button) findViewById(R.id.btoffButton);
Please help me to get the facebook friends from my profile using 3.14 SDK. There is no error in the code but the problem is getting empty list while fetching friends in my profile. I am getting the error in logcat saying .
05-08 16:18:49.252: E/ActivityThread(25644): Failed to find provider info for com.facebook.orca.provider.PlatformProvider<br>
05-08 16:42:20.453: I/QCNEA(28696): |NIMS| getaddrinfo: hostname graph.facebook.com servname NULL numeric 4 appname <br>
05-08 16:51:32.482: D/Request(31861): Warning: Sessionless Request needs token but missing either application ID or client token<br>
Also i am producing the complete code for your reference below
FriendPickerApplication.java*
package com.facebook.samples.friendpicker;
import android.app.Application;
import com.facebook.model.GraphUser;
import java.util.List;
// We use a custom Application class to store our minimal state data (which users have been selected).
// A real-world application will likely require a more robust data model.
public class FriendPickerApplication extends Application {
private List<GraphUser> selectedUsers;
public List<GraphUser> getSelectedUsers() {
return selectedUsers;
}
public void setSelectedUsers(List<GraphUser> selectedUsers) {
this.selectedUsers = selectedUsers;
}
}<br>
FriendPickerSampleActivity.java
package com.facebook.samples.friendpicker;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.facebook.AppEventsLogger;
import com.facebook.Session.NewPermissionsRequest;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import com.facebook.model.GraphUser;
import com.facebook.Session;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class FriendPickerSampleActivity extends FragmentActivity {
private static final List<String> PERMISSIONS = new ArrayList<String>() {
{
add("user_friends");
add("public_profile");
}
};
private static final int PICK_FRIENDS_ACTIVITY = 1;
private Button pickFriendsButton;
private TextView resultsTextView;
private UiLifecycleHelper lifecycleHelper;
boolean pickFriendsWhenSessionOpened;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
resultsTextView = (TextView) findViewById(R.id.resultsTextView);
pickFriendsButton = (Button) findViewById(R.id.pickFriendsButton);
pickFriendsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onClickPickFriends();
}
});
lifecycleHelper = new UiLifecycleHelper(this, new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChanged(session, state, exception);
}
});
lifecycleHelper.onCreate(savedInstanceState);
ensureOpenSession();
}
#Override
protected void onStart() {
super.onStart();
// Update the display every time we are started.
displaySelectedFriends(RESULT_OK);
}
#Override
protected void onResume() {
super.onResume();
// Call the 'activateApp' method to log an app event for use in analytics and advertising reporting. Do so in
// the onResume methods of the primary Activities that an app may be launched into.
AppEventsLogger.activateApp(this);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case PICK_FRIENDS_ACTIVITY:
displaySelectedFriends(resultCode);
break;
default:
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
break;
}
}
private boolean ensureOpenSession() {
if (Session.getActiveSession() == null ||
!Session.getActiveSession().isOpened()) {
Session.openActiveSession(
this,
true,
PERMISSIONS,
new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChanged(session, state, exception);
}
});
return false;
}
return true;
}
private boolean sessionHasNecessaryPerms(Session session) {
if (session != null && session.getPermissions() != null) {
for (String requestedPerm : PERMISSIONS) {
if (!session.getPermissions().contains(requestedPerm)) {
return false;
}
}
return true;
}
return false;
}
private List<String> getMissingPermissions(Session session) {
List<String> missingPerms = new ArrayList<String>(PERMISSIONS);
if (session != null && session.getPermissions() != null) {
for (String requestedPerm : PERMISSIONS) {
if (session.getPermissions().contains(requestedPerm)) {
missingPerms.remove(requestedPerm);
}
}
}
return missingPerms;
}
private void onSessionStateChanged(final Session session, SessionState state, Exception exception) {
if (state.isOpened() && !sessionHasNecessaryPerms(session)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.need_perms_alert_text);
builder.setPositiveButton(
R.string.need_perms_alert_button_ok,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
session.requestNewReadPermissions(
new NewPermissionsRequest(
FriendPickerSampleActivity.this,
getMissingPermissions(session)));
}
});
builder.setNegativeButton(
R.string.need_perms_alert_button_quit,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.show();
} else if (pickFriendsWhenSessionOpened && state.isOpened()) {
pickFriendsWhenSessionOpened = false;
startPickFriendsActivity();
}
}
private void displaySelectedFriends(int resultCode) {
String results = "";
FriendPickerApplication application = (FriendPickerApplication) getApplication();
Collection<GraphUser> selection = application.getSelectedUsers();
if (selection != null && selection.size() > 0) {
ArrayList<String> names = new ArrayList<String>();
for (GraphUser user : selection) {
names.add(user.getName());
}
results = TextUtils.join(", ", names);
} else {
results = "<No friends selected>";
}
resultsTextView.setText(results);
}
private void onClickPickFriends() {
startPickFriendsActivity();
}
private void startPickFriendsActivity() {
if (ensureOpenSession()) {
Intent intent = new Intent(this, PickFriendsActivity.class);
// Note: The following line is optional, as multi-select behavior is the default for
// FriendPickerFragment. It is here to demonstrate how parameters could be passed to the
// friend picker if single-select functionality was desired, or if a different user ID was
// desired (for instance, to see friends of a friend).
PickFriendsActivity.populateParameters(intent, null, true, true);
startActivityForResult(intent, PICK_FRIENDS_ACTIVITY);
} else {
pickFriendsWhenSessionOpened = true;
}
}
} <br>
PickFriendsActivity.java
package com.facebook.samples.friendpicker;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.widget.Toast;
import com.facebook.FacebookException;
import com.facebook.model.GraphUser;
import com.facebook.widget.FriendPickerFragment;
import com.facebook.widget.PickerFragment;
import java.util.List;
public class PickFriendsActivity extends FragmentActivity {
FriendPickerFragment friendPickerFragment;
public static void populateParameters(Intent intent, String userId,
boolean multiSelect, boolean showTitleBar) {
intent.putExtra(FriendPickerFragment.USER_ID_BUNDLE_KEY, userId);
intent.putExtra(FriendPickerFragment.MULTI_SELECT_BUNDLE_KEY,
multiSelect);
intent.putExtra(FriendPickerFragment.SHOW_TITLE_BAR_BUNDLE_KEY,
showTitleBar);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pick_friends_activity);
FragmentManager fm = getSupportFragmentManager();
if (savedInstanceState == null) {
// First time through, we create our fragment programmatically.
final Bundle args = getIntent().getExtras();
friendPickerFragment = new FriendPickerFragment(args);
fm.beginTransaction()
.add(R.id.friend_picker_fragment, friendPickerFragment)
.commit();
} else {
// Subsequent times, our fragment is recreated by the framework and
// already has saved and
// restored its state, so we don't need to specify args again. (In
// fact, this might be
// incorrect if the fragment was modified programmatically since it
// was created.)
friendPickerFragment = (FriendPickerFragment) fm
.findFragmentById(R.id.friend_picker_fragment);
}
friendPickerFragment
.setOnErrorListener(new PickerFragment.OnErrorListener() {
#Override
public void onError(PickerFragment<?> fragment,
FacebookException error) {
PickFriendsActivity.this.onError(error);
}
});
friendPickerFragment
.setOnDoneButtonClickedListener(new PickerFragment.OnDoneButtonClickedListener() {
#Override
public void onDoneButtonClicked(PickerFragment<?> fragment) {
// We just store our selection in the Application for
// other activities to look at.
FriendPickerApplication application = (FriendPickerApplication) getApplication();
application.setSelectedUsers(friendPickerFragment
.getSelection());
setResult(RESULT_OK, null);
finish();
}
});
}
private void onError(Exception error) {
String text = getString(R.string.exception, error.getMessage());
Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
toast.show();
}
#Override
protected void onStart() {
super.onStart();
try {
FriendPickerApplication application = (FriendPickerApplication) getApplication();
List<GraphUser> selectedUsers = application.getSelectedUsers();
if (selectedUsers != null && !selectedUsers.isEmpty()) {
friendPickerFragment.setSelection(selectedUsers);
}
// Load data, unless a query has already taken place.
friendPickerFragment.loadData(false);
} catch (Exception ex) {
onError(ex);
}
}
}<br>
Androidmanifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.facebook.samples.friendpicker"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".FriendPickerApplication"
android:icon="#drawable/icon"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar" >
<activity
android:name="FriendPickerSampleActivity"
android:label="#string/app_name"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="PickFriendsActivity"
android:label="Pick Friends" >
</activity>
<activity
android:name="com.facebook.LoginActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.Translucent.NoTitleBar" />
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/app_id" />
<provider
android:name="com.facebook.NativeAppCallContentProvider"
android:authorities="com.facebook.app.NativeAppCallContentProvider1441068969495032"
android:exported="true" />
</application>
</manifest>
After a long struggle I found my own solution to the above question. Facebook have released their new SDK recently to enhance the level of security. There are a few requirements to use facebook SDK in your app.
The app should be sent for submission and needs to be approved by facebook to be use inside facebook, to enable your own app to show friends details, access locations and other special permissions The approval formalities are similar to the ones for app store in Google Play.
The application must be listed in Google Play, or you may be able to integrate it as a test user (i.e like beta testing in Google Play).
The application should have a proper package name, launching activity, domain name, website url and email.
The app id registered must match with an app name and hash key that must be generated for a user developing on different machines
The basic application information, including screenshots, description, and app logo needs to be added
Once after the successful approval, an "active" symbol will be displayed near your app name.
I hope this will be useful for others!!!
More information on Facebook site.
After spending a good number of hours trying to resolve this, I would like to add the following for anyone still looking:
The only friends you will see in the list with user_friend permissions is other users that have logged in and approved your app. I.e. if no-one else is using it, you will se noone in the list (I know, if you read it all, this is obvious)
The easiest way of testing this is to set up a test app, add test users in the dev interface for facebook under "Roles", make sure that the test users are friends and then log in with each use on your app. Only then will they show up in the list.
Unless you ask for it specifically, your app will not have the user_friends permission (you do not, however, need to review this with Facebook as it is part of the basic permissions) - I added it to the onCreateView in the Splash Segment (from the Scrumptios/Login sample in the SDK) like this:
LoginButton loginButton = (LoginButton) view.findViewById(R.id.login_button);
loginButton.setReadPermissions(Arrays.asList("user_friends"));
Use the Facebook test user interface to login on facebook as your test user to validate that they have been accepting the correct permissions (under apps).