Android background service with no UI is not answering - java

I try to create a background service with no user interface and I created it with BroadcastReceiver and added my necessary things in the manifest file. Then I configure Nothing as written in the link. I'm testing on an Android emulator, when I execute my app nothing happen and the service is not starting. Where is my problem?
Here is my manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.myapplication22">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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/Theme.MyApplication22">
<service android:name=".MyService" />
<receiver
android:name=".StartReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
Here is my BroadcastReceiver
override fun onReceive(context: Context, intent: Intent) {
Log.i("MYSERVICE","override fun onReceive(context: Context, intent: Intent)")
if (intent.action == Intent.ACTION_BOOT_COMPLETED ) {
Intent(context, MyService::class.java).also {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startService(it)
return
}
context.startService(it)
}
}
}
Here is my Service
class MyService : Service() {
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent != null) {
println("MYSERVICE STARTED AUTOMATICALLY")
}
return START_STICKY
}
override fun onCreate() {
super.onCreate()
println("MYSERVICE override fun onCreate() {")
}
override fun onDestroy() {
super.onDestroy()
println("MYSERVICE override fun onDestroy() {")
}
}

your Service will start only when BOOT_COMPLETED action will be received, so only when app already installed and system restarts. it won't start when you just install app through adb (as you configure to start Nothing when installed)
make some Activity fully transparent with startService in onCreate and just after that finish() call. include <activity declaration in manifest, but without any <intent-filter. then instead of Nothing to run when app install just pick Specified Activity and point on this transparent one, which starts Service and quits after that. without intent-filter Activity won't be visible in launcher and only way to start it will be your configuration in AS
when you will be sending your app to end-users then remove <activity declaration leaving no actual way to run this transparent Activity. only Service can be started then, in current circumstances only when system boots up
btw. your Nothing link assumes your app will be system-belong, moved to system partition/folder. do you have such privileges? (on usual user device this won't be possible, you need root privileges) without that all red-marked lines in <application tag won't work
edit:
step 1:
create file res/values/styles.xml and past below or if present already add below <style tag
<resources>
<style name="Theme.Transparent" parent="android:Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
</resources>
step 2: create new Activity and declare in manifest with above style
<activity android:name=".YourActivity" android:theme="#style/Theme.Transparent"/>
if you add below <intent-filter to <activity tag then this Activity shows in system UI (launcher), so just don't do that, placing here just to inform
// launcher icon declaration, not for OPs case
<intent-filter>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN"/>
// MAIN must be placed with first LAUNCHER declaration
</intent-filter>
note that you can also create multiple <activity tags with LAUNCHER declaration (second and further without MAIN tag), making your app show multiple icons, one per Activity LAUNCHER-declared (you can also change their names and icons as far as I remember)
step 3: inside onCreate just after super.onCreate call start your Service and then quit this invisible Activity
startService(this, MyService.class); // will start service
finish(); // quits activity
step 4: under Edit Configurations... instead of Nothing just pick Specified Activity

Related

How to stop my activity from opening another instance in another application from share menu?

I have my application that allows other apps that can share files to select it on the share menu, open the application up and "transfer" the files over to my app.
My problem is when they select my application from the share menu (as example, in gallery, after selecting several photos, they choose to share with my app) the login activity gets opened inside the gallery application
Please note that i have tried this process works on older devices and it worked but not for a newer device.
This is my manifest.xml
<application
android:name="com.Application"
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:largeHeap="true"
android:mimeType="*/*"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/app_name"
android:windowSoftInputMode="adjustPan"/>
<activity
android:name=".login.LoginActivity"
android:label="#string/app_name"
android:launchMode="singleInstance"
android:windowSoftInputMode="adjustResize|stateVisible">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
I have two activities for this app, login and Main, Main will be loaded up if login is successful.
I have tried with different kinds of launcherMode settings but nothing has stopped the instance from being created in gallery
This is from my login Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
receivedIntent = getIntent();
//set orientation
setRequestedOrientation(isPhone() ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent != null && intent.getAction() != null && (intent.getAction().equals(Intent.ACTION_SEND) || intent.getAction().equals(Intent.ACTION_SEND_MULTIPLE))){
finish();
startActivity(intent);
}
}
The problem is, on the older device the onNewIntent method gets called as expected, but on the newer device it just ignores the launcherMode and creates the new instance and runs onCreate()
Any ideas on how to get the application to "force" launch itself when called from a share menu?
Current Testing devices - Samsung mobile Android 8.0, API 26 - not working
Samsung Tablet Android 7.1.1, API 25 - working as expected
All your issue is about the permissions,
Old devices below kitkat(4.4.2) does not required permissions of file but in new devices required permissions for access the file data(ie. gallery and others).
You have to grant permission programmatically,
if (Build.VERSION.SDK_INT > 19) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
arrPerm.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (!arrPerm.isEmpty()) {
String[] permissions = new String[arrPerm.size()];
permissions = arrPerm.toArray(permissions);
ActivityCompat.requestPermissions(this, permissions, MY_PERMISSIONS_REQUEST);
}
}
After Permission Granted you can do your operation:
if (Build.VERSION.SDK_INT > 19) {
if (isPermissionGranted()) {
//Do your Task of gallery
}
}
Or alternate way, you can use library directly:
https://github.com/nabinbhandari/Android-Permissions
I did some digging into other apps on the device and found this issue is only occurring when sharing images from the application "Gallery" otherwise the code works as expected, so i believe this could be an issue with Gallery itself or is expected behavior for the Gallery application.

