"Use Theme.AppCompat theme with this activity" Exception

427 views Asked by At

I used recently Android Asset Studio to generate a custom Action bar theme for an app and when I placed everything in my project the app crashes with this exception:

java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

This is the code in my style.xml:

<resources>

    <style name="Theme.Blinkmessage" parent="@android:style/Theme.Holo.Light">
        <item name="android:actionBarItemBackground">@drawable/selectable_background_blinkmessage</item>
        <item name="android:popupMenuStyle">@style/PopupMenu.Blinkmessage</item>
        <item name="android:dropDownListViewStyle">@style/DropDownListView.Blinkmessage</item>
        <item name="android:actionBarTabStyle">@style/ActionBarTabStyle.Blinkmessage</item>
        <item name="android:actionDropDownStyle">@style/DropDownNav.Blinkmessage</item>
        <item name="android:actionBarStyle">@style/ActionBar.Solid.Blinkmessage</item>
        <item name="android:actionModeBackground">@drawable/cab_background_top_blinkmessage</item>
        <item name="android:actionModeSplitBackground">@drawable/cab_background_bottom_blinkmessage</item>
        <item name="android:actionModeCloseButtonStyle">@style/ActionButton.CloseMode.Blinkmessage</item>


    </style>

    <style name="ActionBar.Solid.Blinkmessage" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">
        <item name="android:background">@drawable/ab_solid_blinkmessage</item>
        <item name="android:backgroundStacked">@drawable/ab_stacked_solid_blinkmessage</item>
        <item name="android:backgroundSplit">@drawable/ab_bottom_solid_blinkmessage</item>
        <item name="android:progressBarStyle">@style/ProgressBar.Blinkmessage</item>
    </style>

    <style name="ActionBar.Transparent.Blinkmessage" parent="@android:style/Widget.Holo.Light.ActionBar">
        <item name="android:background">@drawable/ab_transparent_blinkmessage</item>
        <item name="android:progressBarStyle">@style/ProgressBar.Blinkmessage</item>
    </style>

    <style name="PopupMenu.Blinkmessage" parent="@android:style/Widget.Holo.Light.ListPopupWindow">
        <item name="android:popupBackground">@drawable/menu_dropdown_panel_blinkmessage</item>
    </style>

    <style name="DropDownListView.Blinkmessage" parent="@android:style/Widget.Holo.Light.ListView.DropDown">
        <item name="android:listSelector">@drawable/selectable_background_blinkmessage</item>
    </style>

    <style name="ActionBarTabStyle.Blinkmessage" parent="@android:style/Widget.Holo.Light.ActionBar.TabView">
        <item name="android:background">@drawable/tab_indicator_ab_blinkmessage</item>
    </style>

    <style name="DropDownNav.Blinkmessage" parent="@android:style/Widget.Holo.Light.Spinner">
        <item name="android:background">@drawable/spinner_background_ab_blinkmessage</item>
        <item name="android:popupBackground">@drawable/menu_dropdown_panel_blinkmessage</item>
        <item name="android:dropDownSelector">@drawable/selectable_background_blinkmessage</item>
    </style>

    <style name="ProgressBar.Blinkmessage" parent="@android:style/Widget.Holo.Light.ProgressBar.Horizontal">
        <item name="android:progressDrawable">@drawable/progress_horizontal_blinkmessage</item>
    </style>

    <style name="ActionButton.CloseMode.Blinkmessage" parent="@android:style/Widget.Holo.Light.ActionButton.CloseMode">
        <item name="android:background">@drawable/btn_cab_done_blinkmessage</item>
    </style>

    <!-- this style is only referenced in a Light.DarkActionBar based theme -->
    <style name="Theme.Blinkmessage.Widget" parent="@android:style/Theme.Holo">
        <item name="android:popupMenuStyle">@style/PopupMenu.Blinkmessage</item>
        <item name="android:dropDownListViewStyle">@style/DropDownListView.Blinkmessage</item>
    </style>



    <style name="AuthBackground">
        <item name="android:background">@mipmap/background_fill</item>
    </style>

    <style name="AuthBackgroundImage">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">match_parent</item>
        <item name="android:layout_alignParentTop">true</item>
        <item name="android:layout_alignParentLeft">true</item>
        <item name="android:background">@mipmap/background</item>
        <item name="android:scaleType">fitStart</item>
        <item name="android:contentDescription">@string/content_desc_background</item>
    </style>

    <style name="AuthTitle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
        <item name="android:layout_alignParentTop">true</item>
        <item name="android:layout_centerHorizontal">true</item>
        <item name="android:textSize">50sp</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textColor">@android:color/white</item>
        <item name="android:layout_marginTop">32dp</item>
    </style>

    <style name="AuthSubtitle" parent="AuthTitle">
        <item name="android:textStyle">bold</item>
        <item name="android:textSize">13sp</item>
        <item name="android:layout_alignParentTop">false</item>
        <item name="android:layout_below">@+id/title</item>
        <item name="android:layout_marginTop">0dp</item>
    </style>

    <style name="AuthFiledContainer">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_below">@id/subTitle</item>
        <item name="android:layout_marginTop">@dimen/login_vertical_margin</item>
        <item name="android:layout_marginLeft">@dimen/activity_horizontal_margin</item>
        <item name="android:layout_marginRight">@dimen/activity_horizontal_margin</item>
        <item name="android:background">@android:color/white</item>
        <item name="android:paddingLeft">@dimen/login_horizontal_padding</item>
        <item name="android:paddingRight">@dimen/login_horizontal_padding</item>
        <item name="android:paddingTop">@dimen/activity_horizontal_margin</item>
        <item name="android:paddingBottom">@dimen/activity_horizontal_margin</item>
        <item name="android:orientation">vertical</item>
    </style>

    <style name="AuthEditText">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColorHint">@color/light_gray</item>
        <item name="android:textSize">17sp</item>
    </style>

    <style name="AuthButton">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:background">@drawable/button_custom</item>
        <item name="android:layout_marginLeft">@dimen/activity_horizontal_margin</item>
        <item name="android:layout_marginRight">@dimen/activity_horizontal_margin</item>
        <item name="android:textSize">13sp</item>
        <item name="android:textColor">@color/text_color</item>
        <item name="android:layout_centerHorizontal">true</item>
    </style>
