Content Providers in Android
●
    Overall structure
●
    Interaction with Content Provider
●
    Constructing query
●
    Retreiving cursor asyncronuously
●
    Provider permissions
●
    Creating Content Provider
●
    Questions
●
    Overall structure
●
    Interaction with Content Provider
●
    Constructing query
●
    Retreiving cursor asyncronuously
●
    Provider permissions
●
    Creating Content Provider
●
    Questions
Overall structure
                                                    Application #2
 Application #1
                                                     Activity #1
  Activity #1

  Activity #2             Content Provider          Application #3

  Activity #3                                        Activity #1

                                                     Activity #2




                                              Remote
Database          Files         XML                                …
                                             connection
Content Provider is a source
                                                    Application #2
 Application #1
                                                     Activity #1
  Activity #1

  Activity #2             Content Provider          Application #3

  Activity #3                                        Activity #1

                                                     Activity #2




                                              Remote
Database          Files         XML                                …
                                             connection
For some consumers
                                                    Application #2
 Application #1
                                                     Activity #1
  Activity #1

  Activity #2             Content Provider          Application #3

  Activity #3                                        Activity #1

                                                     Activity #2




                                              Remote
Database          Files         XML                                …
                                             connection
Gives access to variety types of data
                                                     Application #2
  Application #1
                                                      Activity #1
   Activity #1

   Activity #2             Content Provider          Application #3

   Activity #3                                        Activity #1

                                                      Activity #2




                                               Remote
 Database          Files         XML                                …
                                              connection
Overall structure
                                                    Application #2
 Application #1
                                                     Activity #1
  Activity #1

  Activity #2             Content Provider          Application #3

  Activity #3                                        Activity #1

                                                     Activity #2




                                              Remote
Database          Files         XML                                …
                                             connection
●
    Overall structure
●
    Interaction with Content Provider
●
    Constructing query
●
    Retreiving cursor asyncronuously
●
    Provider permissions
●
    Creating Content Provider
●
    Questions
Interaction with Content Provider
                                                    Application #2
 Application #1
                                                     Activity #1
  Activity #1

  Activity #2             Content Provider          Application #3

  Activity #3                                        Activity #1

                                                     Activity #2




                                              Remote
Database          Files         XML                                …
                                             connection
Activity to Content Provider access
Activity


   Cursor        ContentResolver   Content Provider




 CursorAdapter       ListView
Activity
Activity


   Cursor        ContentResolver   Content Provider




 CursorAdapter       ListView
Performing request

                                Content Provider

                                Query

                                Insert
ContentResolver       URI
                                Update

                                Delete
URI



content://com.example.provider/articles

 Scheme          Authority       Path
●
    Overall structure
●
    Interaction with Content Provider
●
    Constructing query
●
    Retreiving cursor asyncronuously
●
    Provider permissions
●
    Creating Content Provider
●
    Questions
Constructing query



SELECT _id, title, content, date
FROM articles
WHERE date >= 1352470000
ORDER BY date ASC
Constructing query
String[] mProjection =
    {
        "_id",
        "title",
        "content",
        "date",
    };
String mSelection = "date >= ?";
String[] mSelectionArgs = {"1352470000"};
String mSortOrder = "date ASC";
Cursor cursor = getContentResolver().query(
        MyContentProvider.ARTICLES_CONTENT_URI,
        mProjection,
        mSelection,
        mSelectionArgs,
        mSortOrder);
Constructing query
String[] mProjection =
    {
        "_id",
        "title",
        "content",
        "date",
    };
String mSelection = "date >= ?";
String[] mSelectionArgs = {"1352470000"};
String mSortOrder = "date ASC";
Cursor cursor = getContentResolver().query(
        MyContentProvider.ARTICLES_CONTENT_URI,
        mProjection,
        mSelection,
        mSelectionArgs,
        mSortOrder);
Constructing query
String[] mProjection =
    {
        "_id",
        "title",
        "content",
        "date",
    };
