5

I read the documentation on receiving simple data. I want to receive an URL,i.e. text/plain from other apps.

So, I declared only this intent filter:

<intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>

In my MainActivity.class:

void onCreate (Bundle savedInstanceState) {
    ...
 // Get intent, action and MIME type

        Intent intent = getIntent();
        String action = intent.getAction();
        String type = intent.getType();

        if (Intent.ACTION_SEND.equals(action) && type != null) {
            if ("text/plain".equals(type)) {
                handleSendText(intent); // Handle text being sent
            }
        }
}

I'm handling the received text as:

void handleSendText(Intent intent) {
        String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
        if (sharedText != null) {
            // Update UI to reflect text being shared
            textBox.setText(sharedText);
        }
    }

But, the document reads that I should handle MIME types of other types carefully.

1) But, since I only registered for plain/text, do I need any more type handling code?

2) Moreover, citing documentation :

Keep in mind that if this activity can be started from other parts of the system, such as the launcher, then you will need to take this into consideration when examining the intent.

The MainActivity.java is also started by LAUNCHER. How do I handle that?

3) Once, user selects my app from the dialog, does it open that app, in all cases? I don't need my app to be opened. Can I circumvent that?

EDIT : I don't need my app's UI to be opened. But I want to receive the text.

enter image description here

Yash Sampat
  • 30,051
  • 12
  • 94
  • 120
Nikhil
  • 6,493
  • 10
  • 31
  • 68
  • `do I need any more type handling code?`. Well you are the one to find out. Under which scenarios your app is now started for types you do not handle? – greenapps Mar 02 '15 at 13:10
  • Since, my app is registered only for "text/plain" in intent-filter, my app doesn't show up when user wants to share other types like images. So, do I still need to handle that? – Nikhil Mar 02 '15 at 13:12
  • 1
    If your app does not show up. So not launched. Then where are you worrying about? If you do worry then simply display a Toast() saying that you are sorry. – greenapps Mar 02 '15 at 13:13

2 Answers2

3

1. Yes, you need to add mimeTypes for all file types you wish to share.

2. I think the problem may be that a starting Activity will also have

<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />. 

in its manifest declaration. So when you call

intent.getAction()

which action is returned ?? ACTION_SEND or MAIN? This is the problem they are talking about, I believe.

3. If you don't want your app to be displayed in the list of share apps, then why have you added the action

<action android:name="android.intent.action.SEND" />

to this Activity in the manifest in the first place ?? Because, the purpose of adding an action to an intent-filter is precisely that the Activity or Service or BroadcastReceiver can be started from another app by sending an implicit intent. And if you don't want that to happen, then how do you plan to "share text" anyway ??

Yash Sampat
  • 30,051
  • 12
  • 94
  • 120
  • No, I added that because I want my app to receive the text from other apps. But, when user clicks on my app, I don't want my app UI to be opened, but I want to grab that text. – Nikhil Mar 02 '15 at 13:27
  • Okay, can I register that intent filter in manifest for a service, unlike an activity. So, that I can avoid a UI being shown. – Nikhil Mar 02 '15 at 13:31
  • well then it will start a `Service`. Is that what you want ? What do you plan to do then ? – Yash Sampat Mar 02 '15 at 13:35
  • Yeah, basically the text would be a URL. I have some code in my app which will access that URL and grab some data from that page. I should also store this URL and the obtained data in Database. Yeah, I also think that not displaying a UI would be weird and user might worry, whether he had performed the action or not. – Nikhil Mar 02 '15 at 13:39
  • I'll better stick with activity only. I think it's better. What do you think ?Thanks again! :) – Nikhil Mar 02 '15 at 13:41
  • yes but I'd say that the "sharing" `Activity` and the "starting" `Activity` should not be the same, because there will be the problem of identifying the `action` – Yash Sampat Mar 02 '15 at 13:43
  • Okay. But my Activity has only UI - a textbox and button. I think that I don't have any code which is specific. Should I create another activity even then? Please look at the MainActivity.java in question. The "if" condition is checking if the action is ACTION_SEND or not. There isn't any other code in my activity. Do u still recommended to create another activity? – Nikhil Mar 02 '15 at 13:49
  • I think you should test it to see whether it works or not. What if it first gets `MAIN` action ? Then what is inside the `if` loop will not be executed ... but test it first anyway ... – Yash Sampat Mar 02 '15 at 13:52
