I made a Bluetooth app. It works fine in Nougat, Marshmallow, Jelly Bean, KitKat but for reason, it crashes in Android Lollipop when Discover button (which discovers all the discoverable devices) is clicked.
Here is the method which gets triggered on clicking Discover button -
private void discoverDevices() {
Log.d(TAG, "btnDiscover: Looking for unpaired devices.");
if(mBluetoothAdapter.isDiscovering()){
mBluetoothAdapter.cancelDiscovery();
Log.d(TAG, "btnDiscover: Canceling discovery.");
//check BT permissions in manifest
checkBTPermissions();
mBluetoothAdapter.startDiscovery();
IntentFilter discoverDevicesIntent = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mBroadcastReceiver3, discoverDevicesIntent);
}
if(!mBluetoothAdapter.isDiscovering()){
//check BT permissions in manifest
checkBTPermissions();
mBluetoothAdapter.startDiscovery();
IntentFilter discoverDevicesIntent = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mBroadcastReceiver3, discoverDevicesIntent);
}
}
CheckBTPermissions()-
private void checkBTPermissions() {
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP){
int permissionCheck = this.checkSelfPermission("Manifest.permission.ACCESS_FINE_LOCATION");
permissionCheck += this.checkSelfPermission("Manifest.permission.ACCESS_COARSE_LOCATION");
if (permissionCheck != 0) {
this.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1001); //Any number
}
}else{
Log.d(TAG, "checkBTPermissions: No need to check permissions. SDK version
=< LOLLIPOP.");
}
}
Permissions in Manifest file-
<uses-feature android:name="android.hardware.bluetooth" />
<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.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
build.gradle-
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "com.example.hpi5.bluetooth"
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
I have not tested this app on Lollipop myself as I don't have any device running on Android L. I got to know about the crash from a friend of mine.
EDIT: I managed to arrange the logs.
07-07 19:29:00.219 30852-30852/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.hpi5.bluetooth, PID: 30852
java.lang.NoSuchMethodError: No virtual method checkSelfPermission(Ljava/lang/String;)I in class Lcom/example/hpi5/bluetooth/MainActivity; or its super classes (declaration of 'com.example.hpi5.bluetooth.MainActivity' appears in /data/app/com.example.hpi5.bluetooth-1/base.apk)
at com.example.hpi5.bluetooth.MainActivity.checkBTPermissions(MainActivity.java:243)
at com.example.hpi5.bluetooth.MainActivity.discoverDevices(MainActivity.java:230)
at com.example.hpi5.bluetooth.MainActivity.access$100(MainActivity.java:24)
at com.example.hpi5.bluetooth.MainActivity$7.onClick(MainActivity.java:189)
at android.view.View.performClick(View.java:4923)
at android.view.View$PerformClick.run(View.java:20341)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5717)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
The exception says it all, the method checkSelfPermission is only available on API 23 onwards. If you want to check permission with API 21, use the Android support library and ContextCompat.checkSelfPermission
Edit: Also, location permissions for Bluetooth are only required from API 23 onwards.
So I arranged the logs somehow and found even for devices running on Lollipop the following condition was evaluating to true
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP){
//code here
}
and because of this, the app was crashing on clicking the Discover button.
So, I just changed the above condition to -
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
}
The app is working fine on Lollipop devices now.
Why was it crashing on Lollipop devices earlier?
So, my friend's device was running on Android version 5.1.1 and that is why the condition was evaluating to true. And since checkSelfPermission was introduced in API level 23 (Android M), the app could not find it and thus crashed.
Runtime permission system was added in API 23, so you shouldn't check permissions under that API. And logcat tells you that it can't find a method that didn't existed in API 21.
Related
I am using the Android studio Arctic Fox version. I need to implement an automated notification app that is going to send notifications by date. I am running my apps on an actual device with the 6.0.1 android version. I have connected fcm and set up the dependencies as well. But token is not showing on logcat. Also registered the app in firebase. Any ideas why this is happening?
build:gradle(:app)
plugins {
id 'com.android.application'
id 'com.google.gms.google-services'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.f1"
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'com.google.firebase:firebase-messaging:22.0.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
build:gradle(module)
dependencies {
classpath "com.android.tools.build:gradle:7.0.2"
classpath 'com.google.gms:google-services:4.3.10'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
manifest.xml
<service android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
MyFirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onNewToken(#NonNull String s)
{
super.onNewToken(s);
Log.d("My token", "Refreshed Token"+s);
sendRegistrationToServer(s);
}
private void sendRegistrationToServer(String s) {
}
}
If you ran the app on the device before adding the MyFirebaseMessagingService code, it probably already generated a token then. Adding the MyFirebaseMessagingService does not generate a new token, so your onNewToken will not be called.
The two options to get the token in that case are:
Call FirebaseMessaging.getInstance().getToken() from (for example) you main activity and call the same sendRegistrationToServer there.
Delete the app and its data after you added the FirebaseMessaging.getInstance().getToken() code, and reinstall the app. Deleting the data deletes the token, so then when you run the app it will generate a new token and call your onNewToken.
The code below crashes my app before it gets a chance to run:
public class MainActivity extends AppCompatActivity {
EditText txtname,txtage,txtphone,txtheight;
Button btnsave;
DatabaseReference reff;
Schedule schedule;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtname=(EditText)findViewById(R.id.txtname);
txtage=(EditText)findViewById(R.id.txtage);
txtphone=(EditText)findViewById(R.id.txtphone);
txtheight=(EditText)findViewById(R.id.txtheight);
btnsave=(Button)findViewById(R.id.btnsave);
schedule=new Schedule();
reff=FirebaseDatabase.getInstance().getReference().child("Schedule");
btnsave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int agea=Integer.parseInt(txtage.getText().toString().trim());
Float hit=
Float.parseFloat(txtheight.getText().toString().trim());
Long phn=Long.parseLong(txtphone.getText().toString().trim());
schedule.setName(txtname.getText().toString().trim());
schedule.setAge(agea);
schedule.setHt(hit);
schedule.setPh(phn);
reff.child("schedule1").setValue(schedule);
Toast.makeText(MainActivity.this, "Data inserted successfully",
Toast.LENGTH_LONG).show();
}
});
Toast.makeText(MainActivity.this, "Firebase connection Success",
Toast.LENGTH_LONG).show();
}
}
I am new to Firebase and not sure where I am going wrong, the code runs when my reff = firebase line is commented out so there must be a problem with the way I am referencing, but obviously, the code does nothing without the connection to the database, if anyone could help.
Logs from crash as requested:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.notihng/com.example.notihng.MainActivity}: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process com.example.notihng. Make sure to call FirebaseApp.initializeApp(Context) first.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2946)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3081)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6806)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
Caused by: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process com.example.notihng. Make sure to call FirebaseApp.initializeApp(Context) first.
at com.google.firebase.FirebaseApp.getInstance(com.google.firebase:firebase-common##16.0.4:240)
at com.google.firebase.database.FirebaseDatabase.getInstance(com.google.firebase:firebase-database##16.0.6:67)
at com.example.notihng.MainActivity.onCreate(MainActivity.java:28)
at android.app.Activity.performCreate(Activity.java:7210)
at android.app.Activity.performCreate(Activity.java:7201)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2926)
... 11 more
App Gradle File:
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.notihng"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-
optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.android.support.constraint:constraint-
layout:1.1.3'
implementation 'com.google.firebase:firebase-database:16.0.6'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation
'com.android.support.test.espresso:espresso-
core:3.0.2'
}
apply plugin: 'com.google.gms.google-services'
The crash report clearly says the problem in your code.
Make sure to call FirebaseApp.initializeApp(Context) first
You need to initialize it first before using it like the following.
FirebaseApp.initializeApp(this);
In your build.gradle file, there are two declarations of adding the following plugin.
apply plugin: 'com.google.gms.google-services'
I would like to suggest you remove the first one. Keep the one at the end of your gradle file.
Got it working guys thanks for all the help.
It was the dependencies in project gradle, when i changed them to
classpath 'com.android.tools.build:gradle:3.3.1'
classpath 'com.google.gms:google-services:3.0.0'
It promted me to install new sdk files.
Not sure if the default dependencies just werent working or the downloading files was the fix, but its working now anyways, thanks again.
I received feedbacks from users that the cast button wouldn't show up.
At first I thought the problem might be that my app was not properly published since I was the only one being able to see the button.
After a few tests, the cast receiver app and the cast device do not seem to be the problem.I figured it might be a compatibility issue since the button wouldn't show up for devices running api>= 26 but would on api 24.
Upgrading my implementations and my api from 24 to 27 target doesn't solve the problem.
compileSdkVersion 27
defaultConfig {
applicationId 'AppId'
minSdkVersion 16
targetSdkVersion 27
versionCode 2
versionName '1.1'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
Here are my dependencies:
dependencies {
implementation 'com.github.dmytrodanylyk.shadow-layout:library:1.0.3'
implementation 'com.github.medyo:fancybuttons:1.8.4'
implementation 'com.pes.materialcolorpicker:library:1.2.0'
implementation fileTree(include: ['*.jar'], dir: 'libs')
//implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
implementation 'com.google.firebase:firebase-core:15.0.0'
testImplementation 'junit:junit:4.12'
implementation 'com.google.android.gms:play-services-cast-framework:15.0.1'
implementation 'com.android.support:mediarouter-v7:27.1.1'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.sofakingforever.libraries:iconpack:0.0.7#aar'
}
Note: firebase isn't at its highest version because gms and firebase have to be a the same version.
I have exactly the same issue using the sample app "cast hello world" from the Cast documentations. It works on api 24 but not higher.
Here is my Options.java:
public class Options implements OptionsProvider {
#Override
public CastOptions getCastOptions(Context context) {
return new CastOptions.Builder()
.setReceiverApplicationId(context.getString(R.string.cast_app_id))
.build();
}
#Override
public List<SessionProvider> getAdditionalSessionProviders(Context context) {
return null;
}
}
Here is my menu inflater:
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.main, menu);
// Setup the menu item for connecting to cast devices
CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item);
return true;
}
Please help.
I made an app which was working fine. I am not sure what caused my app to not support on any devices after it is published in the play store.
Here is my gradle file.
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "############"
minSdkVersion 15
targetSdkVersion 26
versionCode 12
versionName "12"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
The only change I added onto one of my classes is this.
if (Build.VERSION_CODES.N <= android.os.Build.VERSION.SDK_INT) {
// FileProvider required for Android 7. Sending a file URI throws exception.
photoURI = FileProvider.getUriForFile(this,
BuildConfig.APPLICATION_ID + ".provider",
photoFile);
} else {
// For older devices:
// Samsung Galaxy Tab 7" 2 (Samsung GT-P3113 Android 4.2.2, API 17)
// Samsung S3
photoURI = Uri.fromFile(photoFile);
}
That was a code I got to check what the current build version is. Does this help?
How can i make it available to back to all devices as it was before ?
To me the issue was this line in the manifest file:
<uses-feature android:name="android.hardware.camera2" android:required="true" />
The correct way to do it is like this - where the required is set to false
<uses-feature android:name="android.hardware.camera2" android:required="false" />
Trying to compile renderscript without using the support library.
I'm using Android Studio with android sdk build tools 23.0.1 (I also have 20 and 23.0.0). Trying to compile it for Samsung galaxy s5 plus. (Android 5.0.2 API 21)
The inverse.rs file is located in:
/src/main/rs/
In my mainactivity.java:
RenderScript rs = RenderScript.create(this.getApplicationContext());
Allocation allocIn;
allocIn = Allocation.createFromBitmap(rs, bitmap);
Allocation allocOut = Allocation.createTyped(rs, allocIn.getType());
ScriptC_inverse inverse = new ScriptC_inverse(rs); //crashes on this line
inverse.forEach_invert(allocIn,allocOut);
rs.finish();
allocOut.copyTo(bitmap);
allocOut.destroy();
allocIn.destroy();
rs.destroy();
inverse.rs:
#pragma version(1)
#pragma rs java_package_name(com.example.dries.myocrtest)
uchar4 __attribute__((kernel)) invert(uchar4 in) {
uchar4 out = in;
out.r = 255 - in.r;
out.g = 255 - in.g;
out.b = 255 - in.b;
return out;
}
build.gradle file:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "com.example.dries.myocrtest"
minSdkVersion 17
targetSdkVersion 23
versionCode 1
versionName "1.0"
renderscriptTargetApi 23
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile project(':tesstwo')
compile project(':fileExplorer')
}
And this is my error log:
12384-12384/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.dries.myocrtest, PID: 12384
android.renderscript.RSRuntimeException: Loading of ScriptC script failed.
at android.renderscript.ScriptC.<init>(ScriptC.java:82)
at com.example.dries.myocrtest.ScriptC_inverse.<init>(ScriptC_inverse.java:34)
at com.example.dries.myocrtest.MainActivity.ocr(MainActivity.java:126)
at com.example.dries.myocrtest.MainActivity.onOptionsItemSelected(MainActivity.java:86)
at android.app.Activity.onMenuItemSelected(Activity.java:3030)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:325)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:147)
at android.support.v7.internal.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100)
at android.support.v7.app.AppCompatDelegateImplV7.onMenuItemSelected(AppCompatDelegateImplV7.java:609)
at android.support.v7.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:811)
at android.support.v7.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:153)
at android.support.v7.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:958)
at android.support.v7.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:948)
at android.support.v7.internal.view.menu.MenuPopupHelper.onItemClick(MenuPopupHelper.java:191)
at android.widget.AdapterView.performItemClick(AdapterView.java:334)
at android.widget.AbsListView.performItemClick(AbsListView.java:1531)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3667)
at android.widget.AbsListView$3.run(AbsListView.java:5585)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6066)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1388)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1183)
Set targetSdkVersion to the supported level of your S5, as 23 will cause this to be only runnable on API level 23+ devices. We don't use minSdkVersion. We use your targetSdkVersion when compiling for RS.