I am getting runtime error, trying to start a boot-time service. Its failing but there is no hint I can see. The intent is finding the Service but it doesn't get to onCreate or onStart.
public class ControlReceiver extends BroadcastReceiver
{
/**
* #see android.content.BroadcastReceiver#onReceive(Context,Intent)
*/
#Override
public void onReceive(Context context, Intent intent)
{
Intent service = new Intent(context, MyApp.class);
Log.d("rcvr", "Received intent:" + intent.getAction());
context.startService(service);
}
}
The manifest:
<manifest
android:versionCode="1"
android:versionName="1.0"
package="com.company.package"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="10"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_GPS"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS"/>
<uses-permission android:name="android.permission.ACCESS_CELL_ID"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.SET_ACTIVITY_WATCHER"/>
<uses-permission android:name="android.permission.STATUS_BAR"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
<uses-permission android:name="android.permission.CONTROL_LOCATION_UPDATES"/>
<uses-permission android:name="android.permission.SET_DEBUG_APP"/>
<uses-permission android:name="android.permission.BATTERY_STATS"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN"/>
<uses-permission android:name="android.permission.DIAGNOSTIC"/>
<uses-permission android:name="android.permission.DEVICE_POWER"/>
<uses-permission android:name="android.permission.DUMP"/>
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
<uses-permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.PERSISTENT_ACTIVITY"/>
<uses-permission android:name="android.permission.HARDWARE_TEST"/>
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/mod_name"
android:name=".MyApp">
<!-- We declare our service here -->
<service
android:enabled="true"
android:exported="true"
android:icon="#drawable/ic_launcher"
android:label="#string/serv_name"
android:name=".MyApp"
android:process=":my_process">
<intent-filter>
<action android:name="com.company.package.MY_INTENT" />
</intent-filter>
</service>
<receiver
android:name=".ControlReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE" />
</intent-filter>
</receiver>
<receiver
android:name=".BatteryHelper" >
<intent-filter>
<action android:name="android.intent.action.BATTERY_OKAY"/>
<action android:name="android.intent.action.BATTERY_CHANGED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.BATTERY_LOW"/>
<category android:name="android.intent.category.INFO"/>
</intent-filter>
</receiver>
</application>
</manifest>
The exception thrown
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to instantiate application com.company.package.MyApp: java.lang.ClassCastException: com.company.package.MyApp cannot be cast to android.app.Application
at android.app.LoadedApk.makeApplication(LoadedApk.java:529)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4442)
at android.app.ActivityThread.access$1300(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1305)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4945)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
Update
When I removed android:name=".MyApp" for the application from the manifest, the service started. Anyone know why?
when I removed android:name=".MyApp" for the application from the manifest, the service started. Anyone know why?
The reason for this is most likely the fact that your MyApp class does not extend android.app.Application.
As the Android Developer Site says:
android:name
The fully qualified name of an Application subclass
implemented for the application. When the application process is
started, this class is instantiated before any of the application's
components.
The subclass is optional; most applications won't need
one. In the absence of a subclass, Android uses an instance of the
base Application class.
Since subclassing Application is optional, removing android:name=".MyApp" allows your app to properly start because you're no longer trying to cast MyApp to Application which is exactly what your exception claims your app is trying to do.
Related
I have a program with a service and if I reboot my device also the service should Restart. But this only works on the Emulator if I try this on my real device the service doesn't start at all.
Does someone know what I'm doing wrong or why it only works on Emulator?
BroadcastReviever:
#Override
public void onReceive(Context context, Intent intent) {
//we double check here for only boot complete event
if(intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED))
{
//here we start the service
Intent serviceIntent = new Intent(context, UploadService.class);
context.startService(serviceIntent);
}
}
Manifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.READ_OWNER_DATA" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_OWNER_DATA" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="Upload FTP"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<receiver
android:name=".BootCompletedIntentReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<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=".UploadService"
android:isolatedProcess="false"
android:exported="true"
android:enabled="true"/>
</application>
The emulator is at API 23 and real device is API 27.
I'm Building for a min API Level 23 and max API Level 27
EDIT
Now I have also tried the program with a emulator and android API 27 and there when I start my program and then I restart the emulator, the emulator doesn't start any more. As soon as the emulaor has started he begins to reboot again and that in a endless loop. (Real device starts normal just doesn't restarts service)
try to use LOCKED_BOOT_COMPLETED receiver as follow:
<receiver
android:name=".BootReceiver"
android:directBootAware="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
<!-- For pre-N devices -->
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
don't forget permission
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
take a look here for more explanation
Now I fixed in on my own it was easier then i thought
public class BootCompletedIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i=new Intent(context, YourClass.class);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) {
context.startForegroundService(i);
}
else {
context.startService(i);
}
}
I had some weird experience if I don't put full URI,
for example .BootCompletedIntentReceiver would become com.company.BootCompletedIntentRecevier.
I know it sounds dumb but I had many weird regressions when not explicitly stating things on the Manifest with modern SDKs.
I have literally followed the examples for implementing GCM inside an android app and the app is receiving the messages using the following code:
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp;
comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
The problem is that the GcmIntentService (public class GcmIntentService extends IntentService) is never being run? Am I missing something or should it usually fire the onHandleIntent method?
In case in any way related the Manifest file is below, thanks in advance:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.diversivi.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19"/>
<application
android:label="#string/app_name"
android:icon="#drawable/ic_launcher">
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
<activity
android:name=".DemoActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.diversivi.test" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.diversivi.test.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.diversivi.test.permission.C2D_MESSAGE" />
</manifest>
I don't see your GcmIntentService service declared in the manifest. That could be the problem.
In addition, the following line
comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName());
assumes that the GcmIntentService class is in the main package of your app (i.e. its full name is com.diversivi.test.GcmIntentService). If that's not the case, the broadcast receiver can't find the service class.
I don't understand why happens this exception.
In my Main activity, in the method onCreate I have this code at first:
try {
PackageInfo info = this.getPackageManager().getPackageInfo("com.mypacket", PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.e("Hash", Base64.encodeToString(md.digest(), Base64.DEFAULT));
}
} catch (NameNotFoundException e) {
Log.e("Hash", "Error: NameNotFoundException");
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
Log.e("Hash", "Error: NoSuchAlgorithmException");
}
The exception is NameNotFoundException, I want to solve it because I think it causes problem with the Facebook SDK.
Thank you all.
If helps, this is my AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myPackageName.app"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<supports-screens android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true" />
<permission android:name="com.myPackageName.app.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
<uses-permission android:name="com.myPackageName.app.permission.MAPS_RECEIVE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<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.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.myPackageName.app.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.myPackageName.app.permission.C2D_MESSAGE" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:name="#string/app_name"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="#string/app_id"/>
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.myPackageName.app" />
</intent-filter>
</receiver>
<service android:name=".GcmIntentService" />
<activity
android:name="com.myPackageName.app.SplashScreen"
android:screenOrientation="portrait"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Google Maps V2 API KEY -->
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="apy key" />
</application>
</manifest>
You got your package name wrong. For safety, always use Context.getPackageName().
PackageInfo info = this.getPackageManager().getPackageInfo(this.getPackageName(), PackageManager.GET_SIGNATURES);
Your package name is com.myPackageName.app not com.mypacket.
BTW you can obtain package name by Context#getPackageName()
This issue occurs when you have generate hash key project and the application for which you are creating hash key are not on the some workspace / directory, so exception arises NameNotFoundException.
Cheers :)
It means that either you are giving wrong package name or maybe you are not sure about the package name.
Case 1. if you know about your package name, just cross check it.
Case 2. if you are not sure about the package name ( this situation may also arise when you did some code refactoring i.e. Rename Package )
There are multiple approaches to fix it
package name is mentioned in the top of the AndroidManifest.xml
If it is still not resolved to get package name by
Context.getPackageName();
or
Log.d();
In Logcat check the application column package name should be mentioned there.
This can also happen if you have the app already installed. If for example you were to debug your app and then test the release .apk on the same device without uninstalling the debug version. If that is the case, just uninstall and then the install should work.
Uninstall your app from your device then run it again through the android studio. It helps me
I would like to receive information in Application about Enable/Disable Location provider like NETWORK, GPS etc. I create simple BroadcastReceiver:
public class TestReciver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.v("LOCATION_CHANGE_RECEIVER", "PROVIDER UPDATE");
}
}
And register it in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<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.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application
android:label="#string/app_name"
android:icon="#drawable/ic_launcher"
android:allowBackup="true"
android:debuggable="true">
<receiver android:name=".receiver.TestReciver">
<intent-filter>
<action android:name="android.intent.action.PROVIDER_CHANGED"/>
</intent-filter>
</receiver>
But when I try switch on/off GPS this BroadcastReceiver doesn't receive anything.
Change your intent filter to android.location.PROVIDERS_CHANGED
<receiver android:name=".receiver.TestReciver">
<intent-filter>
<action android:name="android.location.PROVIDERS_CHANGED" />
</intent-filter>
</receiver>
I get the following Exception running my app:
java.net.SocketException: Permission denied (maybe missing INTERNET permission)
How do I solve the missing permission problem?
Add the INTERNET permission to your manifest file.
You have to add this line:
<uses-permission android:name="android.permission.INTERNET" />
outside the application tag in your AndroidManifest.xml
In the latest release of Google Play, Google removed the need to ask permission for internet as "most apps need it anyways nowadays". However, for users who have older versions, it is still recommended to leave the code below in your manifest
<uses-permission android:name="android.permission.INTERNET" />
just put above line like below
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.avocats.activeavocats"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.exp.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>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
If you want using Internet in your app as well as check the network state i.e. Is app is connected to the internet then you have to use below code outside of the application tag.
For Internet Permission:
<uses-permission android:name="android.permission.INTERNET" />
For Access network state:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Complete Code:
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<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>
</application>
I had the same problem even use
<uses-permission android:name="android.permission.INTERNET" />
If you want connect web api using http not https. Maybe you use android device using Android 9 (Pie) or API level 28 or higher . android:usesCleartextTraffic default value is false. You have to set be
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<application
...
android:usesCleartextTraffic="true" <!-- this line -->
...>
...
</application>
</manifest>
Finally, should be https
https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic
if just using internet then use-
<uses-permission android:name="android.permission.INTERNET" />
if you are getting the state of internet then use also -
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
just above the application tag.
Use these:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
forget about adding the permission into the manifest
Add this code as a method
public static boolean hasPermissions(Context context, String... permissions)
{
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null)
{
for (String permission : permissions)
{
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED)
{
return false;
}
}
}
return true;
}
and write this in your Main
int PERMISSION_ALL = 1;
String[] PERMISSIONS = {Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_SMS, Manifest.permission.CAMERA};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
Just Add these 2 permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
in your app's AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.networkusage"
...>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
...>
...
</application>
</manifest>
Happy Coding:)
Just put below code in AndroidManifest :
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
As per current versions, Android doesn't ask for permission to interact with the internet but you can add the below code which will help for users using older versions
Just add these in AndroidManifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
To request for internet permission in your code you must add these to your AndroidManifest.xml file
<uses-permission android:name="android.permission.INTERNET" />
For more detail explanation goto https://developer.android.com/training/basics/network-ops/connecting
Google removed the need to ask permission for the internet for the latest version. Still, to request for internet permission in your code you must add these to your AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET"/>