I'm composing a Tweet and then launch Twitter app to tweet it like that:
intent = new TweetComposer.Builder(getFragmentActivity())
.text(viewHolder.etShareText.getText().toString())
.url(contentUrl)
.image(imageUri)
.createIntent();
It worked for a long time, and it still works, I'm able to post a tweet to my profile, but some time ago every action was resulted with RESULT_CANCELED in my onActivityResult() method despite the actual result was successfull.
Maybe something had changed in Twitter API? How to handle results now?
Actually, in this case onActivityResult() usage may not true way. To catch composing result, like vijikumar said, we should use BroadcastReceiver. But this information is not enough for us. Because in many cases, twitter composing ways are confused with each other. Like documentation said ; there are two ways to compose tweets :
Launch the Twitter application’s Tweet Composer
Launch the Twitter Kit Native Composer
If you prefer to use first way, as long as i see, there is not a healthy method to catch composing result using BroadcastReceiver, onActivityResult or etc.
BroadcastReceiver method does not work using first way. But if you prefer to use second way, you can catch composing result using BroadcastReceiver in a healthy position. You shouldn't think that first way is not important. I am going to talk about first way briefly.
To do these above ;
Second Way
Add below repository and dependencies in your app level gradle file
repositories {
jcenter()
}
compile 'com.twitter.sdk.android:twitter-core:3.1.1'
compile 'com.twitter.sdk.android:tweet-composer:3.1.1'
Then add below BroadcastReceiver
public class MyResultReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (TweetUploadService.UPLOAD_SUCCESS.equals(intent.getAction())) {
// success
} else if (TweetUploadService.UPLOAD_FAILURE.equals(intent.getAction())) {
// failure
} else if (TweetUploadService.TWEET_COMPOSE_CANCEL.equals(intent.getAction())) {
// cancel
}
}
}
Then add your BroadcastReceiver to the application manifest file like below
<receiver
android:name=".MyResultReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.twitter.sdk.android.tweetcomposer.UPLOAD_SUCCESS"/>
<action android:name="com.twitter.sdk.android.tweetcomposer.UPLOAD_FAILURE"/>
<action android:name="com.twitter.sdk.android.tweetcomposer.TWEET_COMPOSE_CANCEL"/>
</intent-filter>
</receiver>
As last, to open the composer screen, start ComposerActivity using below code block
final TwitterSession session = TwitterCore.getInstance().getSessionManager()
.getActiveSession();
final Intent intent = new ComposerActivity.Builder(YourActivity.this)
.session(session)
.text("Love where you work")
.hashtags("#twitter")
.createIntent();
startActivity(intent);
When you use this way, you will catch composer result in BroadcastReceiver.
I will not share any code block about First Way. But why can we need the first way ? Actually first way contains very rich content but as long as i see, it does not support to catch result. So second way is enough for us in many cases. however if Twitter app does not exist the device, second way will crash because of session. In this case, we should use first way to open composer screen in internet browser. So we should use both ways but like you see that first one is more effective than second one.
NOTE : Do not forget to add the twitter kit initialization configurations and authentication mechanisms please.
Use BroadcastReceiver.
public class MyResultReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (TweetUploadService.UPLOAD_SUCCESS.equals(intent.getAction())) {
// success
final Long tweetId = intentExtras.getLong(TweetUploadService.EXTRA_TWEET_ID);
} else {
// failure
final Intent retryIntent = intentExtras.getParcelable(TweetUploadService.EXTRA_RETRY_INTENT);
}
}
}
In manifest
<receiver
android:name=".MyResultReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.twitter.sdk.android.tweetcomposer.UPLOAD_SUCCESS"/>
<action android:name="com.twitter.sdk.android.tweetcomposer.UPLOAD_FAILURE"/>
</intent-filter>
</receiver>
Related
I have an issue that I have not found a solution to on this site, but if this is a duplicate question, I apologize.
I am developing an application that serves as a terminal for registering when employees start/finish work, among numerous other things. The way it works is that with NFC switched-on, they scan their NFC cards and my app reads them and ultimately sends the appropriate information to the server.
However, if the app is already open (it's supposed to be open all the time, so this is an issue) and an NFC card is scanned, it reopens the app. Of course, this is done because I have set it that way in the manifest. But I can not find a way to have my app recieve the NFC scan intent if I do not add all of these lines in the manifest:
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
I have tried just writing without the but in that case it does not read the card, but instead the program chooser comes up on the phone, or if the phone does not have an appropriate app it simply says "NFC read error".
Does anyone have a solution for this? This is the last step in my project, and I have had a lot of trouble with it, and would appreciate any help. It's probably something simple that I'm just not seeing, but I'd appreciate it either way.
Android activities have different launch modes. If you set single instance it will use already opened activity and doesn't create a new activity. You can read the new intent in override method onNewIntent()
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// read intent values here
}
For various activity elements
You can use broadcastReceiver,
- first initiate the receiver to your activity
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("whateveryouwant");
notificationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// here you can read the intent and customize the action;
int usage = intent.getIntExtra("usage",1000);
}
}
};
second register the broadcast
registerReceiver(notificationBroadcastReceiver,intentFilter);
At end unregister to the broadcast in the onDestroy method
#Override
protected void onDestroy() {
if(notificationBroadcastReceiver != null){
unregisterReceiver(notificationBroadcastReceiver);
notificationBroadcastReceiver = null;
}
super.onDestroy();
}
after doing that instead of intenting activity you can sendBroadcast()
a little guide: https://developer.android.com/reference/android/content/BroadcastReceiver.html
hope it will be helpfull
I am facing a problem in override the On Click Behavior in Appboy deeplink
Please find the following data
1- Register Appboy in BaseActivity which is the parent activity for all Application Activities
#Override
protected void onResume() {
AppboyInAppMessageManager.getInstance().registerInAppMessageManager(this);
Appboy.getInstance(this).requestInAppMessageRefresh();
}
#Override
protected void onPause() {
AppboyInAppMessageManager.getInstance().unregisterInAppMessageManager(this);
}
2- Add the receivers in Manifest File as following
<receiver android:name="com.forsale.forsale.appboy.AppboyGcmReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.forsale.forsale" />
</intent-filter>
</receiver>
<receiver
android:name="com.forsale.forsale.appboy.AppBoyOpenReceiver"
android:exported="false" >
<intent-filter>
<action android:name="com.forsale.forsale.intent.APPBOY_PUSH_RECEIVED" />
<action android:name="com.forsale.forsale.intent.APPBOY_NOTIFICATION_OPENED" />
</intent-filter>
</receiver>
Know I can send in app message using app boy dashboard, and receive the message, but when I click the message it open appboy web activity with the link
I need to override this behaviour to be able to get the link that I sent in In app message and parse some parameters from it and direct the use to an activity inside my app
I have tried the following
remove default app boy web activity from manifest file /// the app crash
implement the IInAppMessageManagerListener /// the app stop receiving any messages
Please note that the application call the onReceive method when trying to register appboy and print the log (action = REGISTRATION, RegId = "..."), but it never lo any other actions like RECEIVE, or OPEN
public void onReceive(Context context, Intent intent) {
AppboyLogger.i("AMIRA", String.format("Amira %s", intent.toString()));
String action = intent.getAction();
AppboyLogger.i("AMIRA", String.format("Amira %s", action));
Bundle bundle = intent.getExtras();
for (String key : bundle.keySet()) {
Object value = bundle.get(key);
AppboyLogger.i("AMIRA", String.format("Amira %s", key + ":" + value.toString()));
}
}
The root of the problem is that we differentiate deep links and http links based on schema of the URI, so http (and some other schemes) links are detected as web links, and other formats are seen as deep links (see https://github.com/Appboy/appboy-android-sdk/blob/master/android-sdk-ui/src/com/appboy/ui/actions/ActionFactory.java).
We’ll consider how to instrument things for the use case you have, but in the meantime there’s a couple of ways you could solve the issue:
1) Create a deep link that is not also an http link. Everything should work if your link instead looks like, for example, forsale://mylink?a=b&2=3....etc.
2) Set a custom in-app message manager listener: https://documentation.appboy.com/Android/#in-app-message-customization. You can see an example of how we do this in our Droidboy sample app. In your case, you’d want to return defaults for everything but onInAppMessageButtonClicked and onInAppMessageClicked where you’d want to handle the link yourself if it’s of the format of your deep link. Your ticket indicates you’ve tried this, but I’d suggest starting with "the default one we create in the AppboyInAppMessageManager.java (#L608) in the Android SDK - and then just modifying the *clicked methods.
3) Download our UI code and modify the source. You could optionally download the Appboy Android SDK and modify the ActionFactory to handle your deep link in the way you want. Though, at the point you are going to do something like this, solution #2 is likely going to be a nicer one to implement and maintain.
Please let us know if one of these solutions works for you and if you have any other comments/questions.
Thanks,
Waciuma
I'm trying to use this library:
https://github.com/thorikawa/EyeGestureLib
but it not works..
When app starts, occurs a NullPointerException on this line of "onStart()" function:
mEyeGestureManager.register(target1, mEyeGestureListener);
mEyeGestureManager.register(target2, mEyeGestureListener);
I've the other code like the appDemo exposed in the github repository and this lines in "onCreate" function:
mEyeGestureManager = EyeGestureManager.from(this);
mEyeGestureListener = new EyeGestureListener();
Any suggestion? Is there an update library?
The library you posted is pretty outdated (last change 11 months ago). There is currently no official way to detect a wink. I had the same problem to detect only the wink and stop glass to take pictures when detecting it. There are several ways to detect such EyeGestures. Here is what worked for me (quoted from this awesome source):
To listen to Intent, you have to extend BroadcastReceiver.
public class EyeGesture extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra("gesture").equals("WINK")) {
//Disable Camera Snapshot
abortBroadcast();
Log.e("WINKED ","");
} else {
Log.e("SOMETHING", "is detected " + intent.getStringExtra("gesture"));
}
}
}
You must register the intent in the Manifest as below:
<receiver android:name="com.inno.inno.glassplugin.EyeGesture">
<intent-filter>
<action android:name="com.google.android.glass.action.EYE_GESTURE" />
</intent-filter>
</receiver>
The name specified in the Manifest must match the name of the class listening to the intent which is EyeGesture.
Simple as that. No library required but only WINK can be detected. It also stops Glass from taking picture when wink is detected. You can comment abortBroadcast(); if you want Glass to take picture when event is detected.
I work in a company that produces several apps, not all those apps have the same signature or more like it we have at least 5-6 apps certificates for the time being.
We tried to create a mechanism in which all the companie's apps on the same device share the same is,
For example if user installed from the market App A and no app installed, a new ID will be generated, if now he installs App A, app B should have the same id as App A(id is just a generated UUID type #4) etc...
We are using broadcast at the moment and only apps with our permission can receive that broadcast and send back the id with another broadcast(explicit this time).
The broadcast and the responses are protected with our permission with signature level, this is of course not helping since we have more than one signature.
I tried to write an intent broadcast and recover that can have it's own mechanism of protection that will not be limited to only one signature but several, the problem is that things like Binder.getSenderUID() doesn't work for broadcasts and i get my own uid.
it looks like i have no way to get the identity of my snder unless he itself writes his id in the intent, which is NOT something i can trust as it can be easily faked.
Using encryption requires the apps to come with a key on them, which is not secured once more, turning to a server for validation takes too much time and on mobile not guaranteed to success since not 100% sure there is network around.
Anyone has any idea how can one get a validate\secure message from one app to another ?(all my apps but may have different signatures).
As always with a challenging question here i never get a proper, if ANY!' answer, so i'm forced to find it myself.
The problem with Intents is that it's not possible to get the sender as they are the parallel to mulicast in a network where there sender's address is not important.
If i wish to get the snder's UID i need to make a "remote" process even if he is local, instead of using broadcast IPC i need to use AIDL with IBInder implementation.
Once i have a Binder object i can call in my service getCallingUid() and get the uid of the caller, this will allow me to ask PackageManager to give me it's public certificate (without asking the process itself, i ask the OS) and compare it to a set of certificates i prepared in advance in the apk.
The calling application on the other side(the other process that sends me it's ID) just has to use the bindService(service, conn, flags) method to bind to me.
The disadvantage to this approach is ofcourse the time consuming process, Bind takes time, it's an async call that pass through the kernel and is not as fast as binding to a local service. Moreover since i might have several applications i need to synchronize the access my internal ID so only the first binding call that didn't fail will set and ID for me.
I still need to check if i can use the Messanger method that prevents the multi thread issues.
Hopes this helps someone else.
Sorry for late response...
Bind takes time, and more importantly, its asynchronous.
However, there is a way to make a synchronous bind - assuming of course the service you attempt to contact is already started at the time.
Android allowed for this more for BroadcastReceivers (which are async in nature, and thus can't use normal bindService) a BroadcastReceiver has a "peekService" method.
If you want to use it without listening to a broadcast, you can by doing:
final IBinder[] b = new IBinder[1];
new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
b[0] = peekService(context, intent);
}
}.onReceiver(context, intent);
IMyInterface i = IMyInterface.Stub.asInterface(b[0);
note that you don't bind to the service, so make sure to peek at on each use.
As already stated, binding is probably the best solution to this. However, you could consider switching to an Activity rather than a BroadcastReceiver then you can use getCallingActivity(), assuming you launched with startActivityForResult().
Declare you Activity as follows to make it "silent" like a BroadcastReceiver:
<activity
android:name=".FauxReceiver"
android:theme="#android:style/Theme.NoDisplay"
android:excludeFromRecents="true"
android:noHistory="true"
>
<intent-filter>
...
</intent-filter>
</activity>
Inspiration: How to get the sender of an Intent?
I was looking for a way to verify the package name of the application that sent the intent received by my intent-filter. That activity in my app that handles the intent-filter requires that the intent sender includes their process id in an Intent Extras field. My receiving activity can then get the associated application package name from the ActivityManager.
Here is some example code I found while shifting through StackOverflow.
Constants needed for both Apps
public static final String EXTRA_APP_ID;
public static final String ACTION_VERIFY = "com.example.receivingapp.action.VERIFY";
Calling Activity
Intent verifyIntent = new Intent();
verifyIntent.setAction(Consts.ACTION_VERIFY);
verifyIntent.putExtra(EXTRA_APP_ID, android.os.Process.myPid());
// Verify that the intent will resolve to an activity
if (verifyIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(verifyIntent, Consts.REQUEST_VERIFY);
} else {
Log.d(TAG, "Application not found.");
}
Receiving App
Manifest
<activity
android:name="com.example.receivingapp.ReceivingActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="com.example.receivingapp.VERIFY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
ReceivingActivity
if (getIntent().hasExtra(OnyxCoreConsts.EXTRA_APP_ID)) {
string appName = null;
// Resolve intent
if (getIntent().getAction().equals(ACTION_VERIFY) {
int appPid = getIntent().getIntExtra(EXTRA_APP_ID, -1);
if (-1 != mAppPid) {
appName = Utils.getAppNameByPID(mContext, mAppPid);
}
if (null != appName && !"".equalsIgnoreCase(appName)) {
// Do something with the application package name
}
}
}
Utils class
public static String getAppNameByPID(Context context, int pid){
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
if (processInfo.pid == pid) {
return processInfo.processName;
}
}
return "";
}
I want my application to be activated when the user make a specific call. Is there any way to take information which call is making by user in the same time ( not afterwords ) in order to activate the app at the right time ?
Ok i wrote this code for my case and it works:
public class OutgoingCallReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(null == bundle) return;
String phonenumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
if( phonenumber.equals("11111111") ) {
Intent myactivity = new Intent(context, MyKeyboard.class);
myactivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myactivity);
}
}
}
In the Manifest i add this:
<receiver
android:name=".OutgoingCallReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
I don't really know, but I think that's a really dangerous practice. It all depends on what you intend to do with your app. If it's a recording app, I think you can't even think of developping it, or don't post on the internet about it because it would be illegal in many countries. That's how I see and how I feel your question. About Android there is not 15k places to search, have a look at the android API.
http://developer.android.com/reference/android/provider/CallLog.Calls.html
This, for example, I don't know if it's a real time log, or if it's filled after the call is terminated. But you can search in that direction.