Communication between Chrome and Android Device - android

Hi guys I'm try to send string from Chrome app to another app following documentation but without result.
My page opened on Chrome app:
<!DOCTYPE html>
<html>
<body>
<p>URL: <a
href="intent://#Intent;scheme=printer_receiver;package=
kangel.com.printerhandler;S.name=Andrea;i.age=35;end">Do action</a></p>
</body>
</html>
My activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mText = findViewById(R.id.textUploaded);
//TRY ONE
Uri data = this.getIntent().getData();
if (data != null && data.isHierarchical()) {
String uri = this.getIntent().getDataString();
Log.i("PrinterHandler", "Deep link clicked " + uri);
mText.setText(uri);
}
//TRY TWO
Bundle extras = getIntent().getExtras();
if (extras != null){
String name = extras.getString("name");
Integer age = extras.getInt("age");
if (name!=null && age!=null) {
mText.setText(name);
}
}else{
mText.setText("No Data");
}
}
And manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="kangel.com.printerhandler">
<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/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<data android:scheme="printer_receiver" />
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
When I click in browser, load something but never load app.
Do you have any ideas?

Related

Create simple WebView with action.VIEW

Hi I've create a simple link browser, but I lost last update to open external URL.
This is the AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.browser">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:launchMode="singleInstance"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name="com.test.browser.WebViewActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.AppCompat.NoActionBar">
<intent-filter>
<data android:scheme="http" />
<data android:scheme="https" />
<action android:name="android.intent.action.PICK" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
</application>
</manifest>
And this my simple WebViewActivity.java
public class WebViewActivity extends AppCompatActivity {
public static Activity controller;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
controller = this;
mURL = "";
if (getIntent().getData() != null) {
setWebViewAndLoadURL(mURL);
} else {
this.finishAffinity();
}
}
}
The method 'setWebViewAndLoadURL' is not important because the action.VIEW not working.
Do you have any solutions?
I suggest to use the WebView layout in your activity which is more simple.
`<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />`
in your WebViewActivity modify the code with :
String url = "https://www.google.com";
setContentView(R.layout.your_layout);
WebView webView = (WebView) findViewById(R.id.my_webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl(url);
Tnx to all.
I found solution.
In XML I must add this to intent-filter:
<data android:scheme="http" android:host="*"/>
<data android:scheme="https" android:host="*"/>
And in Activity I must add intent URL:
mURL = "";
if (getIntent().getData() != null) {
mURL = getIntent().getData().toString();
setWebViewAndLoadURL(mURL);
}

How to open a url in chrome from app having deep linking

The main theme of my app is to open a website from my app into the chrome engine when user clicks on the button in the app. When i have implemented the code for click event it working fine, but when i have implemented the deep linking for my app, these was an that issue i'm facing.
My App is showing some thing like this when i click on the button. Instead of this when user clicks on the button the website has to launch in chrome engine.
The MainActivity file of my app look like:-
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
intent = getIntent();
action = intent.getAction();
uri = intent.getData();
if (uri != null) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://stackoverflow.com/")));
}
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://stackoverflow.com/")));
}
});
}
The Mainefest file of my app look like:-
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<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.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="stackoverflow.com"
android:scheme="http" />
</intent-filter>
</activity>
</application>
I have modified the code in the button click event, by setting package name of the chrome to the intent, and working fine as per my requirement.
Intent intent1 = new Intent(Intent.ACTION_VIEW);
intent1.setData(Uri.parse("http://stackoverflow.com/"));
intent1.setPackage("com.android.chrome");
startActivity(intent1);

How to open a single image in my app from file explorer

