I have created a Service which listens to a Firebase location.
This is a simple service with low memory usage. Unfortunately, I am seeing a Google play services service called MeasurementBrokerService joining my service and not freeing memory.
Unlike a related question :
"Service MeasurementBrokerService is in use" is showing in my application process
The above question has no accepted answer, so kindly do not mark this as a duplicate
I am not using firebase-appindexing.
Following is my app level gradle file:
buildscript {
repositories {
maven { url 'https://maven.fabric.io/public' }
}
dependencies {
classpath 'io.fabric.tools:gradle:1.+'
}
}
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
repositories {
maven { url 'https://maven.fabric.io/public' }
}
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.example.project.recommendedapp"
minSdkVersion 21
targetSdkVersion 25
versionCode 1
versionName "1.0"
// Enabling multidex support.
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:cardview-v7:25.1.0'
compile 'com.android.support:recyclerview-v7:25.1.0'
compile 'com.android.support:design:25.1.0'
compile 'com.android.support:support-v4:25.1.0'
compile 'com.github.clans:fab:1.6.4'
compile 'com.google.android.gms:play-services-location:10.0.1'
compile('com.crashlytics.sdk.android:crashlytics:2.6.0#aar') {
transitive = true;
}
compile 'com.facebook.fresco:fresco:1.0.0'
compile 'com.google.firebase:firebase-database:10.0.1'
compile 'com.google.firebase:firebase-messaging:10.0.1'
compile 'com.squareup.okhttp3:okhttp:3.5.0'
}
apply plugin: 'com.google.gms.google-services'
Can someone please guide me as to how to stop the service from joining my process.
The service is as follows:
public class SubscriptionListenerService extends Service {
DatabaseReference userNodeSubscriptionRef;
ChildEventListener subscribedTopicsListener;
SharedPreferences sessionPref,subscribedTopicsPreference;
SharedPreferences.Editor subscribedtopicsprefeditor;
String userid;
boolean stoppedInternally = false;
SharedPreferences.OnSharedPreferenceChangeListener sessionPrefChangeListener;
#Nullable
#Override
public IBinder onBind(Intent intent) {
//do not need a binder over here
return null;
}
#Override
public void onCreate(){
super.onCreate();
Log.d("FragmentCreate","onCreate called inside service");
sessionPref = getSharedPreferences("SessionPref",0);
subscribedTopicsPreference=getSharedPreferences("subscribedTopicsPreference",0);
subscribedtopicsprefeditor=subscribedTopicsPreference.edit();
userid = sessionPref.getString("userid",null);
sessionPrefChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Log.d("FragmentCreate","The shared preference changed "+key);
stoppedInternally=true;
sessionPref.unregisterOnSharedPreferenceChangeListener(this);
if(userNodeSubscriptionRef!=null && subscribedTopicsListener!=null){
userNodeSubscriptionRef.removeEventListener(subscribedTopicsListener);
}
stopSelf();
}
};
sessionPref.registerOnSharedPreferenceChangeListener(sessionPrefChangeListener);
subscribedTopicsListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if(!(dataSnapshot.getValue() instanceof Boolean)){
Log.d("FragmentCreate","Please test subscriptions with a boolean value");
}else {
if ((Boolean) dataSnapshot.getValue()) {
//here we subscribe to the topic as the topic has a true value
Log.d("FragmentCreate", "Subscribing to topic " + dataSnapshot.getKey()+" "+this.getClass().getName());
subscribedtopicsprefeditor.putBoolean(dataSnapshot.getKey(), true);
FirebaseMessaging.getInstance().subscribeToTopic(dataSnapshot.getKey());
} else {
//here we unsubscribed from the topic as the topic has a false value
Log.d("FragmentCreate", "Unsubscribing from topic " + dataSnapshot.getKey()+" "+this.getClass().getName());
subscribedtopicsprefeditor.remove(dataSnapshot.getKey());
FirebaseMessaging.getInstance().unsubscribeFromTopic(dataSnapshot.getKey());
}
subscribedtopicsprefeditor.commit();
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
//either an unsubscription will trigger this, or a re-subscription after an unsubscription
if(!(dataSnapshot.getValue() instanceof Boolean)){
Log.d("FragmentCreate","Please test subscriptions with a boolean value");
}else{
if((Boolean)dataSnapshot.getValue()){
Log.d("FragmentCreate","Subscribing to topic "+dataSnapshot.getKey()+" "+this.getClass().getName());
subscribedtopicsprefeditor.putBoolean(dataSnapshot.getKey(),true);
FirebaseMessaging.getInstance().subscribeToTopic(dataSnapshot.getKey());
}else{
Log.d("FragmentCreate","Unsubscribing from topic "+dataSnapshot.getKey()+" "+this.getClass().getName());
subscribedtopicsprefeditor.remove(dataSnapshot.getKey());
FirebaseMessaging.getInstance().unsubscribeFromTopic(dataSnapshot.getKey());
}
subscribedtopicsprefeditor.commit();
}
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
//Log.d("FragmentCreate","Unubscribing from topic "+dataSnapshot.getKey());
//FirebaseMessaging.getInstance().unsubscribeFromTopic(dataSnapshot.getKey());
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
//do nothing, this won't happen --- rather this isnt important
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("FragmentCreate","Failed to listen to subscriptions node");
}
};
if(userid!=null){
Log.d("FragmentCreate","Found user id in service "+userid);
userNodeSubscriptionRef = FirebaseDatabase.getInstance().getReference().child("Users").child(userid).child("subscriptions");
userNodeSubscriptionRef.addChildEventListener(subscribedTopicsListener);
userNodeSubscriptionRef.keepSynced(true);
}else{
Log.d("FragmentCreate","Couldn't find user id");
stoppedInternally=true;
stopSelf();
}
}
#Override
public int onStartCommand(Intent intent,int flags,int startId){
//don't need anything done over here
//The intent can have the following extras
//If the intent was started by the alarm manager ..... it will contain android.intent.extra.ALARM_COUNT
//If the intent was sent by the broadcast receiver listening for boot/update ... it will contain wakelockid
//If it was started from within the app .... it will contain no extras in the intent
//The following will not throw an exception if the intent does not have an wakelockid in extra
//As per android doc... the following method releases the wakelock if any specified inside the extra and returns true
//If no wakelockid is specified, it will return false;
if(intent!=null){
if(BootEventReceiver.completeWakefulIntent(intent)){
Log.d("FragmentCreate","Wakelock released");
}else{
Log.d("FragmentCreate","Wakelock not acquired in the first place");
}
}else{
Log.d("FragmentCreate","Intent started by regular app usage");
}
return START_STICKY;
}
#Override
public void onDestroy(){
if(userNodeSubscriptionRef!=null){
userNodeSubscriptionRef.keepSynced(false);
}
userNodeSubscriptionRef = null;
subscribedTopicsListener = null;
sessionPref = null;
subscribedTopicsPreference = null;
subscribedtopicsprefeditor = null;
userid = null;
sessionPrefChangeListener = null;
if(stoppedInternally){
Log.d("FragmentCreate","Service getting stopped due to no userid or due to logout or data clearance...do not restart auto.. it will launch when user logs in or signs up");
}else{
Log.d("FragmentCreate","Service getting killed by user explicitly from running services or by force stop ... attempt restart");
//well basically restart the service using an alarm manager ... restart after one minute
AlarmManager alarmManager = (AlarmManager) this.getSystemService(ALARM_SERVICE);
Intent restartServiceIntent = new Intent(this,SubscriptionListenerService.class);
restartServiceIntent.setPackage(this.getPackageName());
//context , uniqueid to identify the intent , actual intent , type of pending intent
PendingIntent pendingIntentToBeFired = PendingIntent.getService(this,1,restartServiceIntent,PendingIntent.FLAG_ONE_SHOT);
if(Build.VERSION.SDK_INT>=23){
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+600000,pendingIntentToBeFired);
}else{
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+600000,pendingIntentToBeFired);
}
}
super.onDestroy();
}
}
I checked that somehow still google AppMeasurement service was running on my device.
I have resorted to using the following approach:
The following stops data collection by firebase.
https://firebase.google.com/support/guides/disable-analytics tells us the following approach
<meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" />
This alone still can't stop the appMeasurement from initializing.
The second step that has solved is adding the following to the app level gradle file:
configurations {
all*.exclude group: 'com.google.firebase', module: 'firebase-core'
}
This basically removes all the code that firebase analytics uses.
In case it still doesn't work, make sure that the gradle does not include broad play service dependency
eg: compile 'com.google.android.gms:play-services-location:10.0.1'
instead of 'com.google.android.gms:play-services:10.0.1'
Worst case and i have not tested this as the above solved it for me is:
https://developers.google.com/analytics/devguides/collection/android/v4/advanced
Google should really stop putting unwanted things without the dev's permission IMHO. Hope this helps someone
Related
The application runs but when i try to use the camera only a disturbed grey screen appears and the logs tab gives me two errors:
E/libc: Access denied finding property "vendor.camera.aux.packagelist"
Access denied finding property "vendor.camera.aux.packagelist2"
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
build.gradle (Module:app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 22
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'
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'
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
}
build.gradle(Project:camera)
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
First, check your Android version. If it is running on Android 6.0 and higher (API level 23+), then you need to :
Declare a permission in the app manifest. Make sure to insert the permission above the application tag.
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<application ...>
...
</application>
Then, request that the user approve each permission at runtime
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.CAMERA},
50); }
I had this in my android manifest that prevented the app from using the camera.
android:hardwareAccelerated="false"
Removing it helped me.
Firstly, to check if it is a permission problem, go to the application manager of your phone, find your programme's name, and check the permission list. See if it is allowed to use the camera.
Secondly, open the XML of the layout where your "SurfaceView" resides, check if the "SurfaceView" node has the property "android:background". You must remove it if it is there. No idea why this is never mentioned.
<SurfaceView
android:layout_width="0dp"
android:layout_height="300dp" android:id="#+id/cameraPreview"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" android:background="#3F51B5"/>
Pay attention to the "android:background" in the above snippet. Remove it if you see it.
Thirdly, make sure you start the camera in the "surfaceCreated" event handler rather than anywhere else. You can't directly start the camera in "onViewCreated"!
Sample code just in case:
public void onViewCreated(#NonNull final View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final CameraSource cameraSource = new CameraSource.Builder(getContext(), barcodeDetector)
.setRequestedPreviewSize(640, 480)
.setRequestedFps(10)
.setAutoFocusEnabled(true).build();
((SurfaceView) view.findViewById(R.id.cameraPreview)).getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA}, 1);
}
try {
cameraSource.start(holder);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
cameraSource.stop();
}
});
}
Reason: FileNotFoundException open failed: XXXXXXX EPERM (Operation not permitted)
Adding all the permissions still reports an error, mainly because the permissions requirements of the Android system are very strict.
It is recommended to change to:
ContextWrapper cw = new ContextWrapper(getApplicationContext());
File directory = cw.getExternalFilesDir(Environment.DIRECTORY_MUSIC);
File file = new File(directory, "something" + ".MP3");
public static String DIRECTORY_MUSIC = "Music";
public static String DIRECTORY_ALARMS = "Alarms";
public static String DIRECTORY_NOTIFICATIONS = "Notifications";
public static String DIRECTORY_PICTURES = "Pictures";
public static String DIRECTORY_MOVIES = "Movies";
public static String DIRECTORY_DOWNLOADS = "Download";
public static String DIRECTORY_DCIM = "DCIM";
public static String DIRECTORY_DOCUMENTS = "Documents";
If you are using a firebase plugin in your project, remove it. I was using the firebase crashlytics that camera prevents opening.
I am also seeing same error in my console when I am trying to open camera. However, it does not cause any other side effects.
I think it's best to ignore this error unless it stops app from running. or limits any functionality.
Found a post here that claims to resolve the issue by adding
<application>
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
</application>
However, this did not work in my case. Testing on Mi Note 7
I too faced same error while implementing video capture option, this in my case due to missing Storage and Camera permissions.
Resolved using below code
if ((checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
Log.d(TAG, "No camera and storage permission");
requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_CODE);
}
In my case, you must be following an android jetpack for a camera course in here [https://developer.android.com/codelabs/camerax-getting-started#0][1]
After that, change the companion object like this.
companion object {
private const val TAG = "CameraXBasic"
private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
private const val REQUEST_CODE_PERMISSIONS = 10
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
}
Don't forget to add permission to access storage in the manifest.xml
In my case, the cause of the problem is that the surfaceTexture is available before the ui is not ready. To solve it, i add some delay (i don't know whether it is the correct solution or not, but it's working).
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int arg1, int arg2) {
mSurfaceTexture = surfaceTexture;
try {
Thread.sleep(200); // add some delay
} catch (InterruptedException e) {
e.printStackTrace();
}
cameraHelper.openCamera(mSurfaceTexture);
}
I made an app it run perfectly in api 20+ but for android version 4.4 and less it is getting crashed with error NoClassDefFoundError: android.media.session.MediaSessionManager this is the stack trace that i am getting in the developer console .
java.lang.NoClassDefFoundError: android.media.session.MediaSessionManager
at beatbox.neelay.beatbox.MediaService.initMediaSession(MediaService.java:634)
at beatbox.neelay.beatbox.MediaService.onStartCommand(MediaService.java:170)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2913)
at android.app.ActivityThread.access$2100(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1442)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5339)
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:828)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
at dalvik.system.NativeStart.main(Native Method)
All I am able to understand from this is the error is in the initMediaSession method .this is my initMediaSession method
private void initMediaSession() throws RemoteException {
if (mediaSessionManager != null) return; //mediaSessionManager exists
mediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
// Create a new MediaSession
mediaSession = new MediaSessionCompat(getApplicationContext(), "AudioPlayer");
//Get MediaSessions transport controls
transportControls = mediaSession.getController().getTransportControls();
//set MediaSession -> ready to receive media commands
mediaSession.setActive(true);
//indicate that the MediaSession handles transport control commands
// through its MediaSessionCompat.Callback.
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
//Set mediaSession's MetaData
updateMetaData();
// passing the data
// Attach Callback to receive MediaSession updates
mediaSession.setCallback(new MediaSessionCompat.Callback() {
// Implement callbacks
#Override
public void onPlay() {
super.onPlay();
messagesent();
a = false;
resumeMedia();
buildNotification(PlaybackStatus.PLAYING);
}
#Override
public void onPause() {
super.onPause();
messagesent();
a = true;
pauseMedia();
buildNotification(PlaybackStatus.PAUSED);
}
#Override
public void onSkipToNext() {
super.onSkipToNext();
skipToNext();
updateMetaData();
buildNotification(PlaybackStatus.PLAYING);
}
#Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
skipToPrevious();
updateMetaData();
buildNotification(PlaybackStatus.PLAYING);
}
#Override
public void onStop() {
super.onStop();
removeNotification();
//Stop the service
pauseMedia();
messagesent();
stopSelf();
}
#Override
public void onSeekTo(long position) {
super.onSeekTo(position);
}
});
}
I dont understand why it is getting crashend for 4.4 and less devices and how i can fix this .I googled and got this but this post dont tell how tofix this.
MediaSessionManager was only added in api 21 (5.0)
If it's absolutely necessary to use it then you can set your min sdk to 21 or check your build number with:
android.os.Build.VERSION.SDK
and not call this service with devices with lower sdks
It seems that the reason may be due to multidex. Check your apk method count at Get Method Count
You can enable multidex by adding dependency
compile 'com.android.support:multidex:1.0.1'
then enable it in config
defaultConfig {
multiDexEnabled true
}
add following snippet in android section of your
dexOptions {
javaMaxHeapSize "4g"
preDexLibraries false
}
afterEvaluate {
tasks.matching {
it.name.startsWith('dex')
}.each { dx ->
if (dx.additionalParameters == null) {
dx.additionalParameters = []
}
dx.additionalParameters += '--multi-dex'
// this is optional
dx.additionalParameters += "--main-dex-list=$projectDir/multidex.keep".toString()
}
}
compileOptions {
incremental false
}
I am also following the same tutorial and had same issue. I found the solution to this. Simply check if your SDK >21 then only use method initMediaSession();
I create app named "onlineContact" that save your contact in cloud and you can access your contacts from any Android phone using login. This app is working fine when I test it. I connect my mobile with computer and run it from android studio it's good. So, I upload this app on Google Play Store but When I download and install app from play store it's not worked. What's the problem with this.
Here is my app link on Play store onlineContact
Install it click on any link like login, create account or forget password.
When you clicked any of them it's crashed.
I tried it again from android studio and install it and it's working fine. Now how can I checked what the problem with this. I'm not able to place all code of my app here. Please help me about this what i can do.
UPDATE
Bulid.gradil(Modual:app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.azeem.onlinecontact"
minSdkVersion 11
targetSdkVersion 24
versionCode 3
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:24.2.1'
testCompile 'junit:junit:4.12'
compile 'com.google.android.gms:play-services-ads:10.0.1'
}
LoginActivity
public class LoginActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
}
protected void login(View view){
EditText etxtPhoneNumber = (EditText) findViewById(R.id.etxtPhoneNumber);
EditText etxtPassword = (EditText) findViewById(R.id.etxtPassword);
String phoneNumber = etxtPhoneNumber.getText().toString();
String password = etxtPassword.getText().toString();
String action = "login";
BackgroundWorker backgroundWorker = new BackgroundWorker(this);
backgroundWorker.execute(action, phoneNumber, password);
}
protected void forgetPassActivity(View view){
startActivity(new Intent(this, ForgetPassword.class));
}
protected void createAccount(View view){
Intent loginIntent = new Intent(this, CreateAccount.class);
startActivity(loginIntent);
}
#Override
public void onBackPressed() {
moveTaskToBack(true);
}
}
This activity open fine when I run app But it not work any further when I clicked on any button it will crashed.
My problem is: I need to pass present activity's context. and than toast message is shown. (when using external library that can not be edited)
When i pass my context. This always returns toast message.
But i don't want to show toast message.
Is it possible?
I'm using external MultiImagePicker library
here is my main code, just initialized. i do nothing.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Picker.Builder(this,new MyPickListener(),R.style.MIP_theme)
.setLimit(2)
.setPickMode(Picker.PickMode.MULTIPLE_IMAGES)
.build()
.startActivity();
}
private class MyPickListener implements Picker.PickListener
{
#Override
public void onPickedSuccessfully(final ArrayList<ImageEntry> images)
{
for(ImageEntry image : images){
Log.d("onPickedSuccessfully", "image.path #"+image.path);
}
}
#Override
public void onCancel(){
}
}
gradle(Module:app)
repositories {
maven { url 'https://dl.bintray.com/yazeed44/maven' }
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'net.yazeed44.imagepicker:imagepicker:1.3.0'
}
I really appreciate any help.
Try this,
You can go to the library, open that class and remove toast from the onCancel method().
#Override
public void onCancel() {
Log.i(TAG, "User canceled picker activity");
}
I want to set up a project in Android Studio. However, I don't want an Android App, just the test project.
Following the lastest release of UiAutomator, I was trying to set a class extending ActivityInstrumentationTestCase2 and start my tests from there.
However, I've stumbled in one thing: I can't figure out how to create the project without making it an app.
The options for creating a new project are:
Start a new Android Studio Project
Open existing projects
Import projects
I did:
Start a new project, give it a name, set minSDK and choose "No activity"
Open build.gradle (under app) and add the dependencies and instrumentation information mentioned in the end of Testing Support Library
Opened androidTest under src and changed the main file: changed to ActivityInstrumentationTestCase2, added setUp and tearDown; defined RunWith Junit4 (as indicated in Testing Support Library)
I build the project (build successful) - Press the green arrow next to build in the "action bar"
My problems are:
How do I install this in the device?
How do I run it in the device?
Do I need to do anything in the AndroidManifest?
Am I editing in the right place? Should I do anything under src/main?
I'd appreciate that the install and run instructions would be both for how to do it through Android Studio and using the command line (if you only know one of them post it anyway please).
Note: this is the first time I'm using Android Studio
Thanks in advance.
EDIT:
Right now I can build and run but it tells me I have no tests to run (empty test suite). Here are my graddle and my code.
My build.graddle is as follows:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "androidexp.com.ceninhas"
minSdkVersion 21
targetSdkVersion 22
versionCode 1
versionName "1.0"
testInstrumentationRunner="android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'LICENSE.txt'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile 'com.android.support.test:testing-support-lib:0.1'
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.0.0'
}
My source code (under src/androidTest/java/package) is:
#RunWith(AndroidJUnit4.class)
public class ApplicationTest extends ActivityInstrumentationTestCase2<Activity> {
public final static String ACTIVITY_NAME = "com.calculator.Main";
public final static Class<?> autActivityClass;
static {
try {
autActivityClass = Class.forName(ACTIVITY_NAME);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public ApplicationTest(){
super((Class<Activity>)autActivityClass);
}
#Before
public void setUp() throws Exception{
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
}
#After
public void tearDown() throws Exception{
super.tearDown();
}
#Test
public void cenas(){
assertTrue(true);
}
}
The run log on the console was:
Testing started at 18:06 ...
Waiting for device.
Target device: lge-nexus_5-08e506c10ddef123
Uploading file
local path: C:\Users\Ines\workspace\Ceninhas\app\build\outputs\apk\app-debug.apk
remote path: /data/local/tmp/androidexp.com.ceninhas
No apk changes detected. Skipping file upload, force stopping package instead.
DEVICE SHELL COMMAND: am force-stop androidexp.com.ceninhas
Uploading file
local path: C:\Users\Ines\workspace\Ceninhas\app\build\outputs\apk\app-debug-androidTest-unaligned.apk
remote path: /data/local/tmp/androidexp.com.ceninhas.test
No apk changes detected. Skipping file upload, force stopping package instead.
DEVICE SHELL COMMAND: am force-stop androidexp.com.ceninhas.test
Running tests
Test running startedFinish
Empty test suite.
What am I doing wrong?
I am also using uiautomator 2.0 from AndroidStudio. Here are some answers to your questions.
How do I install this in the device?
How do I run it in the device?
Make sure your device is connected using
adb devices
if not, you must connect it using
adb kill-server
adb connect xxx.xxx.xxx.xxx
Then from AndroidStudio, right click on your test class and click on "Run YourTestCase".
Do I need to do anything in the AndroidManifest?
I have nothing special in my manifest, but be sure you add
android {
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
in your build.gradle
Am I editing in the right place? Should I do anything under src/main?
Yes, you are editing at the right place. But you can move your code to src/main. To do so, you will need to change androidTestCompile to compile in your build.gradle file.
I did not try to run test from command line yet, but you can see AndroidStudio commands, maybe it can help.
I hope it helped you.
EDIT 1
I use this code
build.gradle (projectRoot)
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.0"
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'NOTICE'
exclude 'LICENSE.txt'
}
defaultConfig {
minSdkVersion 19
targetSdkVersion 22
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'])
compile 'com.android.support:appcompat-v7:22.0.0'
compile 'com.android.support.test:testing-support-lib:0.1'
compile 'com.android.support.test.uiautomator:uiautomator-v18:2.0.0'
compile project(':aiccore')
}
LoginTestCase (projectRoot/src/main/LoginTestCase.java)
public class LoginTestCase extends InstrumentationTestCase {
protected UiDevice device = null;
protected String appName;
public LoginTestCase() {
this("YourAppName")
}
public LoginTestCase(String appName) {
this.appName = appName;
}
public void runApp(String appName) throws UiObjectNotFoundException, RemoteException {
device = UiDevice.getInstance(getInstrumentation());
device.pressHome();
device.waitForWindowUpdate("", 2000);
UiObject2 allAppsButton = device.findObject(By.desc("Apps"));
allAppsButton.click();
device.waitForWindowUpdate("", 2000);
UiScrollable appViews = new UiScrollable(new UiSelector().scrollable(true));
appViews.setAsHorizontalList();
UiObject settingsApp = appViews.getChildByText(new UiSelector().className(TextView.class.getName()), appName);
settingsApp.clickAndWaitForNewWindow();
assertTrue("Unable to detect app", settingsApp != null);
}
#Override
public void setUp() throws RemoteException, UiObjectNotFoundException {
this.runApp(appName);
}
#Override
public void tearDown() throws RemoteException, UiObjectNotFoundException {
//Empty for the moment
}
public void testUS1() {
UiObject2 usernameLabel = device.findObject(By.clazz(TextView.class.getName()).text("Username"));
assertTrue("Username label not found", usernameLabel != null);
}
Well, actually, you should not write test code that way. Just keep your code under the src/androidTest folder, and write test code like this:
#RunWith(AndroidJUnit4.class)
#SdkSuppress(minSdkVersion = 18)
public class ChangeTextBehaviorTest {
private static final String BASIC_SAMPLE_PACKAGE
= "com.example.android.testing.uiautomator.BasicSample";
private static final int LAUNCH_TIMEOUT = 5000;
private static final String STRING_TO_BE_TYPED = "UiAutomator";
private UiDevice mDevice;
#Before
public void startMainActivityFromHomeScreen() {
// Initialize UiDevice instance
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// Start from the home screen
mDevice.pressHome();
// Wait for launcher
final String launcherPackage = mDevice.getLauncherPackageName();
assertThat(launcherPackage, notNullValue());
mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)),
LAUNCH_TIMEOUT);
// Launch the app
Context context = InstrumentationRegistry.getContext();
final Intent intent = context.getPackageManager()
.getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE);
// Clear out any previous instances
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
// Wait for the app to appear
mDevice.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)),
LAUNCH_TIMEOUT);
}
#Test
public void checkPreconditions() {
assertThat(mDevice, notNullValue());
}
#Test
public void testChangeText_sameActivity() {
// Type text and then press the button.
mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "editTextUserInput"))
.setText(STRING_TO_BE_TYPED);
mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "changeTextBt"))
.click();
// Verify the test is displayed in the Ui
UiObject2 changedText = mDevice
.wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "textToBeChanged")),
500 /* wait 500ms */);
assertThat(changedText.getText(), is(equalTo(STRING_TO_BE_TYPED)));
}
}
For detail please look out: UIAutomator Test sample