Android not detecting when device rotated

I am trying to start a new activity when an Android device is rotated, but I don;t even seem to be detecting the rotation in the emulator.
I've read the thread at Android: listen for Orientation change? and that all seems to amke sense, but its just not working.
In my manifest I have:
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
and in my mainActivity.java I have:
#Override
public void onConfigurationChanged (Configuration newConfig) {
super.onConfigurationChanged(newConfig);
int orientation=newConfig.orientation;
switch(orientation) {
case Configuration.ORIENTATION_LANDSCAPE:
showMessage("landscape");
break;
case Configuration.ORIENTATION_PORTRAIT:
showMessage("portrait");
break;
}
}
This obviously won't start the new Activity, but I am trying to get the orientation detection working first (showMessage just calls a Toast and is working elsewhere in my code, so that's not why I am not seeing anything).
When I run this in the emulator and use the rotate buttons, the emulator rotates as expected but I never see the Toast...
Where am I going wrong? (I am importing android.content.res.Configuration as required for the Configuration constants).
onConfigurationChanged method will not be invoked when you rotate your device, actually, nothing will be invoked because of this line:
android:screenOrientation="portrait"
device is just locked in a portrait mode, remove this line, and onConfigurationChanged method should be invoked.
If you want to detect that device is rotated and keep android:screenOrientation="portrait" line you can use accelerometer sensor.
Try after removing this lines
android:configChanges="orientation|screenSize"
android:screenOrientation="portrait"
because you are locking screen orientation in manifest and you are
also overriding on config change in activity.

Android createChooser appear in front of Activity

I'm hoping one of you fine folk may be able to help me out with a little issue I am having whilst using Android Intent.createChooser(). I am learning as I go with my application so I apologise if I have the wrong end of the stick with how this should work!
I have been following a number of tutorials and have implemented some code which starts an Intent.createChooser() to share a picture to social media. The code that I have used works fine in that I am able to share the picture as I intended, my issue is that when the code is run my main activity (or any activity I call the code from) appears to close and the chooser appears in front of the homescreen or any other applications I may have open. The effect that I was hoping to have, and the one which seemed to be apparent in the tutorials, is for the chooser to appear in front of the running activity (eg as it does for the gallery).
I am using LibGDX meaning that I have had to use an interface to call the android function that executes the chooser code (in my AndroidLauncher java file). The interfaces all work fine but I wasn't sure if that may have a bearing on the way in which this code operates. I have also played around with swapping to a new activity to implement the chooser code, which I had moved from the AndroidLauncher. This had the same end result.
Any advice on how to make the chooser appear in front of my application would be greatly appreciated! The code which implements the createChooser is included below:
public void ShareHandler(){
String type = "image/*";
String mediaPath = Environment.getExternalStorageDirectory().getPath()+"/Smile.png";
createShareIntent(type, mediaPath);
}
private void createShareIntent(String type, String mediaPath)
{
Intent share = new Intent(Intent.ACTION_SEND);
share.setType(type);
File media = new File(mediaPath);
Uri uri = Uri.fromFile(media);
share.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(share, "Share to"));
}
Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.game"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="25" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/GdxTheme">
<activity
android:name=".AndroidLauncher"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="#string/app_name"
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=".FacebookServiceHandler" />
<meta-data
android:name="come.facebook.sdk.ApplicationID"
android:value="#string/facebook_app_id" />
<provider
android:name="com.facebook.FacebookContentProvider"
android:authorities="com.facebook.app.FacebookContentProviderxxxxxxxxxxxxx"
android:exported="true" />
</application>
</manifest>
Thanks in advance, Ben.
If
android:name=".FacebookServiceHandler"
is the activity, that handle the social media sharing of the picture, i would expand that to something like this:
<activity
android:name=".FacebookServiceHandler">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".AndroidLauncher">
</meta-data>
</activity>
This will tell the programm, that the AndroidLauncher is the parentactivity and should make it appear in front of your activity.
Thank you for the suggestions, I have now solved my issue. It turned out that my code was working correctly all along and the issue I was experiencing was as a result of an exit statement within my Core (LibGDX) java code. Essentially when the startActivity(Intent.createChooser(...)) was called, a dispose function within my core files was also being called. This dispose function contained the exit command and was causing the application to finish.