</resources>

and this is the code in my manifest file:

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

    <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" />

    <uses-feature
        android:name="android.hardware.camera"
        android:required="true" />

    <application
        android:name=".RibbitApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.Blinkmessage" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.Blinkmessage">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".LoginActivity"
            android:label="@string/title_activity_login"
            android:screenOrientation="portrait" >
        </activity>
        <activity
            android:name=".SignUpActivity"
            android:label="@string/title_activity_sign_up"
            android:parentActivityName=".LoginActivity"
            android:screenOrientation="portrait" >
        </activity>

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity
            android:name=".EditFriendsActivity"
            android:label="@string/title_activity_edit_friends"
            android:parentActivityName=".MainActivity"
            android:screenOrientation="portrait" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="koemdzhiev.com.blinkmessage.MainActivity" />
        </activity>
        <activity
            android:name=".RecipientsActivity"
            android:label="@string/title_activity_recipients"
            android:parentActivityName=".MainActivity"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Holo.Light.DarkActionBar" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="koemdzhiev.com.blinkmessage.MainActivity" />
        </activity>
        <activity
            android:name=".ViewImageActivity"
            android:label="@string/title_activity_view_image"
            android:screenOrientation="portrait"
            android:parentActivityName=".MainActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="koemdzhiev.com.blinkmessage.MainActivity" />
        </activity>
    </application>

</manifest>

main activity:

