I would like to be able to get a query string from a Google Play install passed to my Cordova app. I'm stuck on getting it to reliably work, never mind getting it to run after a Google Play install. I've tried both dynamic and static broadcast receivers and briefly had the static one working.. but now it doesn't.
Edit: first, let me add that I get this output from trying and failing to inject a broadcast (detailed below). (My phone is not rooted... does adb shell am broadcast work properly without root?):
D/AndroidRuntime(19631):
D/AndroidRuntime(19631): >>>>>> AndroidRuntime START com.android.internal.os.RuntimeInit <<<<<<
D/AndroidRuntime(19631): CheckJNI is OFF
D/AndroidRuntime(19631): setted country_code = USA
D/AndroidRuntime(19631): setted countryiso_code = US
D/AndroidRuntime(19631): setted sales_code = ATT
D/AndroidRuntime(19631): readGMSProperty: start
D/AndroidRuntime(19631): readGMSProperty: already setted!!
D/AndroidRuntime(19631): readGMSProperty: end
D/AndroidRuntime(19631): addProductProperty: start
D/dalvikvm(19631): Trying to load lib libjavacore.so 0x0
D/dalvikvm(19631): Added shared lib libjavacore.so 0x0
D/dalvikvm(19631): Trying to load lib libnativehelper.so 0x0
D/dalvikvm(19631): Added shared lib libnativehelper.so 0x0
D/dalvikvm(19631): No JNI_OnLoad found in libnativehelper.so 0x0, skipping init
D/dalvikvm(19631): Note: class Landroid/app/ActivityManagerNative; has 194 unimplemented (abstract)
methods
D/AndroidRuntime(19631): Calling main entry com.android.commands.am.Am
D/AndroidRuntime(19631): Shutting down VM
For the static version, here is what is in my XML manifest file:
<receiver android:exported="true" android:name="com.flyingsoftgames.googleplayquery.QueryReceiver ">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
And, I have two files, GooglePlayQuery.java and then QueryReceiver.java.
GooglePlayQuery.java:
package com.flyingsoftgames.googleplayquery;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
public class GooglePlayQuery extends CordovaPlugin {
public static CallbackContext queryCallback = null;
public static CordovaInterface cordova = null;
#Override public void initialize (CordovaInterface initCordova, CordovaWebView webView) {
cordova = initCordova;
super.initialize (cordova, webView);
}
public boolean execute (String action, JSONArray inputs, CallbackContext callbackContext) throws JSONException {
if ("getURI".equals(action)) {this.queryCallback = callbackContext;}
return true;
}
}
QueryReceiver.java:
package com.flyingsoftgames.googleplayquery;
import com.flyingsoftgames.googleplayquery.GooglePlayQuery;
import org.apache.cordova.PluginResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.app.Activity;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.util.Log;
public class QueryReceiver extends BroadcastReceiver {
#Override public void onReceive (Context context, Intent intent) {
Log.d ("QueryReceiver", "com.android.vending.INSTALL_REFERRER"); // <-- doesn't log this.
GooglePlayQuery.queryCallback.sendPluginResult (new PluginResult (PluginResult.Status.OK, intent.toURI()));
// Now destroy the broadcast receiver since we don't need it anymore.
Activity activity = GooglePlayQuery.cordova.getActivity ();
ComponentName receiver = new ComponentName (activity, QueryReceiver.class);
PackageManager pm = activity.getPackageManager ();
pm.setComponentEnabledSetting (receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
}
}
I am running this to test it:
adb shell am broadcast -a com.android.vending.INSTALL_REFERRER -n com.mygame/com.flyingsoftgames.googleplayquery.QueryReceiver --es "referrer" "textinreferrer"
I have no response from onReceive.
Here is my dynamic broadcast receiver version. I run this to test the dynamic version:
adb shell am broadcast -a com.android.vending.INSTALL_REFERRER -n com.mygame/com.flyingsoftgames.googleplayquery.GooglePlayQuery --es "referrer" "textinreferrer"
No response from onReceive here, either. Any tips?
package com.flyingsoftgames.googleplayquery;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.Context;
import android.content.BroadcastReceiver;
import android.util.Log;
public class GooglePlayQuery extends CordovaPlugin {
public static CallbackContext queryCallback = null;
private BroadcastReceiver receiver = null;
#Override public void initialize (CordovaInterface cordova, CordovaWebView webView) {
super.initialize (cordova, webView);
IntentFilter intentFilter = new IntentFilter();
intentFilter.setPriority (999);
intentFilter.addAction ("com.android.vending.INSTALL_REFERRER");
Log.d ("GooglePlayQuery", "initialize"); // <-- runs.
receiver = new BroadcastReceiver () {
#Override public void onReceive (Context context, Intent intent) {
Log.d ("GooglePlayQuery", "com.android.vending.INSTALL_REFERRER"); // <-- No response.
queryCallback.sendPluginResult (new PluginResult (PluginResult.Status.OK, intent.toURI()));
}
};
webView.getContext().registerReceiver (this.receiver, intentFilter);
}
public boolean execute (String action, JSONArray inputs, CallbackContext callbackContext) throws JSONException {
Log.d ("GooglePlayQuery", "execute"); // <-- runs.
if ("getURI".equals(action)) this.queryCallback = callbackContext;
return true;
}
}
Ok. I'm not entirely sure on how exactly to get the dynamic format to actually work, but it seems that the static format needs the receiver to be re-enabled via the package manager -- the broadcast receiver doesn't automatically re-enable the receiver when the app runs. In my case:
Activity activity = cordova.getActivity ();
ComponentName receiver = new ComponentName (activity, QueryReceiver.class);
PackageManager pm = activity.getPackageManager ();
pm.setComponentEnabledSetting (receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Related
I'm trying to make a service that works 24/7 and it's been working until I updated to Android 12. I've checked the new foreground restrictions but still don't understand why it isn't working since I'm starting it from an activity.
ACTIVITY
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class TestActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startForegroundService(new Intent(TestActivity.this, TestService.class));
}
}
SERVICE
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.media.MediaBrowserCompat;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.media.MediaBrowserServiceCompat;
import java.util.List;
public class TestService extends MediaBrowserServiceCompat {
#Override
public BrowserRoot onGetRoot(#NonNull String clientPackageName, int clientUid, #Nullable Bundle rootHints) { return null; }
#Override
public void onLoadChildren(#NonNull String parentId, #NonNull Result<List<MediaBrowserCompat.MediaItem>> result) { result.sendResult(null); }
#Override
public int onStartCommand(Intent ii, int flags, int startId) {
//CREATE NOTI CHANNEL
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"test", "Test Notifications",
NotificationManager.IMPORTANCE_HIGH);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
}
//CREATE NOTI
Notification notification = new NotificationCompat.Builder(this, "test")
.setSmallIcon(R.drawable.icon)
.setContentTitle("title")
.setContentText("test")
.setChannelId("test")
.setOngoing(true)
.setSilent(true)
.build();
//START FOREGROUND
startForeground(101, notification);
return START_STICKY;
}
}
I tried creating a new app with just these lines of code and it works fine so it must be something else making the service close after a minute.
Turns out samsung put my app on deep sleep which caused it to close itself if not used for a minute. Also thanks to the people who took their time to try and help.
Even though you are correct in wanting a foreground Service here, it seems as if you want it to stay alive whenever you app in the background, or not running at all, as you don't intend your app to be running 24/7, do you?
Since it seems as if you're trying to use a MediaBrowserServiceCompat in your example, I would suggest you do so using a companion instance of a MediaSessionCompat in order to have the media session control the lifecycle of your Service on it's own.
Implementing a media Service is not the most straightforward task in Android; they're still trying to fix some of its prevailing issues with the latest release of Android 13. Therefore, I would also suggest you follow this official Android guide if you're attempting to create an audio app with a media foreground Service.
I have been learning jobscheduler in andorid. I have trying to show a toast message in the onstartjob() after every 1minute. But its not showing up. Any help will be grateful.
jobschedul_service .class:
package com.prajwal.jobscheduler;
import android.app.Service;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class jobschedul_service extends JobService {
#Override
public boolean onStartJob(JobParameters jobParameters) {
Toast.makeText(getApplicationContext(), "After 15 minutes", Toast.LENGTH_SHORT).show();
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
return true;
}
}
MainActivity.class:
package com.prajwal.jobscheduler;
import androidx.appcompat.app.AppCompatActivity;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private static final int LOAD_ARTWORK_JOB_ID = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
JobScheduler jobScheduler =
(JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(new JobInfo.Builder
(LOAD_ARTWORK_JOB_ID, new ComponentName(this, jobschedul_service.class))
.setPeriodic(900000)
.build());
}
}
Manifest.xml:
<service
android:name=".jobschedul_service"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"></service>
Got the answer!
The reason was the setperiodic(long interval).
As per the ss below:
This function was added in API 21 i.e Lolipop version. Whereas I was running the app on version > Lolipop.
Whereas this new function in the image below:
was added in API 24 i.e. Nougat
Hence, if you are targetting your app below Nougat i.e < Nougat but >= Lolipop then use setPeriodic(long interval) method whereas if u r targetting >= Nougat then use setPeriodic(long interval, long flexinterval).
Solution
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N)
{
builder.setPeriodic(900000,6000);
}
else
{
builder.setPeriodic(900000);
}
I'm trying to follow Facebook's docs for Sharing a Sticker Asset on Android without any luck. Basically when executed the app flickers and then crash.
Could someone look at this code and point out why the app crashes after calling activity.startActivityForResult(intent, 0);? (debugging the code using logcat, I can see the code is definitely executing startActivityForResult)
package com.app.my;
import android.net.Uri;
import android.content.Intent;
import android.app.Activity;
import android.util.Log;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
public class InstagramStoriesModule extends ReactContextBaseJavaModule {
private static ReactApplicationContext reactContext;
InstagramStoriesModule(ReactApplicationContext context) {
super(context);
reactContext = context;
}
//Mandatory function getName that specifies the module name
#Override
public String getName() {
return "InstagramStories";
}
//Custom function that we are going to export to JS
#ReactMethod
public void share(ReadableMap options) {
String stickerImage = "https://www.example.com/image.jpeg";
String backgroundColor = "#000000";
Uri stickerAssetUri = Uri.parse(stickerImage);
Intent intent = new Intent("com.instagram.share.ADD_TO_STORY");
intent.setType("image/jpeg");
intent.putExtra("interactive_asset_uri", stickerAssetUri);
intent.putExtra("top_background_color", backgroundColor);
intent.putExtra("bottom_background_color", backgroundColor);
Activity activity = reactContext.getCurrentActivity();
activity.grantUriPermission("com.instagram.android", stickerAssetUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (activity.getPackageManager().resolveActivity(intent, 0) != null) {
activity.startActivityForResult(intent, 0);
}
}
}
I have a litle problem while programing on my application. I'm programing a service which shows me how many times my phone was active in the last 24 hours.
I’m doing this by listening for screen on/off action, and I’m getting more and more receives by pusshing the button.
Actually I gat a pattern in it, so:
logs getherd = logs getterd in the previus button puss * 2 - 8
My Reciver class:
package com.example.balinator.androidprojekt.services.screenonservice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Display;
import com.example.balinator.androidprojekt.database.Database;
import java.util.Set;
/**
* Created by Balinator on 2016. 12. 15..
*/
public class MyScreenOnOffReciver extends BroadcastReceiver {
private static final String tag = "MyScreenOnOffReciver";
private Database db;
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getAction();
if (state.equals(Intent.ACTION_SCREEN_ON)) {
if(db == null){
db = new Database(context);
}
db.open();
long id = db.getService(MyScreenOnService.sName).getId();
db.createServiceLog(id,System.currentTimeMillis() + ":on");
db.close();
Log.d(tag,"screen on log");
}else if(state.equals(Intent.ACTION_SCREEN_OFF)) {
if (db == null) {
db = new Database(context);
}
db.open();
long id = db.getService(MyScreenOnService.sName).getId();
db.createServiceLog(id, System.currentTimeMillis() + ":off");
db.close();
Log.d(tag, "screen off log");
}
}
}
I think you registered your receiver 2 times
At activity
manifest
Register your receiver one time by using any one of the above.. then it ll b fyn
I'm trying to have my app turn off a music player using the code below:
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
ActivityManager activityManager = (ActivityManager)
context.getSystemService(Context.ACTIVITY_SERVICE);
String music = "com.sec.android.app.music";
activityManager.killBackgroundProcesses(music);
}
}
But it's only turning down the volume, not killing the application. I have added the appropriate permissions to the manifest and I'm targeting higher than API 8 Thanks.
You cannot kill other processes. Only system can do that. And volume goes down because its settings is not per app.