Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't my app on the list of apps to open txt file?

I have an text reader app that is designed to receive intent from Android system when I click on a text file to open it. But my app isn't on the list popped up by the system. Below are my codes:

Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.broadcastreceivertest1"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk android:minSdkVersion="8" />

<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".BroadcastReceiverTest1Activity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<receiver android:name="MyBroadcastReceiver"> 
<intent-filter> 
<action android:name="android.intent.action.ACTION_VIEW" /> 
<action android:name="android.intent.action.ACTION_EDIT" /> 
<action android:name="android.intent.action.ACTION_PICK" /> 
<data android:scheme="file" /> 
<data android:mimeType="*/*" /> 
<data android:pathPattern=".*\\.txt" />    
<data android:host="*" /> 
</intent-filter> 
</receiver> 

</application>

</manifest>

My extended BroadcastReceiver

public final class MyBroadcastReceiver extends BroadcastReceiver {
private String TAG = "MyBroadcastReceiver";

@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent i = new Intent(context, BroadcastReceiverTest1Activity.class);
i.putExtra("URI", intent.getData());
context.startActivity(i);
Log.d(TAG, "Leaving onReceived...");
}
}

My activity to be opened by the broadcast receiver

public class BroadcastReceiverTest1Activity extends Activity {

private String uri ="";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Intent intent = getIntent();

final String action = intent.getAction();

if(Intent.ACTION_VIEW.equals(action)){
uri = intent.getStringExtra("URI");
TextView textView = (TextView)findViewById(R.id.textView);
textView.setText(uri);

}

}
}

Thanks!

like image 642
Jason Ching Avatar asked Jun 22 '12 08:06

Jason Ching


Video Answer


2 Answers

You need to associate your app with file extension. To do so, add these two line within intent filter and u'r good to go

<data android:scheme="file" />
<data android:mimeType="*/*"/>
<data android:pathPattern=".*\\.pdf" />

And your manifest would be look like this

<activity name="com.your.activity">
    <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:scheme="file" />
        <data android:mimeType="*/*" />
        <data android:pathPattern=".*\\.txt" />
    </intent-filter>
</activity>

<data android:scheme="file" /> => this define that the file must be local, not from http or else

<data android:mimeType="*/*" /> => match any mime type

<data android:pathPattern=".*\\.txt" /> => this is where you specify what extension you want to match

Hope this help

like image 106
Hein Avatar answered Sep 30 '22 12:09

Hein


elaborating on HERO's pseudo code, this effectively works:

change the <manifest> like this:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.broadcastreceivertest1"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="9" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".BroadcastReceiverTest1Activity" >
            <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:scheme="file" />
                <data android:mimeType="*/*" />
                <data android:pathPattern=".*\\.txt" />
            </intent-filter> 
        </activity>
    </application>
</manifest>

drop your broadcast receiver, because it is unnecessary.

change your BroadcastReceiverTest1Activity class (it does NOT need to be your MAIN activity, see BONUS below):

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class BroadcastReceiverTest1Activity extends Activity {
    private String TAG = "TagOpenTxt";
    private String uri ="";
    private Uri uri2;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        final Intent intent = getIntent();  
        final String action = intent.getAction();

        if(Intent.ACTION_VIEW.equals(action)){
            //uri = intent.getStringExtra("URI");
            uri2 = intent.getData();
            uri = uri2.getEncodedPath() + "  complete: " + uri2.toString();
            TextView textView = (TextView)findViewById(R.id.textView);
            textView.setText(uri);
            // now you call whatever function your app uses 
            // to consume the txt file whose location you now know 
        } else {
            Log.d(TAG, "intent was something else: "+action);
        }
    }
}

you have effectively created an intent listener for TXT files, which will call your app IF the user decides to use it (unless the user has previously associated file type TXT to another app...)

your app does NOT need to be active to catch intents. once installed, the system recognizes it as one of the "goto apps" for the particular mime types and/or extensions (less easy than associating by mime type) you chose.

BONUS: you can have a separate MAIN activity and when your BroadcastReceiver is called, it will execute within the same sandbox as your application, without impacting it (you will have to implement that in your MAIN activity's onResume method).

you can read the text data into static variable(s) [sloppy] OR you can place it in a SQLite db, which is permanent AND safe, regardless of app and/or phone shutting down, for example.

you could have the activity selfterminating and never even firing up a layout/window - which is sort of weird in case your user wants some kind of confirmation that the txt file was correctly and completely consumed by app.

like image 41
tony gil Avatar answered Sep 30 '22 12:09

tony gil