Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
anbox
提交
90846984
A
anbox
项目概览
openeuler
/
anbox
通知
24
Star
1
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
anbox
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
90846984
编写于
12月 13, 2016
作者:
S
Simon Fels
提交者:
GitHub
12月 13, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #17 from morphis/app-view
Implement simple application view
上级
43513ab4
9ed4dd2b
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
1113 addition
and
2 deletion
+1113
-2
android/appmgr/AndroidManifest.xml
android/appmgr/AndroidManifest.xml
+6
-2
android/appmgr/res/layout/app_view.xml
android/appmgr/res/layout/app_view.xml
+17
-0
android/appmgr/res/layout/list_item_icon_text.xml
android/appmgr/res/layout/list_item_icon_text.xml
+38
-0
android/appmgr/res/values/dimens.xml
android/appmgr/res/values/dimens.xml
+5
-0
android/appmgr/src/org/anbox/appmgr/AppListAdapter.java
android/appmgr/src/org/anbox/appmgr/AppListAdapter.java
+89
-0
android/appmgr/src/org/anbox/appmgr/AppListFragment.java
android/appmgr/src/org/anbox/appmgr/AppListFragment.java
+74
-0
android/appmgr/src/org/anbox/appmgr/AppModel.java
android/appmgr/src/org/anbox/appmgr/AppModel.java
+101
-0
android/appmgr/src/org/anbox/appmgr/AppViewActivity.java
android/appmgr/src/org/anbox/appmgr/AppViewActivity.java
+41
-0
android/appmgr/src/org/anbox/appmgr/AppsGridFragment.java
android/appmgr/src/org/anbox/appmgr/AppsGridFragment.java
+90
-0
android/appmgr/src/org/anbox/appmgr/AppsLoader.java
android/appmgr/src/org/anbox/appmgr/AppsLoader.java
+184
-0
android/appmgr/src/org/anbox/appmgr/GridFragment.java
android/appmgr/src/org/anbox/appmgr/GridFragment.java
+399
-0
android/appmgr/src/org/anbox/appmgr/PackageIntentReceiver.java
...id/appmgr/src/org/anbox/appmgr/PackageIntentReceiver.java
+62
-0
setup/gui/anbox.desktop
setup/gui/anbox.desktop
+7
-0
未找到文件。
android/appmgr/AndroidManifest.xml
浏览文件 @
90846984
...
...
@@ -6,14 +6,18 @@
<application
android:name=
"org.anbox.appmgr.MainApplication"
>
<activity
android:name=
".LauncherActivity"
android:launchMode=
"singleTask"
>
android:name=
".LauncherActivity"
>
<intent-filter>
<action
android:name=
"android.intent.action.MAIN"
/>
<category
android:name=
"android.intent.category.HOME"
/>
<category
android:name=
"android.intent.category.DEFAULT"
/>
</intent-filter>
</activity>
<activity
android:name=
".AppViewActivity"
android:label=
"@string/app_name"
android:excludeFromRecents=
"true"
>
</activity>
<service
android:name=
".LauncherService"
android:exported=
"false"
>
...
...
android/appmgr/res/layout/app_view.xml
0 → 100644
浏览文件 @
90846984
<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:paddingLeft=
"@dimen/activity_horizontal_margin"
android:paddingRight=
"@dimen/activity_horizontal_margin"
android:paddingTop=
"@dimen/activity_vertical_margin"
android:paddingBottom=
"@dimen/activity_vertical_margin"
tools:context=
".AppViewActivity"
>
<fragment
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:name=
"org.anbox.appmgr.AppsGridFragment"
android:id=
"@+id/apps_grid"
/>
</RelativeLayout>
android/appmgr/res/layout/list_item_icon_text.xml
0 → 100644
浏览文件 @
90846984
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2007 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:orientation=
"vertical"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<ImageView
android:id=
"@+id/icon"
android:layout_width=
"48dp"
android:layout_height=
"48dp"
android:layout_gravity=
"center_horizontal"
/>
<TextView
android:id=
"@+id/text"
android:layout_gravity=
"center_horizontal"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:singleLine=
"true"
android:gravity=
"center"
android:textColor=
"@android:color/black"
android:textSize=
"14sp"
/>
</LinearLayout>
android/appmgr/res/values/dimens.xml
0 → 100644
浏览文件 @
90846984
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen
name=
"activity_horizontal_margin"
>
16dp
</dimen>
<dimen
name=
"activity_vertical_margin"
>
16dp
</dimen>
</resources>
android/appmgr/src/org/anbox/appmgr/AppListAdapter.java
0 → 100644
浏览文件 @
90846984
/*
* The MIT License (MIT)
*
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package
org.anbox.appmgr
;
import
android.annotation.TargetApi
;
import
android.content.Context
;
import
android.os.Build
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.ArrayAdapter
;
import
android.widget.ImageView
;
import
android.widget.TextView
;
import
java.util.ArrayList
;
import
java.util.Collection
;
/**
* Created by Arnab Chakraborty
*/
public
class
AppListAdapter
extends
ArrayAdapter
<
AppModel
>
{
private
final
LayoutInflater
mInflater
;
public
AppListAdapter
(
Context
context
)
{
super
(
context
,
android
.
R
.
layout
.
simple_list_item_2
);
mInflater
=
LayoutInflater
.
from
(
context
);
}
public
void
setData
(
ArrayList
<
AppModel
>
data
)
{
clear
();
if
(
data
!=
null
)
{
addAll
(
data
);
}
}
@Override
@TargetApi
(
Build
.
VERSION_CODES
.
HONEYCOMB
)
public
void
addAll
(
Collection
<?
extends
AppModel
>
items
)
{
//If the platform supports it, use addAll, otherwise add in loop
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
HONEYCOMB
)
{
super
.
addAll
(
items
);
}
else
{
for
(
AppModel
item:
items
){
super
.
add
(
item
);
}
}
}
/**
* Populate new items in the list.
*/
@Override
public
View
getView
(
int
position
,
View
convertView
,
ViewGroup
parent
)
{
View
view
;
if
(
convertView
==
null
)
{
view
=
mInflater
.
inflate
(
R
.
layout
.
list_item_icon_text
,
parent
,
false
);
}
else
{
view
=
convertView
;
}
AppModel
item
=
getItem
(
position
);
((
ImageView
)
view
.
findViewById
(
R
.
id
.
icon
)).
setImageDrawable
(
item
.
getIcon
());
((
TextView
)
view
.
findViewById
(
R
.
id
.
text
)).
setText
(
item
.
getLabel
());
return
view
;
}
}
android/appmgr/src/org/anbox/appmgr/AppListFragment.java
0 → 100644
浏览文件 @
90846984
/*
* The MIT License (MIT)
*
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package
org.anbox.appmgr
;
import
android.os.Bundle
;
import
android.support.v4.app.ListFragment
;
import
android.support.v4.app.LoaderManager
;
import
android.support.v4.content.Loader
;
import
java.util.ArrayList
;
/**
* Created by Arnab Chakraborty
*/
public
class
AppListFragment
extends
ListFragment
implements
LoaderManager
.
LoaderCallbacks
<
ArrayList
<
AppModel
>>
{
AppListAdapter
mAdapter
;
@Override
public
void
onActivityCreated
(
Bundle
savedInstanceState
)
{
super
.
onActivityCreated
(
savedInstanceState
);
setEmptyText
(
"No Applications"
);
mAdapter
=
new
AppListAdapter
(
getActivity
());
setListAdapter
(
mAdapter
);
// till the data is loaded display a spinner
setListShown
(
false
);
// create the loader to load the apps list in background
getLoaderManager
().
initLoader
(
0
,
null
,
this
);
}
@Override
public
Loader
<
ArrayList
<
AppModel
>>
onCreateLoader
(
int
id
,
Bundle
bundle
)
{
return
new
AppsLoader
(
getActivity
());
}
@Override
public
void
onLoadFinished
(
Loader
<
ArrayList
<
AppModel
>>
loader
,
ArrayList
<
AppModel
>
apps
)
{
mAdapter
.
setData
(
apps
);
if
(
isResumed
())
{
setListShown
(
true
);
}
else
{
setListShownNoAnimation
(
true
);
}
}
@Override
public
void
onLoaderReset
(
Loader
<
ArrayList
<
AppModel
>>
loader
)
{
mAdapter
.
setData
(
null
);
}
}
android/appmgr/src/org/anbox/appmgr/AppModel.java
0 → 100644
浏览文件 @
90846984
/*
* The MIT License (MIT)
*
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package
org.anbox.appmgr
;
import
android.content.Context
;
import
android.content.pm.ApplicationInfo
;
import
android.graphics.drawable.Drawable
;
import
java.io.File
;
/**
* @credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html
*/
public
class
AppModel
{
private
final
Context
mContext
;
private
final
ApplicationInfo
mInfo
;
private
String
mAppLabel
;
private
Drawable
mIcon
;
private
boolean
mMounted
;
private
final
File
mApkFile
;
public
AppModel
(
Context
context
,
ApplicationInfo
info
)
{
mContext
=
context
;
mInfo
=
info
;
mApkFile
=
new
File
(
info
.
sourceDir
);
}
public
ApplicationInfo
getAppInfo
()
{
return
mInfo
;
}
public
String
getApplicationPackageName
()
{
return
getAppInfo
().
packageName
;
}
public
String
getLabel
()
{
return
mAppLabel
;
}
public
Drawable
getIcon
()
{
if
(
mIcon
==
null
)
{
if
(
mApkFile
.
exists
())
{
mIcon
=
mInfo
.
loadIcon
(
mContext
.
getPackageManager
());
return
mIcon
;
}
else
{
mMounted
=
false
;
}
}
else
if
(!
mMounted
)
{
// If the app wasn't mounted but is now mounted, reload
// its icon.
if
(
mApkFile
.
exists
())
{
mMounted
=
true
;
mIcon
=
mInfo
.
loadIcon
(
mContext
.
getPackageManager
());
return
mIcon
;
}
}
else
{
return
mIcon
;
}
return
mContext
.
getResources
().
getDrawable
(
android
.
R
.
drawable
.
sym_def_app_icon
);
}
void
loadLabel
(
Context
context
)
{
if
(
mAppLabel
==
null
||
!
mMounted
)
{
if
(!
mApkFile
.
exists
())
{
mMounted
=
false
;
mAppLabel
=
mInfo
.
packageName
;
}
else
{
mMounted
=
true
;
CharSequence
label
=
mInfo
.
loadLabel
(
context
.
getPackageManager
());
mAppLabel
=
label
!=
null
?
label
.
toString
()
:
mInfo
.
packageName
;
}
}
}
}
android/appmgr/src/org/anbox/appmgr/AppViewActivity.java
0 → 100644
浏览文件 @
90846984
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package
org.anbox.appmgr
;
import
android.os.Bundle
;
import
android.util.Log
;
import
android.support.v4.app.FragmentActivity
;
public
final
class
AppViewActivity
extends
FragmentActivity
{
private
static
final
String
TAG
=
"AnboxAppView"
;
@Override
public
void
onCreate
(
Bundle
info
)
{
super
.
onCreate
(
info
);
setContentView
(
R
.
layout
.
app_view
);
Log
.
i
(
TAG
,
"Created application view activity"
);
}
@Override
public
void
onDestroy
()
{
Log
.
i
(
TAG
,
"Destroying application view activity"
);
super
.
onDestroy
();
}
}
android/appmgr/src/org/anbox/appmgr/AppsGridFragment.java
0 → 100644
浏览文件 @
90846984
/*
* The MIT License (MIT)
*
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package
org.anbox.appmgr
;
import
android.content.Intent
;
import
android.os.Bundle
;
import
android.support.v4.app.LoaderManager
;
import
android.support.v4.content.Loader
;
import
android.view.View
;
import
android.widget.GridView
;
import
java.util.ArrayList
;
/**
* Created by Arnab Chakraborty
*/
public
class
AppsGridFragment
extends
GridFragment
implements
LoaderManager
.
LoaderCallbacks
<
ArrayList
<
AppModel
>>
{
AppListAdapter
mAdapter
;
@Override
public
void
onActivityCreated
(
Bundle
savedInstanceState
)
{
super
.
onActivityCreated
(
savedInstanceState
);
setEmptyText
(
"No Applications"
);
mAdapter
=
new
AppListAdapter
(
getActivity
());
setGridAdapter
(
mAdapter
);
// till the data is loaded display a spinner
setGridShown
(
false
);
// create the loader to load the apps list in background
getLoaderManager
().
initLoader
(
0
,
null
,
this
);
}
@Override
public
Loader
<
ArrayList
<
AppModel
>>
onCreateLoader
(
int
id
,
Bundle
bundle
)
{
return
new
AppsLoader
(
getActivity
());
}
@Override
public
void
onLoadFinished
(
Loader
<
ArrayList
<
AppModel
>>
loader
,
ArrayList
<
AppModel
>
apps
)
{
mAdapter
.
setData
(
apps
);
if
(
isResumed
())
{
setGridShown
(
true
);
}
else
{
setGridShownNoAnimation
(
true
);
}
}
@Override
public
void
onLoaderReset
(
Loader
<
ArrayList
<
AppModel
>>
loader
)
{
mAdapter
.
setData
(
null
);
}
@Override
public
void
onGridItemClick
(
GridView
g
,
View
v
,
int
position
,
long
id
)
{
AppModel
app
=
(
AppModel
)
getGridAdapter
().
getItem
(
position
);
if
(
app
!=
null
)
{
Intent
intent
=
getActivity
().
getPackageManager
().
getLaunchIntentForPackage
(
app
.
getApplicationPackageName
());
if
(
intent
!=
null
)
{
startActivity
(
intent
);
}
}
}
}
android/appmgr/src/org/anbox/appmgr/AppsLoader.java
0 → 100644
浏览文件 @
90846984
/*
* The MIT License (MIT)
*
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package
org.anbox.appmgr
;
import
android.content.Context
;
import
android.content.pm.ApplicationInfo
;
import
android.content.pm.PackageManager
;
import
android.support.v4.content.AsyncTaskLoader
;
import
java.text.Collator
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Comparator
;
/**
* @credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html
*/
public
class
AppsLoader
extends
AsyncTaskLoader
<
ArrayList
<
AppModel
>>
{
ArrayList
<
AppModel
>
mInstalledApps
;
final
PackageManager
mPm
;
PackageIntentReceiver
mPackageObserver
;
public
AppsLoader
(
Context
context
)
{
super
(
context
);
mPm
=
context
.
getPackageManager
();
}
@Override
public
ArrayList
<
AppModel
>
loadInBackground
()
{
// retrieve the list of installed applications
List
<
ApplicationInfo
>
apps
=
mPm
.
getInstalledApplications
(
0
);
if
(
apps
==
null
)
{
apps
=
new
ArrayList
<
ApplicationInfo
>();
}
final
Context
context
=
getContext
();
// create corresponding apps and load their labels
ArrayList
<
AppModel
>
items
=
new
ArrayList
<
AppModel
>(
apps
.
size
());
for
(
int
i
=
0
;
i
<
apps
.
size
();
i
++)
{
String
pkg
=
apps
.
get
(
i
).
packageName
;
// only apps which are launchable
if
(
context
.
getPackageManager
().
getLaunchIntentForPackage
(
pkg
)
!=
null
)
{
AppModel
app
=
new
AppModel
(
context
,
apps
.
get
(
i
));
app
.
loadLabel
(
context
);
items
.
add
(
app
);
}
}
// sort the list
Collections
.
sort
(
items
,
ALPHA_COMPARATOR
);
return
items
;
}
@Override
public
void
deliverResult
(
ArrayList
<
AppModel
>
apps
)
{
if
(
isReset
())
{
// An async query came in while the loader is stopped. We
// don't need the result.
if
(
apps
!=
null
)
{
onReleaseResources
(
apps
);
}
}
ArrayList
<
AppModel
>
oldApps
=
apps
;
mInstalledApps
=
apps
;
if
(
isStarted
())
{
// If the Loader is currently started, we can immediately
// deliver its results.
super
.
deliverResult
(
apps
);
}
// At this point we can release the resources associated with
// 'oldApps' if needed; now that the new result is delivered we
// know that it is no longer in use.
if
(
oldApps
!=
null
)
{
onReleaseResources
(
oldApps
);
}
}
@Override
protected
void
onStartLoading
()
{
if
(
mInstalledApps
!=
null
)
{
// If we currently have a result available, deliver it
// immediately.
deliverResult
(
mInstalledApps
);
}
// watch for changes in app install and uninstall operation
if
(
mPackageObserver
==
null
)
{
mPackageObserver
=
new
PackageIntentReceiver
(
this
);
}
if
(
takeContentChanged
()
||
mInstalledApps
==
null
)
{
// If the data has changed since the last time it was loaded
// or is not currently available, start a load.
forceLoad
();
}
}
@Override
protected
void
onStopLoading
()
{
// Attempt to cancel the current load task if possible.
cancelLoad
();
}
@Override
public
void
onCanceled
(
ArrayList
<
AppModel
>
apps
)
{
super
.
onCanceled
(
apps
);
// At this point we can release the resources associated with 'apps'
// if needed.
onReleaseResources
(
apps
);
}
@Override
protected
void
onReset
()
{
// Ensure the loader is stopped
onStopLoading
();
// At this point we can release the resources associated with 'apps'
// if needed.
if
(
mInstalledApps
!=
null
)
{
onReleaseResources
(
mInstalledApps
);
mInstalledApps
=
null
;
}
// Stop monitoring for changes.
if
(
mPackageObserver
!=
null
)
{
getContext
().
unregisterReceiver
(
mPackageObserver
);
mPackageObserver
=
null
;
}
}
/**
* Helper method to do the cleanup work if needed, for example if we're
* using Cursor, then we should be closing it here
*
* @param apps
*/
protected
void
onReleaseResources
(
ArrayList
<
AppModel
>
apps
)
{
// do nothing
}
/**
* Perform alphabetical comparison of application entry objects.
*/
public
static
final
Comparator
<
AppModel
>
ALPHA_COMPARATOR
=
new
Comparator
<
AppModel
>()
{
private
final
Collator
sCollator
=
Collator
.
getInstance
();
@Override
public
int
compare
(
AppModel
object1
,
AppModel
object2
)
{
return
sCollator
.
compare
(
object1
.
getLabel
(),
object2
.
getLabel
());
}
};
}
android/appmgr/src/org/anbox/appmgr/GridFragment.java
0 → 100644
浏览文件 @
90846984
package
org.anbox.appmgr
;
/*
* Created by Thomas Barrasso on 9/11/12.
* Copyright (c) 2012 Loupe Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import
android.content.Context
;
import
android.content.res.Resources
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.os.Handler
;
import
android.support.v4.app.Fragment
;
import
android.util.TypedValue
;
import
android.view.Gravity
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.view.animation.AnimationUtils
;
import
android.widget.AdapterView
;
import
android.widget.FrameLayout
;
import
android.widget.GridView
;
import
android.widget.LinearLayout
;
import
android.widget.ListAdapter
;
import
android.widget.ListView
;
import
android.widget.ProgressBar
;
import
android.widget.TextView
;
/**
* Based on {@link android.app.ListFragment} but adapted for {@link GridView}.
*/
public
class
GridFragment
extends
Fragment
{
static
final
int
INTERNAL_EMPTY_ID
=
0x00ff0001
;
static
final
int
INTERNAL_PROGRESS_CONTAINER_ID
=
0x00ff0002
;
static
final
int
INTERNAL_LIST_CONTAINER_ID
=
0x00ff0003
;
final
private
Handler
mHandler
=
new
Handler
();
final
private
Runnable
mRequestFocus
=
new
Runnable
()
{
public
void
run
()
{
mGrid
.
focusableViewAvailable
(
mGrid
);
}
};
final
private
AdapterView
.
OnItemClickListener
mOnClickListener
=
new
AdapterView
.
OnItemClickListener
()
{
public
void
onItemClick
(
AdapterView
<?>
parent
,
View
v
,
int
position
,
long
id
)
{
onGridItemClick
((
GridView
)
parent
,
v
,
position
,
id
);
}
};
ListAdapter
mAdapter
;
GridView
mGrid
;
View
mEmptyView
;
TextView
mStandardEmptyView
;
View
mProgressContainer
;
View
mGridContainer
;
CharSequence
mEmptyText
;
boolean
mGridShown
;
public
GridFragment
()
{
}
/**
* Provide default implementation to return a simple grid view. Subclasses
* can override to replace with their own layout. If doing so, the
* returned view hierarchy <em>must</em> have a GridView whose id
* is {@link android.R.id#list android.R.id.list} and can optionally
* have a sibling view id {@link android.R.id#empty android.R.id.empty}
* that is to be shown when the grid is empty.
*
* <p>If you are overriding this method with your own custom content,
* consider including the standard layout {@link android.R.layout#list_content}
* in your layout file, so that you continue to retain all of the standard
* behavior of ListFragment. In particular, this is currently the only
* way to have the built-in indeterminant progress state be shown.
*/
@Override
public
View
onCreateView
(
LayoutInflater
inflater
,
ViewGroup
container
,
Bundle
savedInstanceState
)
{
final
Context
context
=
getActivity
();
FrameLayout
root
=
new
FrameLayout
(
context
);
// ------------------------------------------------------------------
LinearLayout
pframe
=
new
LinearLayout
(
context
);
pframe
.
setId
(
INTERNAL_PROGRESS_CONTAINER_ID
);
pframe
.
setOrientation
(
LinearLayout
.
VERTICAL
);
pframe
.
setVisibility
(
View
.
GONE
);
pframe
.
setGravity
(
Gravity
.
CENTER
);
ProgressBar
progress
=
new
ProgressBar
(
context
,
null
,
android
.
R
.
attr
.
progressBarStyleLarge
);
pframe
.
addView
(
progress
,
new
FrameLayout
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
));
root
.
addView
(
pframe
,
new
FrameLayout
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
));
// ------------------------------------------------------------------
FrameLayout
lframe
=
new
FrameLayout
(
context
);
lframe
.
setId
(
INTERNAL_LIST_CONTAINER_ID
);
TextView
tv
=
new
TextView
(
getActivity
());
tv
.
setId
(
INTERNAL_EMPTY_ID
);
tv
.
setGravity
(
Gravity
.
CENTER
);
lframe
.
addView
(
tv
,
new
FrameLayout
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
));
GridView
lv
=
new
GridView
(
getActivity
());
lv
.
setId
(
android
.
R
.
id
.
list
);
lv
.
setDrawSelectorOnTop
(
false
);
lv
.
setColumnWidth
(
convertDpToPixels
(
60
,
getActivity
()));
lv
.
setStretchMode
(
GridView
.
STRETCH_COLUMN_WIDTH
);
lv
.
setNumColumns
(
GridView
.
AUTO_FIT
);
lv
.
setHorizontalSpacing
(
convertDpToPixels
(
20
,
getActivity
()));
lv
.
setVerticalSpacing
(
convertDpToPixels
(
20
,
getActivity
()));
lv
.
setSmoothScrollbarEnabled
(
true
);
// disable overscroll
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
GINGERBREAD
)
{
lv
.
setOverScrollMode
(
ListView
.
OVER_SCROLL_NEVER
);
}
lframe
.
addView
(
lv
,
new
FrameLayout
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
));
root
.
addView
(
lframe
,
new
FrameLayout
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
));
// ------------------------------------------------------------------
root
.
setLayoutParams
(
new
FrameLayout
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
MATCH_PARENT
));
return
root
;
}
/**
* Attach to grid view once the view hierarchy has been created.
*/
@Override
public
void
onViewCreated
(
View
view
,
Bundle
savedInstanceState
)
{
super
.
onViewCreated
(
view
,
savedInstanceState
);
ensureGrid
();
}
/**
* Detach from {@link GridView}
*/
@Override
public
void
onDestroyView
()
{
mHandler
.
removeCallbacks
(
mRequestFocus
);
mGrid
=
null
;
mGridShown
=
false
;
mEmptyView
=
mProgressContainer
=
mGridContainer
=
null
;
mStandardEmptyView
=
null
;
super
.
onDestroyView
();
}
public
static
int
convertDpToPixels
(
float
dp
,
Context
context
){
Resources
resources
=
context
.
getResources
();
return
(
int
)
TypedValue
.
applyDimension
(
TypedValue
.
COMPLEX_UNIT_DIP
,
dp
,
resources
.
getDisplayMetrics
()
);
}
/**
* This method will be called when an item in the grid is selected.
* Subclasses should override. Subclasses can call
* getGridView().getItemAtPosition(position) if they need to access the
* data associated with the selected item.
*
* @param g The {@link GridView} where the click happened
* @param v The view that was clicked within the {@link GridView}
* @param position The position of the view in the grid
* @param id The row id of the item that was clicked
*/
public
void
onGridItemClick
(
GridView
g
,
View
v
,
int
position
,
long
id
)
{
}
/**
* Provide the cursor for the {@link GridView}.
*/
public
void
setGridAdapter
(
ListAdapter
adapter
)
{
final
boolean
hadAdapter
=
(
mAdapter
!=
null
);
mAdapter
=
adapter
;
if
(
mGrid
!=
null
)
{
mGrid
.
setAdapter
(
adapter
);
if
(!
mGridShown
&&
!
hadAdapter
)
{
// The grid was hidden, and previously didn't have an
// adapter. It is now time to show it.
setGridShown
(
true
,
(
getView
().
getWindowToken
()
!=
null
));
}
}
}
/**
* Set the currently selected grid item to the specified
* position with the adapter's data
*
* @param position
*/
public
void
setSelection
(
int
position
)
{
ensureGrid
();
mGrid
.
setSelection
(
position
);
}
/**
* Get the position of the currently selected grid item.
*/
public
int
getSelectedItemPosition
()
{
ensureGrid
();
return
mGrid
.
getSelectedItemPosition
();
}
/**
* Get the cursor row ID of the currently selected grid item.
*/
public
long
getSelectedItemId
()
{
ensureGrid
();
return
mGrid
.
getSelectedItemId
();
}
/**
* Get the activity's {@link GridView} widget.
*/
public
GridView
getGridView
()
{
ensureGrid
();
return
mGrid
;
}
/**
* The default content for a ListFragment has a TextView that can
* be shown when the grid is empty. If you would like to have it
* shown, call this method to supply the text it should use.
*/
public
void
setEmptyText
(
CharSequence
text
)
{
ensureGrid
();
if
(
mStandardEmptyView
==
null
)
{
throw
new
IllegalStateException
(
"Can't be used with a custom content view"
);
}
mStandardEmptyView
.
setText
(
text
);
if
(
mEmptyText
==
null
)
{
mGrid
.
setEmptyView
(
mStandardEmptyView
);
}
mEmptyText
=
text
;
}
/**
* Control whether the grid is being displayed. You can make it not
* displayed if you are waiting for the initial data to show in it. During
* this time an indeterminant progress indicator will be shown instead.
*
* <p>Applications do not normally need to use this themselves. The default
* behavior of ListFragment is to start with the grid not being shown, only
* showing it once an adapter is given with {@link #setGridAdapter(ListAdapter)}.
* If the grid at that point had not been shown, when it does get shown
* it will be do without the user ever seeing the hidden state.
*
* @param shown If true, the grid view is shown; if false, the progress
* indicator. The initial value is true.
*/
public
void
setGridShown
(
boolean
shown
)
{
setGridShown
(
shown
,
true
);
}
/**
* Like {@link #setGridShown(boolean)}, but no animation is used when
* transitioning from the previous state.
*/
public
void
setGridShownNoAnimation
(
boolean
shown
)
{
setGridShown
(
shown
,
false
);
}
/**
* Control whether the grid is being displayed. You can make it not
* displayed if you are waiting for the initial data to show in it. During
* this time an indeterminant progress indicator will be shown instead.
*
* @param shown If true, the grid view is shown; if false, the progress
* indicator. The initial value is true.
* @param animate If true, an animation will be used to transition to the
* new state.
*/
private
void
setGridShown
(
boolean
shown
,
boolean
animate
)
{
ensureGrid
();
if
(
mProgressContainer
==
null
)
{
throw
new
IllegalStateException
(
"Can't be used with a custom content view"
);
}
if
(
mGridShown
==
shown
)
{
return
;
}
mGridShown
=
shown
;
if
(
shown
)
{
if
(
animate
)
{
mProgressContainer
.
startAnimation
(
AnimationUtils
.
loadAnimation
(
getActivity
(),
android
.
R
.
anim
.
fade_out
));
mGridContainer
.
startAnimation
(
AnimationUtils
.
loadAnimation
(
getActivity
(),
android
.
R
.
anim
.
fade_in
));
}
else
{
mProgressContainer
.
clearAnimation
();
mGridContainer
.
clearAnimation
();
}
mProgressContainer
.
setVisibility
(
View
.
GONE
);
mGridContainer
.
setVisibility
(
View
.
VISIBLE
);
}
else
{
if
(
animate
)
{
mProgressContainer
.
startAnimation
(
AnimationUtils
.
loadAnimation
(
getActivity
(),
android
.
R
.
anim
.
fade_in
));
mGridContainer
.
startAnimation
(
AnimationUtils
.
loadAnimation
(
getActivity
(),
android
.
R
.
anim
.
fade_out
));
}
else
{
mProgressContainer
.
clearAnimation
();
mGridContainer
.
clearAnimation
();
}
mProgressContainer
.
setVisibility
(
View
.
VISIBLE
);
mGridContainer
.
setVisibility
(
View
.
GONE
);
}
}
/**
* Get the ListAdapter associated with this activity's {@link GridView}.
*/
public
ListAdapter
getGridAdapter
()
{
return
mAdapter
;
}
private
void
ensureGrid
()
{
if
(
mGrid
!=
null
)
{
return
;
}
View
root
=
getView
();
if
(
root
==
null
)
{
throw
new
IllegalStateException
(
"Content view not yet created"
);
}
if
(
root
instanceof
GridView
)
{
mGrid
=
(
GridView
)
root
;
}
else
{
mStandardEmptyView
=
(
TextView
)
root
.
findViewById
(
INTERNAL_EMPTY_ID
);
if
(
mStandardEmptyView
==
null
)
{
mEmptyView
=
root
.
findViewById
(
android
.
R
.
id
.
empty
);
}
else
{
mStandardEmptyView
.
setVisibility
(
View
.
GONE
);
}
mProgressContainer
=
root
.
findViewById
(
INTERNAL_PROGRESS_CONTAINER_ID
);
mGridContainer
=
root
.
findViewById
(
INTERNAL_LIST_CONTAINER_ID
);
View
rawGridView
=
root
.
findViewById
(
android
.
R
.
id
.
list
);
if
(!(
rawGridView
instanceof
GridView
))
{
if
(
rawGridView
==
null
)
{
throw
new
RuntimeException
(
"Your content must have a GridView whose id attribute is "
+
"'android.R.id.list'"
);
}
throw
new
RuntimeException
(
"Content has view with id attribute 'android.R.id.list' "
+
"that is not a GridView class"
);
}
mGrid
=
(
GridView
)
rawGridView
;
if
(
mEmptyView
!=
null
)
{
mGrid
.
setEmptyView
(
mEmptyView
);
}
else
if
(
mEmptyText
!=
null
)
{
mStandardEmptyView
.
setText
(
mEmptyText
);
mGrid
.
setEmptyView
(
mStandardEmptyView
);
}
}
mGridShown
=
true
;
mGrid
.
setOnItemClickListener
(
mOnClickListener
);
if
(
mAdapter
!=
null
)
{
ListAdapter
adapter
=
mAdapter
;
mAdapter
=
null
;
setGridAdapter
(
adapter
);
}
else
{
// We are starting without an adapter, so assume we won't
// have our data right away and start with the progress indicator.
if
(
mProgressContainer
!=
null
)
{
setGridShown
(
false
,
false
);
}
}
mHandler
.
post
(
mRequestFocus
);
}
}
android/appmgr/src/org/anbox/appmgr/PackageIntentReceiver.java
0 → 100644
浏览文件 @
90846984
/*
* The MIT License (MIT)
*
* Copyright 2016 Arnab Chakraborty. http://arnab.ch
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package
org.anbox.appmgr
;
import
android.content.BroadcastReceiver
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.IntentFilter
;
/**
* Helper class to look for interesting changes to the installed apps
* so that the loader can be updated.
*
* @Credit http://developer.android.com/reference/android/content/AsyncTaskLoader.html
*/
public
class
PackageIntentReceiver
extends
BroadcastReceiver
{
final
AppsLoader
mLoader
;
public
PackageIntentReceiver
(
AppsLoader
loader
)
{
mLoader
=
loader
;
IntentFilter
filter
=
new
IntentFilter
(
Intent
.
ACTION_PACKAGE_ADDED
);
filter
.
addAction
(
Intent
.
ACTION_PACKAGE_REMOVED
);
filter
.
addAction
(
Intent
.
ACTION_PACKAGE_CHANGED
);
filter
.
addDataScheme
(
"package"
);
mLoader
.
getContext
().
registerReceiver
(
this
,
filter
);
// Register for events related to sdcard installation.
IntentFilter
sdFilter
=
new
IntentFilter
();
sdFilter
.
addAction
(
Intent
.
ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
);
sdFilter
.
addAction
(
Intent
.
ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE
);
mLoader
.
getContext
().
registerReceiver
(
this
,
sdFilter
);
}
@Override
public
void
onReceive
(
Context
context
,
Intent
intent
)
{
// Tell the loader about the change.
mLoader
.
onContentChanged
();
}
}
setup/gui/anbox.desktop
0 → 100644
浏览文件 @
90846984
[Desktop Entry]
Name=Anbox
GenericName=Android in a box
Version=1.0
Type=Application
Exec=anbox launch --package=org.anbox.appmgr --component=org.anbox.appmgr.AppViewActivity
Terminal=false
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录