1

Receriving all Data(like image, text) from other app(like gallery app image share to your app)

Kotlin

activity_receiving_data_from_other_app.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ReceivingDataFromOtherAppActivity">

    <TextView
        android:id="@+id/receivingDataTxt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:contentDescription="@string/todo"
        android:layout_marginTop="8dp"
        android:id="@+id/receivingSingleImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/receivingDataTxt" />

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/receivingSingleImageView"
        tools:ignore="SpeakableTextPresentCheck" />

</androidx.constraintlayout.widget.ConstraintLayout>

image_item.xml

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/imageViewMain"
    android:contentDescription="@string/todo">

</ImageView>

ImageUsPagerAdapter.kt


import android.content.Context
import android.net.Uri
import android.view.*
import androidx.viewpager.widget.PagerAdapter
import com.materialsouk.allcodeapp.R
import java.util.*
import kotlin.collections.ArrayList

class ImageUsPagerAdapter(context: Context, private val urlImage: ArrayList<String>?) :
    PagerAdapter() {

    private val mLayoutInflater =
        context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater?


    override fun getCount(): Int {
        return urlImage!!.size
        
    }

    override fun isViewFromObject(view: View, `object`: Any): Boolean {
        return view === `object`
    }

    override fun instantiateItem(container: ViewGroup, position: Int): Any {
        val itemView: View = mLayoutInflater!!.inflate(R.layout.image_item, container, false)
        val imageView: ImageView= itemView.findViewById(R.id.imageViewMain)

       
       imageView.setImageURI(Uri.parse(urlImage!![position]))
        
        Objects.requireNonNull(container).addView(itemView)
        return itemView
    }

    override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
        container.removeView(`object` as View?)
    }


}

ReceivingDataFromOtherAppActivity.kt

import android.content.Intent
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Parcelable
import android.widget.ImageView
import android.widget.TextView
import androidx.viewpager.widget.ViewPager

class ReceivingDataFromOtherAppActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_receiving_data_from_other_app)

        when {
            intent?.action == Intent.ACTION_SEND -> {
                if ("text/plain" == intent.type) {
                    handleSendText(intent) // Handle text being sent
                } else if (intent.type?.startsWith("image/") == true) {
                    handleSendImage(intent) // Handle single image being sent
                }
            }
            intent?.action == Intent.ACTION_SEND_MULTIPLE
                    && intent.type?.startsWith("image/") == true -> {
                handleSendMultipleImages(intent) // Handle multiple images being sent
            }
        }
    }
    private fun handleSendText(intent: Intent) {
        intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
            findViewById<TextView>(R.id.receivingDataTxt).text = it
        }
    }

    private fun handleSendImage(intent: Intent) {
        (intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let {
            // Update UI to reflect image being shared
            findViewById<ImageView>(R.id.receivingSingleImageView).setImageURI(it)
        }
    }

    private fun handleSendMultipleImages(intent: Intent) {
        intent.getParcelableArrayListExtra<Parcelable>(Intent.EXTRA_STREAM)?.let {
            // Update UI to reflect multiple images being shared
            val mViewPager = findViewById<ViewPager>(R.id.viewPager)
            val imageArrayList : ArrayList<String> = ArrayList()
            for (i in it){
                imageArrayList.add(i.toString())
            }
            val mViewPagerAdapter = ImageUsPagerAdapter(this, imageArrayList)
            mViewPager.adapter = mViewPagerAdapter
        }
    }
}

AndroidManifest.xml

 <application ...>
   <activity
            android:name=".ReceivingDataFromOtherAppActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
            </intent-filter>
        </activity>
 </application>
Meet Bhavsar
  • 442
  • 6
  • 12