public class MainActivity extends ActionBarActivity implements ActionBar.TabListener {
public static final int TAKE_PHOTO_REQUEST = 0;
public static final int TAKE_VIDEO_REQUEST = 1;
public static final int PICK_PHOTO_REQUEST = 2;
public static final int PICK_VIDEO_REQUEST = 3;
public static final int FILE_SIZE_LIMIT = 1024 * 1024 * 10;

public static final int MEDIA_TYPE_IMAGE = 4;
public static final int MEDIA_TYPE_VIDEO = 5;


// media path as Uri (Uniform resource unifier) unify system resorses
protected Uri mMediaUri;

protected DialogInterface.OnClickListener mDialogListener = new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        switch (which){
            case 0:  //Take picture
                Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                mMediaUri = getOutputMediaFileUrl(MEDIA_TYPE_IMAGE);
                if(mMediaUri == null){
                    // display an error
                    Toast.makeText(MainActivity.this,getString(R.string.error_external_storage),Toast.LENGTH_LONG).show();
                }
                takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT,mMediaUri);
                startActivityForResult(takePhotoIntent, TAKE_PHOTO_REQUEST);
                break;
            case 1: //Take video
                    Intent videoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
                    mMediaUri = getOutputMediaFileUrl(MEDIA_TYPE_VIDEO);
                if(mMediaUri == null){
                    // display an error
                    Toast.makeText(MainActivity.this,getString(R.string.error_external_storage),Toast.LENGTH_LONG).show();
                }
                videoIntent.putExtra(MediaStore.EXTRA_OUTPUT,mMediaUri);
                videoIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT,10);
                videoIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,0);
                startActivityForResult(videoIntent,TAKE_VIDEO_REQUEST);
                break;
            case 2://Choose picture
                Intent choosePhotoIntent = new Intent(Intent.ACTION_GET_CONTENT);
                choosePhotoIntent.setType("image/*");
                startActivityForResult(choosePhotoIntent,PICK_PHOTO_REQUEST);

                break;
            case 3:   //Choose video
                Intent chooseVideoIntent = new Intent(Intent.ACTION_GET_CONTENT);
                chooseVideoIntent.setType("video/*");
                Toast.makeText(MainActivity.this,getString(R.string.video_size_warning),Toast.LENGTH_LONG).show();
                startActivityForResult(chooseVideoIntent, PICK_VIDEO_REQUEST);
                break;
        }
    }

    private Uri getOutputMediaFileUrl(int mediaType) {
        if(isExternalStoreageAvailable()){
            //get URI

            // 1. Get the external storage directory
            String appName = MainActivity.this.getString(R.string.app_name);
            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                                        appName);
            Log.d(TAG,mediaStorageDir + "");
            // 2. Create our subdirectory
            if(! mediaStorageDir.exists()){
                //creates directory. IF it fails returns false otherwise it creates the directory and returns true
                if(! mediaStorageDir.mkdirs()){
                    Log.e(TAG,"Failer to create directory");
                    return null;
                };
            }
            // 3. Create a file name
            // 4. Create the file
            File mediaFile;
            Date now = new Date();
            String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.UK).format(now);
            String path = mediaStorageDir.getPath() + File.separator;
            if(mediaType == MEDIA_TYPE_IMAGE){
                mediaFile = new File(path + "IMG_" + timestamp + ".jpg");
            }else if (mediaType == MEDIA_TYPE_VIDEO){
                mediaFile = new File(path + "VID_" + timestamp + ".mp4");
            }else{
                return null;
            }

            // 5. Return the file's uri
            Log.d(TAG,"File: " + Uri.fromFile(mediaFile));
            return Uri.fromFile(mediaFile);
        }else{
            return null;
        }

    }

    private boolean isExternalStoreageAvailable(){
        String state = Environment.getExternalStorageState();
        if(state.equals(Environment.MEDIA_MOUNTED)){
            return true;
        }else{
            return false;
        }
    }
};



private static final String TAG = AppCompatActivity.class.getSimpleName();
/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link FragmentPagerAdapter} derivative, which will keep every
 * loaded fragment in memory. If this becomes too memory intensive, it
 * may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
SectionsPagerAdapter mSectionsPagerAdapter;