Unable to find explicit activity class Android

Ugh, so many posts on StackOverflow similar to my problem but none fix it :/
I am currently learning android development. In my main activity I do:
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch(item.getItemId()){
case R.id.changeName:
Intent intent = new Intent(this, PreferenceActivity.class);
startActivityForResult(intent, 1);
return true;
}
return false;
}
Preference.java is a freshly created activity with nothing in it except the automatically created onCreate method. The error is:
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.package.chat.oneway.client/android.preference.PreferenceActivity}; have you declared this activity in your AndroidManifest.xml?
My android manifest has:
<application
android:allowBackup="false"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
<activity
android:name=".ChatClient"
android:label="#string/app_name" />
<activity android:name=".Parent">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".PreferenceActivity"></activity>
</application>
As you can see, .PreferenceActivity is in the manifest. The packages for the ChatClient and PreferenceActivity activities are the same com.package.chat.oneway.client package.It's been driving me nuts for the past 4 hours.
As you can see, .PreferenceActivity is in the manifest.
Yes, it is. However, that is not what your Intent is using. If you look more closely at the error message, you will see that your Intent is using android.preference.PreferenceActivity.
This comes when you reuse existing class names. There are countless possible class names. Rename yours to something else, and you can avoid this sort of problem in the future.
Or, if you are completely set on having your class named PreferenceActivity, then remove the import android.preference.PreferenceActivity statement from the class where you are creating your Intent. Or, change your Intent to:
Intent intent = new Intent(this, com.package.chat.oneway.client.PreferenceActivity.class);

Android app opening wrong page after using uri scheme

In IOS I have 2 apps (App A and App B) that will be performing different objective but at 1 point, App A will call App B using uri scheme to perform a function where App A does not have.
I wanted to implement this function to Android and currently have developed a demo for initiating call to App B. Now I am working on App B that will be receiving the uri scheme from the demo app.
Problem:
After App B return to the demo app using uri scheme I close the demo app.
When I go back to home page and open the multitask to reopen App B(or open App B through the icon), the page it reopen is the function that is used for demo app but what I wanted is the login page of App B.
This is a part of the Manifest for the intent-filter
<activity
android:name="com.apps.MasterActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:clearTaskOnLaunch="true"
android:windowSoftInputMode="adjustPan" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data
android:host="x-callback-url"
android:scheme="myapp" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
This is where I call back to the demo app
Intent sendIntent = new Intent(Intent.ACTION_VIEW, responseUri);
sendIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
finish();
startActivity(sendIntent);
Try adding this to your activity tag in AndroidManifest.xml
android:clearTaskOnLaunch="true"
Apparently I kinda found a solution that can force the app to show the login page after going back to the demo app. By putting this code in the activity.java file.
#SuppressWarnings("deprecation")
#Override
public void onDestroy()
{
super.onDestroy();
System.runFinalizersOnExit(true);
System.exit(0);
}
I know its a deprecated function that I'm using but will try to solve it when there's something wrong in the future or when I found a better solution for it.
Edit:
Found a better solution that does not need to use the deprecated function which I have forgotten to set it to false.
I have a flag that is set to true when the app is connected through Uri Scheme which i just have to set it to false and it will be fixed. This is the change location that I made
Intent sendIntent = new Intent(Intent.ACTION_VIEW, responseUri);
sendIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
finish();
startActivity(sendIntent);
Util.isUriScheme = false;

Categories

Resources