String mSelection = "date >= ?";
String[] mSelectionArgs = {"1352470000"};
String mSortOrder = "date ASC";
Cursor cursor = getContentResolver().query(
        MyContentProvider.ARTICLES_CONTENT_URI,
        mProjection,
        mSelection,
        mSelectionArgs,
        mSortOrder);
Constructing query
String[] mProjection =
    {
        "_id",
        "title",
        "content",
        "date",
    };
String mSelection = "date >= ?";
String[] mSelectionArgs = {"1352470000"};
String mSortOrder = "date ASC";
Cursor cursor = getContentResolver().query(
        MyContentProvider.ARTICLES_CONTENT_URI,
        mProjection,
        mSelection,
        mSelectionArgs,
        mSortOrder);
Constructing query
String[] mProjection =
    {
        "_id",
        "title",
        "content",
        "date",
    };
String mSelection = "date >= ?";
String[] mSelectionArgs = {"1352470000"};
String mSortOrder = "date ASC";
Cursor cursor = getContentResolver().query(
        MyContentProvider.ARTICLES_CONTENT_URI,
        mProjection,
        mSelection,
        mSelectionArgs,
        mSortOrder);
Constructing query
String[] mProjection =
    {
        "_id",
        "title",
        "content",
        "date",
    };
String mSelection = "date >= ?";
String[] mSelectionArgs = {"1352470000"};
String mSortOrder = "date ASC";
Cursor cursor = getContentResolver().query(
        MyContentProvider.ARTICLES_CONTENT_URI,
        mProjection,
        mSelection,
        mSelectionArgs,
        mSortOrder);
Cursor
      _id                title             content           date
1             First article        Lorem ipsum...      1352475013
2             Second article       Dolor sit amet...   1352471413
...           ...                  ...                 ...




      if (mCursor != null) {
          while (mCursor.moveToNext()) {
              String title = mCursor.getString(Columns.TITLE);
          }
      }
●
    Overall structure
●
    Interaction with Content Provider
●
    Constructing query
●
    Retreiving cursor asyncronuously
●
    Provider permissions
●
    Creating Content Provider
●
    Questions
Activity & blocking queries
Activity


   Cursor        ContentResolver   Content Provider




 CursorAdapter       ListView
Activity & non blocking queries
Activity

CursorLoader



     Cursor         ContentResolver

                                        Content Provider

                    AsyncQueryHandler




    CursorAdapter        ListView
Activity & Loader
Activity

CursorLoader



     Cursor          ContentResolver

                                         Content Provider

                     AsyncQueryHandler




    CursorAdapter         ListView
Activity & Loader
public class ArticlesActivity extends FragmentActivity implements
LoaderCallbacks<Cursor> {
...
getSupportLoaderManager().initLoader(0, null, this);
...
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(
            this,            // context
            MyContentProvider.ARTICLES_CONTENT_URI,
            mProjection,
            mSelection,
            mSelectionArgs,
            mSortOrder);
}

public void onLoadFinished(
        Loader<Cursor> loader,
        Cursor cursor) {
    mAdapter.swapCursor(cursor);
}
Activity & Loader
public class ArticlesActivity extends FragmentActivity implements
LoaderCallbacks<Cursor> {
...
getSupportLoaderManager().initLoader(0, null, this);
...
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(
            this,            // context
            MyContentProvider.ARTICLES_CONTENT_URI,
            mProjection,
            mSelection,
            mSelectionArgs,
            mSortOrder);
}

public void onLoadFinished(
        Loader<Cursor> loader,
        Cursor cursor) {
    mAdapter.swapCursor(cursor);
}
Activity & Loader
public class ArticlesActivity extends FragmentActivity implements
LoaderCallbacks<Cursor> {
...
getSupportLoaderManager().initLoader(0, null, this);
...
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(
            this,            // context
            MyContentProvider.ARTICLES_CONTENT_URI,
            mProjection,
            mSelection,
            mSelectionArgs,
            mSortOrder);
}