/**
 * The {@link ViewPager} that will host the section contents.
 */
ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    //start it here to be available in the Fragment's activity too
    supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    ParseUser currentUser = ParseUser.getCurrentUser();
    if(currentUser == null) {
        navigateToLogin();

    }else{
        Log.i(TAG,currentUser.getUsername());
    }
    // Set up the action bar.
    final ActionBar actionBar = getSupportActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    actionBar.setTitle("        Blink Message");
    actionBar.setLogo(R.mipmap.ic_launcher);
    actionBar.setDisplayUseLogoEnabled(true);
    actionBar.setDisplayShowHomeEnabled(true);

    // Create the adapter that will return a fragment for each of the three
    // primary sections of the activity.
    mSectionsPagerAdapter = new SectionsPagerAdapter(this,getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    // When swiping between different sections, select the corresponding
    // tab. We can also use ActionBar.Tab#select() to do this if we have
    // a reference to the Tab.
    mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            actionBar.setSelectedNavigationItem(position);
        }
    });

    // For each of the sections in the app, add a tab to the action bar.
    for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
        // Create a tab with text corresponding to the page title defined by
        // the adapter. Also specify this Activity object, which implements
        // the TabListener interface, as the callback (listener) for when
        // this tab is selected.
        actionBar.addTab(
                actionBar.newTab()
                        .setText(mSectionsPagerAdapter.getPageTitle(i))
                        .setTabListener(this));
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if(resultCode == RESULT_OK){
        // if we pick a photo or video store the uri
        if(requestCode == PICK_PHOTO_REQUEST || requestCode == PICK_VIDEO_REQUEST){
            if(data == null){
                Toast.makeText(this,R.string.general_error,Toast.LENGTH_LONG).show();
            }else{
                mMediaUri = data.getData();
            }
             Log.i(TAG,"Media path: "+mMediaUri);
            if(requestCode == PICK_VIDEO_REQUEST){
                //ckech the size of the video - less than 10 MB

                int fileSize = 0;
                InputStream inputStream = null;
                try {
                    inputStream = getContentResolver().openInputStream(mMediaUri);
                    fileSize = inputStream.available();
                }catch (FileNotFoundException e){
                    Toast.makeText(this,getString(R.string.error_open_file),Toast.LENGTH_LONG).show();
                    return;
                }catch (IOException e){
                    Toast.makeText(this,getString(R.string.error_open_file),Toast.LENGTH_LONG).show();
                    return;
                }finally {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    if(fileSize >= FILE_SIZE_LIMIT){
                        Toast.makeText(this,getString(R.string.file_too_large),Toast.LENGTH_LONG).show();
                        //return to the activity
                        return;
                    }
                }

            }
        }
        //else add it to the gallery
        else {
            //successful add it to the gallery
            Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            mediaScanIntent.setData(mMediaUri);
            sendBroadcast(mediaScanIntent);
        }

        Intent recipientsIntent = new Intent(this,RecipientsActivity.class);
        recipientsIntent.setData(mMediaUri);
        String fileType;
        if(requestCode == PICK_PHOTO_REQUEST || requestCode == TAKE_PHOTO_REQUEST){
            fileType = ParseConstants.TYPE_IMAGE;
        }else{
            fileType = ParseConstants.TYPE_VIDEO;
        }
        recipientsIntent.putExtra(ParseConstants.KEY_FILE_TYPE,fileType);
        startActivity(recipientsIntent);

    }else if(resultCode != RESULT_CANCELED){
        Toast.makeText(this,getString(R.string.general_error),Toast.LENGTH_LONG).show();
    }
}

private void navigateToLogin() {
    Intent intent = new Intent(this,LoginActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(intent);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    switch (id){
        case R.id.action_logout:
            ParseUser.logOut();
            navigateToLogin();
            break;
        case R.id.action_edit_friends:
            Intent intent = new Intent(this,EditFriendsActivity.class);
            startActivity(intent);
            break;
        case R.id.action_camera:
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setItems(R.array.camera_choices,mDialogListener);
            AlertDialog dialog = builder.create();
            dialog.show();
            break;
    }
    //noinspection SimplifiableIfStatement

    return super.onOptionsItemSelected(item);
}
//-----------ActionBar.TabListener methods-------------------//
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    // When the given tab is selected, switch to the corresponding page in
    // the ViewPager.
    mViewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}

@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
2

There are 2 answers

0
Blackbelt On BEST ANSWER

change the parent of your Theme.BlinkMessage to Theme.AppCompat.Light. This should fix your :

<style name="Theme.Blinkmessage" parent="Theme.AppCompat.Light">
0
Anton Kovalyov On

You should use Theme.AppCompat theme (or descendant) as parent for your theme.

<style name="Theme.Blinkmessage" parent="Theme.AppCompat">