I am working on an app in which I want to open any photo in my app from external file explorer. Like when I click on photo, choose applications window appears and I select my app and image is shown in my app. But here, no image appears.
I added code in Manifest.xml:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.image.MainActivity"
android:label="#string/app_name" >
<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" />
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
<data android:mimeType="text/*" />
</intent-filter>
</activity>
</application>
Layout file activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
tools:context=".DataReceiverActivity" >
<ImageView
android:id="#+id/picture"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:contentDescription="Receive Picture Sharing" />
<TextView
android:id="#+id/txt"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
And in my MainActivity.java:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView picView = (ImageView) findViewById(R.id.picture);
TextView txtView = (TextView) findViewById(R.id.txt);
Intent receivedIntent = getIntent();
String receivedAction = receivedIntent.getAction();
String receivedType = receivedIntent.getType();
// make sure it's an action and type we can handle
if (receivedAction.equals(Intent.ACTION_SEND)) {
if (receivedType.startsWith("text/")) {
picView.setVisibility(View.GONE);
String receivedText = receivedIntent
.getStringExtra(Intent.EXTRA_TEXT);
if (receivedText != null) {
txtView.setText(receivedText);
}
} else if (receivedType.startsWith("image/")) {
txtView.setVisibility(View.GONE);
Uri receivedUri = (Uri) receivedIntent
.getParcelableExtra(Intent.EXTRA_STREAM);
if (receivedUri != null) {
picView.setImageURI(receivedUri);// just for demonstration
}
}
} else if (receivedAction.equals(Intent.ACTION_VIEW)) {
if (receivedType.startsWith("text/")) {
Toast.makeText(this, "TextRecived", Toast.LENGTH_SHORT).show();
Uri uri2 = receivedIntent.getData();
String uri = uri2.getEncodedPath() + " complete: "
+ uri2.toString();
txtView.setText(uri);
} else if (receivedType.startsWith("image/")) {
txtView.setVisibility(View.GONE);
Uri receivedUri = (Uri) receivedIntent
.getParcelableExtra(Intent.EXTRA_STREAM);
Toast.makeText(this, receivedUri.toString(), Toast.LENGTH_SHORT).show();
if (receivedUri != null) {
picView.setImageURI(receivedUri);// just for demonstration
}
}
} else if (receivedAction.equals(Intent.ACTION_MAIN)) {
txtView.setText("-----------------------------");
}
}
}
Here are my screenshots:
The problem is that you are trying to get Uri by wrong way. Change all occurances of
Uri receivedUri = (Uri) receivedIntent.getParcelableExtra(Intent.EXTRA_STREAM);
to
Uri receivedUri = receivedIntent.getData();
this will get you the right Uri of the file. Also do note that setImageURI does
Bitmap reading and decoding on the UI thread
Refer this link for more details.

Android: Starting a sharing intent closes my activity

In my fragment when I try to lunch a sharing intent, it closes my application. I want the intent to appear on top of my application and when the user finishes sharing and presses the back button, I want my application to appear. Here is my manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.joyfm.activity"
android:versionCode="5"
android:versionName="1.4" >
<uses-sdk
android:minSdkVersion="4"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:theme="#style/Theme.Sherlock"
android:allowBackup="true"
android:label="#string/app_name"
android:icon="#drawable/logo_launcher">
<activity
android:theme="#style/Theme.Sherlock"
android:name="com.joyfm.activity.MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:label="#string/app_name" >
</activity>
<activity
android:name="com.joyfm.activity.SplashActivity"
android:theme="#style/Theme.Sherlock"
android:launchMode="singleTask"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Here is my code in my EDITED fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
String authorInformation = "<i><BR>" + news.getAuthorInfo() + "<BR>\u00A9 www.myjoyonline.com</i>";
ScrollView layout = (ScrollView) inflater.inflate(R.layout.news_viewer, container, false);
TextView title = (TextView) layout.findViewById(R.id.txtTitle);
TextView summaryDetails = (TextView) layout.findViewById(R.id.summaryDetails);
TextView date = (TextView) layout.findViewById(R.id.txtNewsDate);
TextView copyRight = (TextView) layout.findViewById(R.id.txtCopyRight);
TextView newsDetails = (TextView) layout.findViewById(R.id.txtNewsDetails);
ImageViewSpinner image = (ImageViewSpinner) layout.findViewById(R.id.thumbNail);
title.setText(Html.fromHtml(news.getTitle()));
summaryDetails.setText(Html.fromHtml(ITALIC_START + news.getDescription() + ITALICS_END));
date.setText(Html.fromHtml(ITALIC_START + news.getDate() + ITALICS_END));
newsDetails.setText(Html.fromHtml(news.getNewsItem()));
copyRight.setText(Html.fromHtml(authorInformation));
if(news.getThumbnailUrl().trim().length() > 0)
{
imageDownloader.download(image, news.getThumbnailUrl(), null);
}else
{
image.setVisibility(View.GONE);
}
shareContentSubject = title.getText();
shareContentDetails = newsDetails.getText();
image.setClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
try
{
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, SHARED_SUBJECT + shareContentSubject);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareContentDetails);
startActivity(Intent.createChooser(sharingIntent, "Share with"));
}catch(Exception ex)
{
ex.printStackTrace();
}
}
});
return layout;
}
Please help, I have struggled with this and tried everything.
Issue Resolved. I had this in my activity so it was destroying it when the intent pops up.
#Override
protected void onUserLeaveHint()
{
super.onUserLeaveHint();
finish();
}
Register your Activity for the Share Intent in Android Mainfest file and check it once
<activity
android:name=".ActivityTest"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>