public void onLoadFinished(
        Loader<Cursor> loader,
        Cursor cursor) {
    mAdapter.swapCursor(cursor);
}
Activity & Loader
public class ArticlesActivity extends FragmentActivity implements
LoaderCallbacks<Cursor> {
...
getSupportLoaderManager().initLoader(0, null, this);
...
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(
            this,            // context
            MyContentProvider.ARTICLES_CONTENT_URI,
            mProjection,
            mSelection,
            mSelectionArgs,
            mSortOrder);
}

public void onLoadFinished(
        Loader<Cursor> loader,
        Cursor cursor) {
    mAdapter.swapCursor(cursor);
}
Activity & Loader
public class ArticlesActivity extends FragmentActivity implements
LoaderCallbacks<Cursor> {
...
getSupportLoaderManager().initLoader(0, null, this);
...
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(
            this,            // context
            MyContentProvider.ARTICLES_CONTENT_URI,
            mProjection,
            mSelection,
            mSelectionArgs,
            mSortOrder);
}

public void onLoadFinished(
        Loader<Cursor> loader,
        Cursor cursor) {
    mAdapter.swapCursor(cursor);
}
Activity & AsyncQueryHandler
Activity

CursorLoader



     Cursor         ContentResolver

                                        Content Provider

                    AsyncQueryHandler




    CursorAdapter        ListView
Activity & AsyncQueryHandler
private AsyncQueryHandler mHandler;

...



mHandler = new MyAsyncQueryHandler(getContentResolver());
mHandler.startQuery(
    0,                // token
    null,             // cookie
    MyContentProvider.ARTICLES_CONTENT_URI,
    mProjection,
    mSelection,
    mSelectionArgs,
    mSortOrder);
Activity & AsyncQueryHandler

class MyAsyncQueryHandler extends AsyncQueryHandler {
    public MyAsyncQueryHandler(ContentResolver cr) {
        super(cr);
    }

    @Override
    protected void onQueryComplete(
            int token,
            Object cookie,
            Cursor cursor) {
        mAdapter.swapCursor(cursor);
    }
}
●
    Overall structure
●
    Interaction with Content Provider
●
    Constructing query
●
    Retreiving cursor asyncronuously
●
    Provider permissions
●
    Creating Content Provider
●
    Questions
Permissions

<permission
    android:name="com.example.provider.permission.READ_ARTICLES"
    android:protectionLevel="normal" />



<provider android:name=".MyContentProvider"
    android:exported="false"
    android:authorities="com.example.provider"
    android:permission="com.example.provider.permission.READ_ARTICLES"
/>



<uses-permission
    android:name="com.example.provider.permission.READ_ARTICLES" />
Permissions

<permission
    android:name="com.example.provider.permission.READ_ARTICLES"
    android:protectionLevel="normal" />



<provider android:name=".MyContentProvider"
    android:exported="false"
    android:authorities="com.example.provider"
    android:permission="com.example.provider.permission.READ_ARTICLES"
/>



<uses-permission
    android:name="com.example.provider.permission.READ_ARTICLES" />
Permissions

<permission
    android:name="com.example.provider.permission.READ_ARTICLES"
    android:protectionLevel="normal" />



<provider android:name=".MyContentProvider"
    android:exported="false"
    android:authorities="com.example.provider"
    android:permission="com.example.provider.permission.READ_ARTICLES"
/>



<uses-permission
    android:name="com.example.provider.permission.READ_ARTICLES" />
●
    Overall structure
●
    Interaction with Content Provider
●
    Constructing query
●
    Retreiving cursor asyncronuously
●
    Provider permissions
●
    Creating Content Provider
●
    Questions