How to grant temporary access to custom content provider using FLAG_GRANT_READ_URI_PERMISSION

I am trying to query custom content provider(App A) from another app(App B).
I can do that when there is no permission protection for content provider. Specifically, I build custom content provider on App A and sent an intent containing the URI to App B.
Here is intent-sending part in App A.
class InsertOnClickListener implements OnClickListener{
public void onClick(View v) {
ContentValues values = new ContentValues();
values.put(DataBaseConfiguation.TableConfiguation.USER_NAME, "Jack");
Uri uri = getContentResolver().insert(DataBaseConfiguation.TableConfiguation.CONTENT_URI, values);
System.out.println("uri------------------->" + uri);
// the uri above should be like "content://com.catking.contentprovider.MyContentProvider/user"
Uri uri2 = Uri.parse("content://com.catking.contentprovider.MyContentProvider/user");
Cursor c = managedQuery(uri2, null, null, null, null);
String sendvalue = null;
if (c.moveToFirst()) {
do{
System.out.println("User name:"+c.getString(c.getColumnIndex(DataBaseConfiguation.TableConfiguation.USER_NAME)).toString());
sendvalue = c.getString(c.getColumnIndex(DataBaseConfiguation.TableConfiguation.USER_NAME)).toString();
} while (c.moveToNext());
}
Intent sendIntent = new Intent();
sendIntent.setClassName("com.android.web", "com.android.web.Provid");
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
sendIntent.putExtra("name", uri2.toString());
sendIntent.setType("text/plain");
startActivity(sendIntent);
}
}
followed by manifest file of App A.
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".ContentProviderTestActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider android:authorities="com.catking.contentprovider.MyContentProvider"
android:exported="true"
android:grantUriPermissions="true"
android:name="com.catking.contentprovider.MyContentProvider"
android:readPermission="android.permission.permRead"
android:writePermission="android.permission.permWrite" >
</provider>
</application>
Then App B(class Provid) get the URI and query the corresponding data in content provider(using following code).
public class Provid extends Activity {
public void onCreate(Bundle savedInstanceState) {
Bundle extras = getIntent().getExtras();
String userNameuri;
if (extras != null) {
userNameuri = extras.getString("name");
Uri allTitles = Uri.parse(userNameuri);
Cursor c = managedQuery(allTitles, null, null, null, null);
if (c.moveToFirst()) {
do{
System.out.println("Name is"+c.getString(c.getColumnIndex(DataBaseConfiguation.TableConfiguation.USER_NAME)).toString());
} while (c.moveToNext());
}
}
}
}
Here's App B's manifest file.
<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name="._GetWebResoureActivity"
android:label="#string/app_name" >
<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" >
</action>
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
<receiver android:name="StaticReceiver11" >
<intent-filter>
<action android:name="android.intent.action.MYSEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name="Provid"
android:label="#string/title_activity_provid" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
However, when I query content provider from App B, errors occur:
java.lang.RuntimeException: Unable to start activity ComponentInfo {com.android.web/com.android.web.Provid}: java.lang.SecurityException: Permission Denial: opening provider com.ck.contentprovider.MyContentProvider from ProcessRecord{426c6ea8 17032:com.android.web/u0a95} (pid=17032, uid=10095) requires android.permission.permRead or android.permission.permWrite
It seems that App B did not make use of the temporary permission to access. In other word, how to utilize FLAG_GRANT_READ_URI_PERMISSION from App B?
I have also tried directly adding Uri to intent(using setData()), instead of Uri.toString()(using putExtra()).
sendIntent.setData(uri2);
and
Uri userNameuri = getIntent().getData();
But the "userNameuri" got in App B is null.
I am totally confused...
updated
I tried "grantUriPermission("com.android.getCPaccess", uri2, Intent.FLAG_GRANT_READ_URI_PERMISSION)" according to a previous post
What is the correct permission handling when sending sensitive app data as email attachment?
And it works indeed. It can work without using FLAG_GRANT_READ_URI_PERMISSION. But the permission is not "temporary". It have to be ended manually by revokeUriPermission().
So, I am wondering if there is a way to grant temporary permission as introduced in FLAG_GRANT_READ_URI_PERMISSION, or it's a bug at all?
It seems that FLAG_GRANT_READ_URI_PERMISSION affects only Uri Intent.mData but not uris in extras.
I found similar problems when playing with ACTION_SEND, which takes an uri in EXTRA_STREAM. Providing the same uri in setData() will work, but doesn't conform to the rules and leads to unexpected behavior (e.g. Gmail recipient).
As of Jelly Bean intents can contain ClipData, which should solve the problem. For ACTION_SEND it's generated automatically from extras.
grantUriPermission will work, but requires revokeUriPermission. To do the same job as startActivity(Intent.createChooser(intent, title)) you will have to pick the target (ACTION_PICK_ACTIVITY), grant permissions to its package and revoke them when not needed anymore (onActivityResult?).
Here's some code:
Receiver app:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.handler" >
<application android:allowBackup="true" android:icon="#drawable/ic_launcher" android:label="#string/app_name" >
…
<activity
android:name=".ActivityView"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="*/*"/>
</intent-filter>
</activity>
</application>
</manifest>
ActivityView.java:
protected void onCreate(Bundle savedInstanceState) {
Intent intent = getIntent();
if ((intent != null)) {
procUri(intent.getData());
procUri(intent.<Uri>getParcelableExtra(Intent.EXTRA_STREAM));
}
}
private void procUri(Uri uri) {
if (uri != null) {
InputStream i;
try {
i = getContentResolver().openInputStream(uri);
byte[] b = new byte[i.available()];
i.read(b);
…
} catch (Throwable e) {
…
}
}
}
Sender app:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sender" >
<application android:allowBackup="true" android:icon="#drawable/ic_launcher" android:label="#string/app_name" >
…
<activity
android:name=".ActivitySend"
android:label="#string/app_name" >
</activity>
<provider
android:name=".MyContentProvider"
android:authorities="com.example.sender.content"
android:enabled="true"
android:exported="false"
android:grantUriPermissions="true" >
</provider>
</application>
</manifest>
ActivitySend.java:
// OK!
private void doTestView(Uri uri, String type) {
startActivity(
new Intent(Intent.ACTION_VIEW)
.setDataAndType(uri, type)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
);
}
// error prior to JellyBean
// ok on JellyBean, even without explicit FLAG_GRANT_READ_URI_PERMISSION (due to generated ClipData)
private void doTestSend(Uri uri, String type, CharSequence title) {
startActivity(
Intent.createChooser(
new Intent(Intent.ACTION_SEND)
.setType(type)
.putExtra(Intent.EXTRA_STREAM, uri)
.putExtra(Intent.EXTRA_SUBJECT, title)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
,
title
)
);
}
// working but not ok, unexpected results!
private void doTestSend2(Uri uri, String type, CharSequence title) {
startActivity(
Intent.createChooser(
new Intent(Intent.ACTION_SEND)
.setDataAndType(uri, type)
.putExtra(Intent.EXTRA_STREAM, uri)
.putExtra(Intent.EXTRA_SUBJECT, title)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
,
title
)
);
}

Categories

Resources