Creating content provider
public class MyContentProvider extends ContentProvider {
...


onCreate()
query()
insert()
update()
delete()
getType()
URI matching


content://com.example.provider/articles
content://com.example.provider/articles/*
content://com.example.provider/articles/#
URI matching


content://com.example.provider/articles
content://com.example.provider/articles/*
content://com.example.provider/articles/#
URI matching


content://com.example.provider/articles
content://com.example.provider/articles/*
content://com.example.provider/articles/#
URI matching
sUriMatcher.addURI("com.example.provider", "articles/#", 0);

sUriMatcher.addURI("com.example.provider", "articles/today", 1);

sUriMatcher.addURI("com.example.provider", "articles/history/*", 2);

...


public String getType(Uri uri) {
    switch (sUriMatcher.match(uri)) {
...
URI matching
sUriMatcher.addURI("com.example.provider", "articles/#", 0);

sUriMatcher.addURI("com.example.provider", "articles/today", 1);

sUriMatcher.addURI("com.example.provider", "articles/history/*", 2);

...


public String getType(Uri uri) {
    switch (sUriMatcher.match(uri)) {
...
MIME types
getType()

vnd.android.cursor.dir/vnd.com.example.provider.article

vnd.android.cursor.item/vnd.com.example.provider.article



getStreamTypes()

{ "image/jpeg", "image/png", "image/gif" }
MIME types
getType()

vnd.android.cursor.dir/vnd.com.example.provider.article

vnd.android.cursor.item/vnd.com.example.provider.article



getStreamTypes()

{ "image/jpeg", "image/png", "image/gif" }
Questions



Thank you!
Useful links
http://developer.android.com/guide/topics/providers/content-provider-basics.html

http://developer.android.com/guide/topics/providers/content-provider-creating.html

http://developer.android.com/guide/topics/security/permissions.html

http://gdg.org.ua

http://dnipro.gdg.org.ua
About speaker
 Alexey Ustenko — Android developer
 Coordniator of GDG Dnipropetrovs'k




 @ustav

Content providers in Android

  • 1.
  • 2.
    Overall structure ● Interaction with Content Provider ● Constructing query ● Retreiving cursor asyncronuously ● Provider permissions ● Creating Content Provider ● Questions
  • 3.
    Overall structure ● Interaction with Content Provider ● Constructing query ● Retreiving cursor asyncronuously ● Provider permissions ● Creating Content Provider ● Questions
  • 4.
    Overall structure Application #2 Application #1 Activity #1 Activity #1 Activity #2 Content Provider Application #3 Activity #3 Activity #1 Activity #2 Remote Database Files XML … connection
  • 5.
    Content Provider isa source Application #2 Application #1 Activity #1 Activity #1 Activity #2 Content Provider Application #3 Activity #3 Activity #1 Activity #2 Remote Database Files XML … connection
  • 6.
    For some consumers Application #2 Application #1 Activity #1 Activity #1 Activity #2 Content Provider Application #3 Activity #3 Activity #1 Activity #2 Remote Database Files XML … connection
  • 7.
    Gives access tovariety types of data Application #2 Application #1 Activity #1 Activity #1 Activity #2 Content Provider Application #3 Activity #3 Activity #1 Activity #2 Remote Database Files XML … connection
  • 8.
    Overall structure Application #2 Application #1 Activity #1 Activity #1 Activity #2 Content Provider Application #3 Activity #3 Activity #1 Activity #2 Remote Database Files XML … connection
  • 9.
    Overall structure ● Interaction with Content Provider ● Constructing query ● Retreiving cursor asyncronuously ● Provider permissions ● Creating Content Provider ● Questions
  • 10.
    Interaction with ContentProvider Application #2 Application #1 Activity #1 Activity #1 Activity #2 Content Provider Application #3 Activity #3 Activity #1 Activity #2 Remote Database Files XML … connection
  • 11.
    Activity to ContentProvider access Activity Cursor ContentResolver Content Provider CursorAdapter ListView
  • 12.
    Activity Activity Cursor ContentResolver Content Provider CursorAdapter ListView
  • 13.
    Performing request Content Provider Query Insert ContentResolver URI Update Delete
  • 14.
  • 15.
    Overall structure ● Interaction with Content Provider ● Constructing query ● Retreiving cursor asyncronuously ● Provider permissions ● Creating Content Provider ● Questions
  • 16.
    Constructing query SELECT _id,title, content, date FROM articles WHERE date >= 1352470000 ORDER BY date ASC
  • 17.
    Constructing query String[] mProjection= { "_id", "title", "content", "date", }; String mSelection = "date >= ?"; String[] mSelectionArgs = {"1352470000"}; String mSortOrder = "date ASC"; Cursor cursor = getContentResolver().query( MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder);
  • 18.
    Constructing query String[] mProjection= { "_id", "title", "content", "date", }; String mSelection = "date >= ?"; String[] mSelectionArgs = {"1352470000"}; String mSortOrder = "date ASC"; Cursor cursor = getContentResolver().query( MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder);
  • 19.
    Constructing query String[] mProjection= { "_id", "title", "content", "date", }; String mSelection = "date >= ?"; String[] mSelectionArgs = {"1352470000"}; String mSortOrder = "date ASC"; Cursor cursor = getContentResolver().query( MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder);
  • 20.
    Constructing query String[] mProjection= { "_id", "title", "content", "date", }; String mSelection = "date >= ?"; String[] mSelectionArgs = {"1352470000"}; String mSortOrder = "date ASC"; Cursor cursor = getContentResolver().query( MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder);
  • 21.
    Constructing query String[] mProjection= { "_id", "title", "content", "date", }; String mSelection = "date >= ?"; String[] mSelectionArgs = {"1352470000"}; String mSortOrder = "date ASC"; Cursor cursor = getContentResolver().query( MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder);
  • 22.
    Constructing query String[] mProjection= { "_id", "title", "content", "date", }; String mSelection = "date >= ?"; String[] mSelectionArgs = {"1352470000"}; String mSortOrder = "date ASC"; Cursor cursor = getContentResolver().query( MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder);
  • 23.
    Cursor _id title content date 1 First article Lorem ipsum... 1352475013 2 Second article Dolor sit amet... 1352471413 ... ... ... ... if (mCursor != null) { while (mCursor.moveToNext()) { String title = mCursor.getString(Columns.TITLE); } }
  • 24.
    Overall structure ● Interaction with Content Provider ● Constructing query ● Retreiving cursor asyncronuously ● Provider permissions ● Creating Content Provider ● Questions
  • 25.
    Activity & blockingqueries Activity Cursor ContentResolver Content Provider CursorAdapter ListView
  • 26.
    Activity & nonblocking queries Activity CursorLoader Cursor ContentResolver Content Provider AsyncQueryHandler CursorAdapter ListView
  • 27.
    Activity & Loader Activity CursorLoader Cursor ContentResolver Content Provider AsyncQueryHandler CursorAdapter ListView
  • 28.
    Activity & Loader publicclass ArticlesActivity extends FragmentActivity implements LoaderCallbacks<Cursor> { ... getSupportLoaderManager().initLoader(0, null, this); ... public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader( this, // context MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder); } public void onLoadFinished( Loader<Cursor> loader, Cursor cursor) { mAdapter.swapCursor(cursor); }
  • 29.
    Activity & Loader publicclass ArticlesActivity extends FragmentActivity implements LoaderCallbacks<Cursor> { ... getSupportLoaderManager().initLoader(0, null, this); ... public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader( this, // context MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder); } public void onLoadFinished( Loader<Cursor> loader, Cursor cursor) { mAdapter.swapCursor(cursor); }
  • 30.
    Activity & Loader publicclass ArticlesActivity extends FragmentActivity implements LoaderCallbacks<Cursor> { ... getSupportLoaderManager().initLoader(0, null, this); ... public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader( this, // context MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder); } public void onLoadFinished( Loader<Cursor> loader, Cursor cursor) { mAdapter.swapCursor(cursor); }
  • 31.
    Activity & Loader publicclass ArticlesActivity extends FragmentActivity implements LoaderCallbacks<Cursor> { ... getSupportLoaderManager().initLoader(0, null, this); ... public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader( this, // context MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder); } public void onLoadFinished( Loader<Cursor> loader, Cursor cursor) { mAdapter.swapCursor(cursor); }
  • 32.
    Activity & Loader publicclass ArticlesActivity extends FragmentActivity implements LoaderCallbacks<Cursor> { ... getSupportLoaderManager().initLoader(0, null, this); ... public Loader<Cursor> onCreateLoader(int id, Bundle args) { return new CursorLoader( this, // context MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder); } public void onLoadFinished( Loader<Cursor> loader, Cursor cursor) { mAdapter.swapCursor(cursor); }
  • 33.
    Activity & AsyncQueryHandler Activity CursorLoader Cursor ContentResolver Content Provider AsyncQueryHandler CursorAdapter ListView
  • 34.
    Activity & AsyncQueryHandler privateAsyncQueryHandler mHandler; ... mHandler = new MyAsyncQueryHandler(getContentResolver()); mHandler.startQuery( 0, // token null, // cookie MyContentProvider.ARTICLES_CONTENT_URI, mProjection, mSelection, mSelectionArgs, mSortOrder);
  • 35.
    Activity & AsyncQueryHandler classMyAsyncQueryHandler extends AsyncQueryHandler { public MyAsyncQueryHandler(ContentResolver cr) { super(cr); } @Override protected void onQueryComplete( int token, Object cookie, Cursor cursor) { mAdapter.swapCursor(cursor); } }
  • 36.
    Overall structure ● Interaction with Content Provider ● Constructing query ● Retreiving cursor asyncronuously ● Provider permissions ● Creating Content Provider ● Questions
  • 37.
    Permissions <permission android:name="com.example.provider.permission.READ_ARTICLES" android:protectionLevel="normal" /> <provider android:name=".MyContentProvider" android:exported="false" android:authorities="com.example.provider" android:permission="com.example.provider.permission.READ_ARTICLES" /> <uses-permission android:name="com.example.provider.permission.READ_ARTICLES" />
  • 38.
    Permissions <permission android:name="com.example.provider.permission.READ_ARTICLES" android:protectionLevel="normal" /> <provider android:name=".MyContentProvider" android:exported="false" android:authorities="com.example.provider" android:permission="com.example.provider.permission.READ_ARTICLES" /> <uses-permission android:name="com.example.provider.permission.READ_ARTICLES" />
  • 39.
    Permissions <permission android:name="com.example.provider.permission.READ_ARTICLES" android:protectionLevel="normal" /> <provider android:name=".MyContentProvider" android:exported="false" android:authorities="com.example.provider" android:permission="com.example.provider.permission.READ_ARTICLES" /> <uses-permission android:name="com.example.provider.permission.READ_ARTICLES" />
  • 40.
    Overall structure ● Interaction with Content Provider ● Constructing query ● Retreiving cursor asyncronuously ● Provider permissions ● Creating Content Provider ● Questions
  • 41.
    Creating content provider publicclass MyContentProvider extends ContentProvider { ... onCreate() query() insert() update() delete() getType()
  • 42.
  • 43.
  • 44.
  • 45.
    URI matching sUriMatcher.addURI("com.example.provider", "articles/#",0); sUriMatcher.addURI("com.example.provider", "articles/today", 1); sUriMatcher.addURI("com.example.provider", "articles/history/*", 2); ... public String getType(Uri uri) { switch (sUriMatcher.match(uri)) { ...
  • 46.
    URI matching sUriMatcher.addURI("com.example.provider", "articles/#",0); sUriMatcher.addURI("com.example.provider", "articles/today", 1); sUriMatcher.addURI("com.example.provider", "articles/history/*", 2); ... public String getType(Uri uri) { switch (sUriMatcher.match(uri)) { ...
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
    About speaker AlexeyUstenko — Android developer Coordniator of GDG Dnipropetrovs'k @ustav